Пример #1
0
int main(int argc, char **argv)
{
  int     use_stdin = FALSE;
  int     use_stdout = FALSE;
  int     use_tcpip = FALSE;
  int     port = 88; // Useful default port number
  char   *input_name = NULL;
  char   *output_name = NULL;
  int     had_input_name = FALSE;
  int     had_output_name = FALSE;
  PS_reader_p ps = NULL;
  TS_writer_p output = NULL;
  int     verbose = FALSE;
  int     quiet = FALSE;
  int     max = 0;
  uint32_t pmt_pid = 0x66;
  uint32_t video_pid = 0x68;
  uint32_t pcr_pid = video_pid;  // Use PCRs from the video stream
  uint32_t audio_pid = 0x67;
  int     keep_audio = TRUE;
  int     repeat_program_every = 100;
  int     pad_start = 8;
  int     err = 0;
  int     ii = 1;

  int     video_type = VIDEO_H262;  // hopefully a sensible default
  int     force_stream_type = FALSE;

  int     video_stream = -1;
  int     audio_stream = -1;
  int     want_ac3_audio = FALSE;

  int     input_is_dvd = TRUE;
  int     want_dolby_as_dvb = TRUE;

  if (argc < 2)
  {
    print_usage();
    return 0;
  }

  while (ii < argc)
  {
    if (argv[ii][0] == '-')
    {
      if (!strcmp("--help",argv[ii]) || !strcmp("-help",argv[ii]) ||
          !strcmp("-h",argv[ii]))
      {
        print_usage();
        return 0;
      }
      else if (!strcmp("-avc",argv[ii]) || !strcmp("-h264",argv[ii]))
      {
        force_stream_type = TRUE;
        video_type = VIDEO_H264;
      }
      else if (!strcmp("-h262",argv[ii]))
      {
        force_stream_type = TRUE;
        video_type = VIDEO_H262;
      }
      else if (!strcmp("-vtype",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = int_value("ps2ts",argv[ii],argv[ii+1],TRUE,0,
                        &video_type);
        if (err) return 1;
        ii++;
        force_stream_type = TRUE;
      }
      else if (!strcmp("-mp42",argv[ii]))
      {
        force_stream_type = TRUE;
        video_type = VIDEO_MPEG4_PART2;
      }
      else if (!strcmp("-dolby",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        if (!strcmp("dvb",argv[ii+1]))
          want_dolby_as_dvb = TRUE;
        else if (!strcmp("atsc",argv[ii+1]))
          want_dolby_as_dvb = FALSE;
        else
        {
          print_err("### ps2ts: -dolby must be followed by dvb or atsc\n");
          return 1;
        }
        ii++;
      }
      else if (!strcmp("-stdin",argv[ii]))
      {
        had_input_name = TRUE; // more or less
        use_stdin = TRUE;
      }
      else if (!strcmp("-stdout",argv[ii]))
      {
        had_output_name = TRUE; // more or less
        use_stdout = TRUE;
        redirect_output_stderr();
      }
      else if (!strcmp("-err",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        if (!strcmp(argv[ii+1],"stderr"))
          redirect_output_stderr();
        else if (!strcmp(argv[ii+1],"stdout"))
          redirect_output_stdout();
        else
        {
          fprint_err("### ps2ts: "
                     "Unrecognised option '%s' to -err (not 'stdout' or"
                     " 'stderr')\n",argv[ii+1]);
          return 1;
        }
        ii++;
      }
      else if (!strcmp("-dvd",argv[ii]))
      {
        input_is_dvd = TRUE;
      }
      else if (!strcmp("-notdvd",argv[ii]) || !strcmp("-nodvd",argv[ii]))
      {
        input_is_dvd = FALSE;
      }
      else if (!strcmp("-host",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = host_value("ps2ts",argv[ii],argv[ii+1],&output_name,&port);
        if (err) return 1;
        had_output_name = TRUE; // more or less
        use_tcpip = TRUE;
        ii++;
      }
      else if (!strcmp("-verbose",argv[ii]) || !strcmp("-v",argv[ii]))
      {
        verbose = TRUE;
        quiet = FALSE;
      }
      else if (!strcmp("-quiet",argv[ii]) || !strcmp("-q",argv[ii]))
      {
        verbose = FALSE;
        quiet = TRUE;
      }
      else if (!strcmp("-max",argv[ii]) || !strcmp("-m",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = int_value("ps2ts",argv[ii],argv[ii+1],TRUE,10,&max);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-prepeat",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = int_value("ps2ts",argv[ii],argv[ii+1],TRUE,10,
                        &repeat_program_every);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-pad",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = int_value("ps2ts",argv[ii],argv[ii+1],TRUE,10,&pad_start);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-vpid",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = unsigned_value("ps2ts",argv[ii],argv[ii+1],0,&video_pid);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-apid",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = unsigned_value("ps2ts",argv[ii],argv[ii+1],0,&audio_pid);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-pmt",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = unsigned_value("ps2ts",argv[ii],argv[ii+1],0,&pmt_pid);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-noaudio",argv[ii]))
      {
        keep_audio = FALSE;
      }
      else if (!strcmp("-vstream",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = int_value_in_range("ps2ts",argv[ii],argv[ii+1],0,0xF,0,
                                 &video_stream);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-astream",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = int_value_in_range("ps2ts",argv[ii],argv[ii+1],0,0x1F,0,
                                 &audio_stream);
        if (err) return 1;
        want_ac3_audio = FALSE;
        ii++;
      }
      else if (!strcmp("-ac3stream",argv[ii]))
      {
        CHECKARG("ps2ts",ii);
        err = int_value_in_range("ps2ts",argv[ii],argv[ii+1],0,0x7,0,
                                 &audio_stream);
        if (err) return 1;
        want_ac3_audio = TRUE;
        input_is_dvd = TRUE;
        ii++;
      }
      else
      {
        fprint_err("### ps2ts: "
                   "Unrecognised command line switch '%s'\n",argv[ii]);
        return 1;
      }
    }
    else
    {
      if (had_input_name && had_output_name)
      {
        fprint_err("### ps2ts: Unexpected '%s'\n",argv[ii]);
        return 1;
      }
      else if (had_input_name)
      {
        output_name = argv[ii];
        had_output_name = TRUE;
      }
      else
      {
        input_name = argv[ii];
        had_input_name = TRUE;
      }
    }
    ii++;
  }

  if (!had_input_name)
  {
    print_err("### ps2ts: No input file specified\n");
    return 1;
  }
  if (!had_output_name)
  {
    print_err("### ps2ts: No output file specified\n");
    return 1;
  }

  // Try to stop extraneous data ending up in our output stream
  if (use_stdout)
  {
    verbose = FALSE;
    quiet = TRUE;
  }

  err = open_PS_file(input_name,quiet,&ps);
  if (err)
  {
    fprint_err("### ps2ts: Unable to open input %s\n",
               (use_stdin?"<stdin>":input_name));
    return 1;
  }

  if (!quiet)
    fprint_msg("Reading from %s\n",(use_stdin?"<stdin>":input_name));

  // Try to decide what sort of data stream we have
  if (force_stream_type || use_stdin)
  {
    if (!quiet)
      fprint_msg("Reading input as %s (0x%02x)\n",
                 h222_stream_type_str(video_type),video_type);
  }
  else
  {
    err = determine_PS_video_type(ps,&video_type);
    if (err) return 1;
    if (!quiet)
      fprint_msg("Video appears to be %s (0x%02x)\n",
                 h222_stream_type_str(video_type),video_type);
  }

  if (!quiet)
  {
    if (input_is_dvd)
      print_msg("Treating input as from DVD\n");
    else
      print_msg("Treating input as NOT from DVD\n");

    print_msg("Reading video from ");
    if (video_stream == -1)
      print_msg("first stream found");
    else
      fprint_msg("stream %0#x (%d)",video_stream,video_stream);
    if (keep_audio)
    {
      print_msg(", audio from ");
      if (audio_stream == -1)
        fprint_msg("first %s found",(want_ac3_audio?"AC3 stream":"stream"));
      else
        fprint_msg("%s %0#x (%d)",(want_ac3_audio?"AC3 stream":"stream"),
               audio_stream,audio_stream);
      print_msg("\n");
    }

    fprint_msg("Writing video with PID 0x%02x",video_pid);
    if (keep_audio)
      fprint_msg(", audio with PID 0x%02x,",audio_pid);
    fprint_msg(" PMT PID 0x%02x, PCR PID 0x%02x\n",pmt_pid,pcr_pid);
    if (max)
      fprint_msg("Stopping after %d program stream packets\n",max);
  }

  if (use_stdout)
    err = tswrite_open(TS_W_STDOUT,NULL,NULL,0,quiet,&output);
  else if (use_tcpip)
    err = tswrite_open(TS_W_TCP,output_name,NULL,port,quiet,&output);
  else
    err = tswrite_open(TS_W_FILE,output_name,NULL,0,quiet,&output);
  if (err)
  {
    fprint_err("### ps2ts: Unable to open %s\n",output_name);
    (void) close_PS_file(&ps);
    return 1;
  }

  err = ps_to_ts(ps,output,pad_start,repeat_program_every,
                 video_type,input_is_dvd,
                 video_stream,audio_stream,want_ac3_audio,
                 want_dolby_as_dvb,pmt_pid,pcr_pid,video_pid,
                 keep_audio,audio_pid,max,verbose,quiet);
  if (err)
  {
    print_err("### ps2ts: Error transferring data\n");
    (void) close_PS_file(&ps);
    (void) tswrite_close(output,TRUE);
    return 1;
  }

  // And tidy up when we're finished
  err = tswrite_close(output,quiet);
  if (err)
    fprint_err("### ps2ts: Error closing output %s: %s\n",output_name,
            strerror(errno));
  err = close_PS_file(&ps);
  if (err)
    fprint_err("### ps2ts: Error closing input %s\n",
               (use_stdin?"<stdin>":input_name));
  return 0;
}
Пример #2
0
/*
 * Read PS packets and then output them as TS.
 *
 * - `input` is the program stream
 * - `output` is the transport stream
 * - `pad_start` is the number of filler TS packets to start the output
 *   with.
 * - `program_repeat` is how often (after how many PS packs) to repeat
 *   the program information (PAT/PMT)
 * - `want_h264` should be true to indicate that the video stream is H.264
 *   (ISO/IEC 14496-2, MPEG-4/AVC), false if it is H.262 (ISO/IEC 13818-3,
 *   MPEG-2, or indeed 11172-3, MPEG-1)
 * - `input_is_dvd` indicates if the PS data came from a DVD, and thus follows
 *   its conventions for private_stream_1 and AC-3/DTS/etc. substreams
 * - `video_stream` indicates which video stream we want - i.e., the stream
 *   with id 0xE0 + <video_stream> - and -1 means the first video stream found.
 * - `audio_stream` indicates which audio stream we want. If `want_ac3_audio`
 *   is false, then this will be the stream with id 0xC0 + <audio_stream>, or,
 *   if it is -1, the first audio stream found.
 * - if `want_ac3_audio` is true, then if `is_dvd` is true, then we want
 *   audio from private_stream_1 (0xBD) with substream id <audio_stream>,
 *   otherwise we ignore `audio_stream` and assume that all data in
 *   private_stream_1 is the audio we want.
 * - `want_dolby_as_dvb` indicates if any Dolby (AC-3) audio data should be output
 *   with DVB or ATSC stream type
 * - `pmt_pid` is the PID of the PMT to write
 * - `pcr_pid` is the PID of the TS unit containing the PCR
 * - `video_pid` is the PID for the video we write
 * - `keep_audio` is true if the audio stream should be output, false if
 *   it should be ignored
 * - `audio_pid` is the PID for the audio we write
 * - if `max` is non-zero, then we want to stop reading after we've read
 *   `max` packets
 * - if `loop`, play the input file repeatedly (up to `max` TS packets
 *   if applicable)
 * - if `verbose` then we want to output diagnostic information
 *   (nb: only applies to first time if looping is enabled)
 * - if `quiet` then we want to be as quiet as we can
 *   (nb: only applies to first time if looping is enabled)
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
extern int play_PS_stream(int          input,
                          TS_writer_p  output,
                          int          pad_start,
                          int          program_repeat,
                          int          force_stream_type,
                          int          want_h262,
                          int          input_is_dvd,
                          int          video_stream,
                          int          audio_stream,
                          int          want_ac3_audio,
                          int          want_dolby_as_dvb,
                          uint32_t     pmt_pid,
                          uint32_t     pcr_pid,
                          uint32_t     video_pid,
                          int          keep_audio,
                          uint32_t     audio_pid,
                          int          max,
                          int          loop,
                          int          verbose,
                          int          quiet)
{
  int  err;
  int  is_h264;
  PS_reader_p   ps;

  err = build_PS_reader(input,quiet,&ps);
  if (err)
  {
    print_err("### Error building PS reader for input\n");
    return 1;
  }

  if (force_stream_type)
  {
    is_h264 = !want_h262;
    if (!quiet)
      fprint_msg("Reading input as %s\n",(want_h262?"MPEG-2 (H.262)":
                                          "MPEG-4/AVC (H.264)"));
  }
  else
  {
    err = determine_if_PS_is_h264(ps,&is_h264);
    if (err) return 1;

    if (!quiet)
      fprint_msg("Video appears to be %s\n",
                 (is_h264?"MPEG-4/AVC (H.264)":"MPEG-2 (H.262)"));
  }

  err = ps_to_ts(ps,output,pad_start,program_repeat,
                 is_h264,input_is_dvd,
                 video_stream,audio_stream,want_ac3_audio,
                 want_dolby_as_dvb,pmt_pid,pcr_pid,
                 video_pid,keep_audio,audio_pid,max,verbose,quiet);

  if (err)
  {
    if (loop)
      print_err("!!! Ignoring error and looping\n");
    else
    {
      free_PS_reader(&ps);
      return 1;
    }
  }

  if (loop)
  {
    for (;;)
    {
      if (!quiet) print_msg("Rewinding and continuing\n");
      err = rewind_program_stream(ps);
      if (err)
      {
        print_err("### Error rewinding\n");
        free_PS_reader(&ps);
        return 1;
      }
      err = ps_to_ts(ps,output,pad_start,program_repeat,
                     is_h264,input_is_dvd,
                     video_stream,audio_stream,want_ac3_audio,
                     want_dolby_as_dvb,pmt_pid,pcr_pid,
                     video_pid,keep_audio,audio_pid,max,FALSE,TRUE);
      if (err)
      {
        if (loop)
          print_err("!!! Ignoring error and looping\n");
        else
        {
          free_PS_reader(&ps);
          return 1;
        }
      }
    }
  }
  return 0;
}