Ejemplo n.º 1
0
/*
 * Look for an initial 0x47 sync byte, and check for TS
 *
 * Returns 0 if nothing went wrong, 1 if something did.
 */
static int check_if_TS(int   input,
                       byte  cur_byte,
                       int   verbose,
                       int  *decided,
                       int  *result)
{
  int  ii;

  if (verbose)
    print_msg("Is it Transport Stream?\n");

  // It may be enough to look at the first byte of the stream
  if (cur_byte != 0x47)
  {
    if (verbose)
      fprint_msg("  First byte in file is 0x%02X not 0x47, so it is not\n",cur_byte);
    return 0;
  }

  // Transport Stream packets start with 0x47, so it's a good bet.
  if (verbose)
    print_msg("  First byte in file is 0x47, so it looks like Transport Stream\n");

  // To check a bit, we can try looking at every 188th byte
  if (verbose)
    print_msg("  Checking next 500 packets to see if they start 0x47\n");
  for (ii=0; ii<500; ii++)
  {
    byte buf[TS_PACKET_SIZE];
    int err = read_bytes(input,TS_PACKET_SIZE,buf);
    if (err)
    {
      fprint_err("### %s trying to read start of packet %d\n",
                 (err==EOF?"EOF":"Error"),ii+1);
      return 1;
    }
    if (buf[TS_PACKET_SIZE-1] != 0x47)
    {
      if (verbose)
        fprint_msg("  Packet %d does not start with 0x47 (%02x instead)\n",
                   ii+1,buf[TS_PACKET_SIZE-1]);
      return 0;
    }
  }
  if (verbose)
    print_msg("The checked packets all start with 0x47 - looks like TS\n");
  *decided = TRUE;
  *result  = STREAM_IS_TS;
  return 0;
}
Ejemplo n.º 2
0
static int write_out_packet(pcapreport_ctx_t * const ctx,
                            pcapreport_stream_t * const st,
                            const byte *data, 
                            const uint32_t len)
{
  int rv;
  unsigned int pkts = len / 188;

  if (st->output_name)
  {
    if (!st->output_file)
    {
      fprint_msg("pcapreport: Dumping all packets for %s:%d to %s\n",
                 ipv4_addr_to_string(st->output_dest_addr),
                 st->output_dest_port,
                 st->output_name);
      st->output_file = fopen(st->output_name, "wb");
      if (!st->output_file)
      {
        fprint_err("### pcapreport: Cannot open %s .\n", 
                   st->output_name);
        return 1;
      }
    }

    if (ctx->verbose)
    {
      fprint_msg("++   Dumping %d bytes to output file.\n", len);
    }
    rv = fwrite(data, 188, pkts, st->output_file);
    if (rv != pkts)
    {
      fprint_err( "### pcapreport: Couldn't write %d bytes"
                  " to %s (error = %d).\n", 
                  len, st->output_name, 
                  ferror(st->output_file));
      return 1;
    }
  }
  return 0;
}
Ejemplo n.º 3
0
static int check(uint64_t value)
{
  int      err;
  byte     data[5];
  uint64_t result;

  encode_pts_dts(data,2,value);
  err = decode_pts_dts(data,2,&result);
  if (err) return 1;

  if (value == result)
    fprint_msg("Value " LLU_FORMAT " OK\n",value);
  else
  {
    fprint_msg("Input " LLU_FORMAT ", output " LLU_FORMAT "\n",value,result);
    return 1;
  }

  return 0;

}
Ejemplo n.º 4
0
/*
 * Read the next ADTS frame.
 *
 * Assumes that the input stream is synchronised - i.e., it does not
 * try to cope if the next three bytes are not '1111 1111 1111'.
 *
 * - `file` is the file descriptor of the ADTS file to read from
 * - `frame` is the ADTS frame that is read
 * - `flags` indicates if we are forcing the recognition of "emphasis"
 *   fields, etc.
 *
 * Returns 0 if all goes well, EOF if end-of-file is read, and 1 if something
 * goes wrong.
 */
extern int read_next_adts_frame(int            file,
                                audio_frame_p *frame,
                                unsigned int   flags)
{
#define JUST_ENOUGH 6 // just enough to hold the bits of the headers we want

  int    err, ii;
  int    id, layer;
  byte   header[JUST_ENOUGH];
  byte  *data = NULL;
  int    frame_length;
  int    has_emphasis = 0;

  offset_t  posn = tell_file(file);
#if DEBUG
  fprint_msg("Offset: " OFFSET_T_FORMAT "\n",posn);
#endif

  err = read_bytes(file,JUST_ENOUGH,header);
  if (err == EOF)
    return EOF;
  else if (err)
  {
    fprint_err("### Error reading header bytes of ADTS frame\n"
               "    (in frame starting at " OFFSET_T_FORMAT ")\n",posn);
    free(data);
    return 1;
  }

#if DEBUG
  print_msg("ADTS frame\n");
  print_data(TRUE,"Start",header,JUST_ENOUGH,JUST_ENOUGH);
#endif

  if (header[0] != 0xFF || (header[1] & 0xF0) != 0xF0)
  {
    fprint_err("### ADTS frame does not start with '1111 1111 1111'"
               " syncword - lost synchronisation?\n"
               "    Found 0x%X%X%X instead of 0xFFF\n",
               (unsigned)(header[0] & 0xF0) >> 4,
               (header[0] & 0x0F),
               (unsigned)(header[1] & 0xF0) >> 4);
    fprint_err("    (in frame starting at " OFFSET_T_FORMAT ")\n",posn);
    return 1;
  }
Ejemplo n.º 5
0
/*
 * Merge the given elementary streams to the given output.
 *
 * Returns 0 if all goes well, 1 if something goes wrong.
 */
static int merge_with_h264(access_unit_context_p  video_context,
                           int                    audio_file,
                           TS_writer_p            output1,
 //                          TS_writer_p            output2,
                           int                    audio_type,
                           int                    audio_samples_per_frame,
                           int                    audio_sample_rate,
                           int                    video_frame_rate,
                           int                    pat_pmt_freq,
                           int                    quiet,
                           int                    verbose,
                           int                    debugging,
                           int                    serialno,
                           uint32_t               *rete)
{
  int  ii;
  int  err;
  uint32_t prog_pids[2];
  byte     prog_type[2];

  int video_frame_count = 0; //serialno/2*125;
  int audio_frame_count = 0;

  uint32_t video_pts_increment = 90000 / video_frame_rate;
  uint32_t audio_pts_increment = (90000 * audio_samples_per_frame) / audio_sample_rate;
  uint64_t video_pts = 0;//900000*serialno/2;
  if(serialno!=0){
  FILE *pFilePTS = fopen ("PTSCache.txt","r");
  uint32_t ret=fscanf(pFilePTS, "%lld", &video_pts);
  printf("ret of fscanf= %d",ret);
  fclose(pFilePTS);
  }
  uint64_t video_dts = 0;
  uint64_t audio_pts = 0;

  // The "actual" times are just for information, so we aren't too worried
  // about accuracy - thus floating point should be OK.
  double audio_time = 0.0;
  double video_time = 0.0;

  int got_video = TRUE;
  int got_audio = FALSE;

  if (verbose)
    fprint_msg("Video PTS increment %u\n"
               "Audio PTS increment %u\n",video_pts_increment,audio_pts_increment);

  // Start off our output with some null packets - this is in case the
  // reader needs some time to work out its byte alignment before it starts
  // looking for 0x47 bytes
  for (ii=0; ii<8; ii++)
  {
    err = write_TS_null_packet(output1);
  //  err = write_TS_null_packet(output2);
    if (err) return 1;
  }

  // Then write some program data
  // @@@ later on we might want to repeat this every so often
  prog_pids[0] = DEFAULT_VIDEO_PID;
  prog_pids[1] = DEFAULT_AUDIO_PID;
  prog_type[0] = AVC_VIDEO_STREAM_TYPE;

  /*switch (audio_type)
  {
  case AUDIO_ADTS:
  case AUDIO_ADTS_MPEG2:
  case AUDIO_ADTS_MPEG4:
    prog_type[1] = ADTS_AUDIO_STREAM_TYPE;
    break;
  case AUDIO_L2:
    prog_type[1] = MPEG2_AUDIO_STREAM_TYPE;
    break;
  case AUDIO_AC3:
    prog_type[1] = ATSC_DOLBY_AUDIO_STREAM_TYPE;
    break;
  default:              // what else can we do?
    prog_type[1] = ADTS_AUDIO_STREAM_TYPE;
    break;
  }*/

   // prog_type[1] = MPEG2_AUDIO_STREAM_TYPE;
  err = write_TS_program_data2(output1,
                               1, // transport stream id
                               1, // program number
                               DEFAULT_PMT_PID,
                               DEFAULT_VIDEO_PID,  // PCR pid
                               2,prog_pids,prog_type);
/*  err = write_TS_program_data2(output2,
                               1, // transport stream id
                               1, // program number
                               DEFAULT_PMT_PID,
                               DEFAULT_VIDEO_PID,  // PCR pid
                               2,prog_pids,prog_type);*/
  if (err)
  {
    print_err("### Error writing out TS program data\n");
    return 1;
  }

  //uint32_t restrictTime=serialno/2*125+125;
  uint32_t restrictTime=300;
  while ((got_video || got_audio) && video_frame_count < restrictTime)
  {
    access_unit_p  access_unit;
    audio_frame_p  aframe;

    // Start with a video frame
    if (got_video)
    {
      err = get_next_h264_frame(video_context,quiet,debugging,&access_unit);
      //printf("index of access_unit %d\n", access_unit->index);
      if (err == EOF)
      {
        if (verbose)
          print_msg("EOF: no more video data\n");
        got_video = FALSE;
      }
      else if (err)
        return 1;
    }

    if (got_video)
    {
      video_time = video_frame_count / (double) video_frame_rate;
      video_pts += video_pts_increment;
      video_dts += video_pts_increment;
      video_frame_count ++;
      if (verbose)
        fprint_msg("\n%s video frame %5d (@ %.2fs, " LLU_FORMAT ")\n",
                   (is_I_or_IDR_frame(access_unit)?"**":"++"),
                   video_frame_count,video_time,video_pts);

      if (pat_pmt_freq && !(video_frame_count % pat_pmt_freq ))
        {
          printf("**********write PAT PMT**********\n");
          if (verbose)
            {
              fprint_msg("\nwriting PAT and PMT (frame = %d, freq = %d).. ",
                         video_frame_count, pat_pmt_freq);
            }
          //if(video_frame_count<restrictTime/2) {
          err = write_TS_program_data2(output1,
                                       1, // tsid
                                       1, // Program number
                                       DEFAULT_PMT_PID,
                                       DEFAULT_VIDEO_PID, // PCR pid
                                       2, prog_pids, prog_type);
         /* }else {
          err = write_TS_program_data2(output2,
                                       1, // tsid
                                       1, // Program number
                                       DEFAULT_PMT_PID,
                                       DEFAULT_VIDEO_PID, // PCR pid
                                       2, prog_pids, prog_type);
          }*/
        }


      // PCR counts frames as seen in the stream, so is easy
      // The presentation and decoding time for B frames (if we ever get any)
      // could reasonably be the same as the PCR.
      // The presentation and decoding time for I and IDR frames is unlikely to
      // be the same as the PCR (since frames come out later...), but it may
      // work to pretend the PTS is the PCR plus a delay time (for decoding)...

      // We could output the timing information every video frame,
      // but might as well only do it on index frames.
      if (!is_I_or_IDR_frame(access_unit)){
        //if(video_frame_count<restrictTime/2) {
        err = write_access_unit_as_TS_with_pts_dts(access_unit,video_context,
                                                   output1,DEFAULT_VIDEO_PID,
                                                   //TRUE,video_pts+45000,
                                                   TRUE,video_pts,
                                                   TRUE,video_pts);
        /*}else {
        err = write_access_unit_as_TS_with_pts_dts(access_unit,video_context,
                                                   output2,DEFAULT_VIDEO_PID,
                                                   //TRUE,video_pts+45000,
                                                   TRUE,video_pts,
                                                   TRUE,video_pts);
        }*/
      }else {
        //if(video_frame_count<restrictTime/2) {
        err = write_access_unit_as_TS_with_PCR(access_unit,video_context,
                                               output1,DEFAULT_VIDEO_PID,
                                               video_pts,0);
        /*}else {
        err = write_access_unit_as_TS_with_PCR(access_unit,video_context,
                                               output2,DEFAULT_VIDEO_PID,
                                               video_pts,0);
        }*/
      }

      if (err)
      {
        free_access_unit(&access_unit);
        print_err("### Error writing access unit (frame)\n");
        return 1;
      }
      free_access_unit(&access_unit);

      // Did the logical video stream end after the last access unit?
      if (video_context->end_of_stream)
      {
        if (verbose)
          print_msg("Found End-of-stream NAL unit\n");
        got_video = FALSE;
      }
    }

    if (!got_audio)
      continue;

    // Then output enough audio frames to make up to a similar time
    while (audio_pts < video_pts || !got_video)
    {
    //  err = read_next_audio_frame(audio_file,audio_type,&aframe);
      if (!got_video)
        err = EOF;
      if (err == EOF)
      {
        if (verbose)
          print_msg("EOF: no more audio data\n");
        got_audio = FALSE;
        break;
      }
      else if (err)
        return 1;

      audio_time = audio_frame_count *
        audio_samples_per_frame / (double)audio_sample_rate;
      audio_pts += audio_pts_increment;
      audio_frame_count ++;
      if (verbose)
        fprint_msg("** audio frame %5d (@ %.2fs, " LLU_FORMAT ")\n",
                   audio_frame_count,audio_time,audio_pts);

/*      err = write_ES_as_TS_PES_packet_with_pts_dts(output,aframe->data,
                                                   aframe->data_len,
                                                   DEFAULT_AUDIO_PID,
                                                   DEFAULT_AUDIO_STREAM_ID,
                                                   TRUE,audio_pts,
                                                   TRUE,audio_pts);*/
      if (err)
      {
        free_audio_frame(&aframe);
        print_err("### Error writing audio frame\n");
        return 1;
      }
      free_audio_frame(&aframe);
    }
  }

  printf("video_pts is %lld",video_pts);
  FILE *pFilePTS = fopen ("PTSCache.txt","w");
  fprintf(pFilePTS, "%lld", video_pts);
  fclose(pFilePTS);
  /*uint32_t video_elapsed = 100*video_frame_count/video_frame_rate;
  FILE *pFileLen = fopen ("videoLength.txt","w");
  fprintf(pFileLen, "%.2f", video_elapsed/100.0);
  fclose(pFileLen);*/
  *rete = 100*video_frame_count/video_frame_rate;

  if (!quiet)
  {
    uint32_t video_elapsed = 100*video_frame_count/video_frame_rate;
    uint32_t audio_elapsed = 100*audio_frame_count*
      audio_samples_per_frame/audio_sample_rate;
    fprint_msg("Read %d video frame%s, %.2fs elapsed (%dm %.2fs)\n",
               video_frame_count,(video_frame_count==1?"":"s"),
               video_elapsed/100.0,video_elapsed/6000,(video_elapsed%6000)/100.0);
    fprint_msg("Read %d audio frame%s, %.2fs elapsed (%dm %.2fs)\n",
               audio_frame_count,(audio_frame_count==1?"":"s"),
               audio_elapsed/100.0,audio_elapsed/6000,(audio_elapsed%6000)/100.0);
  }

  return 0;

}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/*
 * Read the next TS packet, coping with looping, etc.
 *
 * - `tsreader` is the TS reader context
 * - `count` is a running count of TS packets read from this input
 * - `data` is a pointer to the data for the packet
 * - `pid` is the PID of the TS packet
 * - `got_PCR` is TRUE if the adaptation field of this packet contains a PCR
 * - `pcr` is then the PCR value itself
 * - if `max` is greater than zero, then at most `max` TS packets should
 *   be read from the input
 * - if `loop`, play the input file repeatedly (up to `max` TS packets
 *   if applicable) - i.e., rewind to `start_posn` and start again if
 *   `count` reaches `max` (obviously only if `max` is greater than zero).
 * - `start_count` is the value `count` should have after we've looped back
 *   to `start_posn`
 * - if `quiet` is true, then only error messages should be written out
 *
 * Returns 0 if all went well, 1 if something went wrong, EOF if `loop` is
 * false and either EOF was read, or `max` TS packets were read.
 */
static int read_TS_packet(TS_reader_p  tsreader,
                          uint32_t    *count,
                          byte        *data[TS_PACKET_SIZE],
                          uint32_t    *pid,
                          int         *got_pcr,
                          uint64_t    *pcr,
                          int          max,
                          int          loop,
                          offset_t     start_posn,
                          uint32_t     start_count,
                          int          quiet)
{
  int     err;
  int     payload_unit_start_indicator;
  byte   *adapt;
  int     adapt_len;
  byte   *payload;
  int     payload_len;

  if (max > 0 && (*count) >= (uint32_t)max)
  {
    if (loop)
    {
      if (!quiet)
        fprint_msg("Read %d packets, rewinding and continuing\n",max);
      err = seek_using_TS_reader(tsreader,start_posn);
      if (err) return 1;
      *count = start_count;
    }
    else
    {
      if (!quiet) fprint_msg("Stopping after %d TS packets\n",max);
      return EOF;
    }
  }

  // Read the next packet
  err = read_next_TS_packet(tsreader,data);
  if (err)
  {
    if (err == EOF)
    {
      if (!loop)
        return EOF;
      if (!quiet)
        fprint_msg("EOF (after %d TS packets), rewinding and continuing\n",
                   *count);
    }
    else
    {
      fprint_err("### Error reading TS packet %d\n",*count);
      if (!loop)
        return 1;
      if (!quiet)
        print_msg("!!! Rewinding and continuing anyway\n");
    }
    err = seek_using_TS_reader(tsreader,start_posn);
    if (err) return 1;
    *count = start_count;
  }

  err = split_TS_packet(*data,pid,&payload_unit_start_indicator,
                        &adapt,&adapt_len,&payload,&payload_len);
  if (err)
  {
    fprint_err("### Error splitting TS packet %d\n",*count);
    return 1;
  }

  get_PCR_from_adaptation_field(adapt,adapt_len,got_pcr,pcr);

  (*count) ++;
  return 0;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
/*
 * Look at the start of our "elementary" stream, and try to determine
 * its actual type.
 *
 * - `input` is the input stream to inspect
 * - if `verbose` is true, the caller wants details of how the decision
 *   is being made
 * - `decided` is returned TRUE if the function believes it has identified
 *   the stream type, in which case:
 * - `result` will an appropriate value indicating what we've decided
 *
 * Note that this function reads into the stream, and may attempt to
 * rewind it.
 *
 * Returns 0 if nothing went wrong, 1 if an error occurred
 */
static int determine_packet_type(int   input,
                                 int   verbose,
                                 int  *decided,
                                 int  *result)
{
  int  err;
#ifdef _WIN32
  int  length;
#else
  ssize_t length;
#endif
  byte   first_byte;
  int    video_type;

  length = read(input,&first_byte,1);
  if (length == 0)
  {
    print_err("### EOF reading first byte\n");
    return 1;
  }
  else if (length == -1)
  {
    fprint_err("### Error reading first byte: %s\n",strerror(errno));
    return 1;
  }
  
  // Does it look like transport stream?
  err = check_if_TS(input,first_byte,verbose,decided,result);
  if (err)
  {
    close_file(input);
    return 1;
  }
  if (*decided)
  {
    close_file(input);
    return 0;
  }

  seek_file(input,0);

  // Does it look like program stream?
  err = check_if_PS(input,verbose,decided,result);
  if (err)
  {
    close_file(input);
    return 1;
  }
  if (*decided)
  {
    close_file(input);
    return 0;
  }

  seek_file(input,0);
  
  // Does it look like one of the types of ES we recognise?
  if (verbose)
    print_msg("Is it an Elementary Stream we recognise?\n");

  err = decide_ES_file_video_type(input,!verbose,verbose,&video_type);
  if (err)
  {
    close_file(input);
    return 1;
  }

  switch (video_type)
  {
  case VIDEO_H264:
    *result = STREAM_IS_H264;
    *decided = TRUE;
    break;
  case VIDEO_H262:
    *result = STREAM_IS_H262;
    *decided = TRUE;
    break;
  case VIDEO_AVS:
    *result = STREAM_IS_AVS;
    *decided = TRUE;
    break;
  case VIDEO_UNKNOWN:
    *result = STREAM_IS_UNSURE;
    *decided = FALSE;
    if (verbose) print_msg("Still not sure\n");
    break;
  default:
    fprint_msg("### stream_type: Unexpected decision from"
               " decide_ES_file_video_type: %d\n",video_type);
    close_file(input);
    return 1;
  }

  close_file(input);
  return 0;
}
Ejemplo n.º 10
0
int main(int argc, char **argv)
{
  int    use_stdin = FALSE;
  char  *input_name = NULL;
  int    had_input_name = FALSE;

  PS_reader_p  ps;        // The PS file we're reading
  int    max     = 0;     // The maximum number of PS packets to read (or 0)
  int    verbose = FALSE; // True => output diagnostic/progress messages

  int    err = 0;
  int    ii = 1;

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

  while (ii < argc)
  {
    if (argv[ii][0] == '-')
    {
      if (!strcmp("--help",argv[ii]) || !strcmp("-h",argv[ii]) ||
          !strcmp("-help",argv[ii]))
      {
        print_usage();
        return 0;
      }
      else if (!strcmp("-err",argv[ii]))
      {
        CHECKARG("psdots",ii);
        if (!strcmp(argv[ii+1],"stderr"))
          redirect_output_stderr();
        else if (!strcmp(argv[ii+1],"stdout"))
          redirect_output_stdout();
        else
        {
          fprint_err("### psdots: "
                     "Unrecognised option '%s' to -err (not 'stdout' or"
                     " 'stderr')\n",argv[ii+1]);
          return 1;
        }
        ii++;
      }
      else if (!strcmp("-verbose",argv[ii]) || !strcmp("-v",argv[ii]))
      {
        verbose = TRUE;
      }
      else if (!strcmp("-max",argv[ii]) || !strcmp("-m",argv[ii]))
      {
        CHECKARG("psdots",ii);
        err = int_value("psdots",argv[ii],argv[ii+1],TRUE,10,&max);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-stdin",argv[ii]))
      {
        use_stdin = TRUE;
        had_input_name = TRUE;  // so to speak
      }
      else
      {
        fprint_err("### psdots: "
                   "Unrecognised command line switch '%s'\n",argv[ii]);
        return 1;
      }
    }
    else
    {
      if (had_input_name)
      {
        fprint_err("### psdots: Unexpected '%s'\n",argv[ii]);
        return 1;
      }
      else
      {
        input_name = argv[ii];
        had_input_name = TRUE;
      }
    }
    ii++;
  }

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


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

  if (max)
    fprint_msg("Stopping after %d PS packets\n",max);

  err = report_ps_dots(ps,max,verbose);
  if (err)
    print_err("### psdots: Error reporting on input stream\n");


  err = close_PS_file(&ps);
  if (err)
  {
    fprint_err("### psdots: Error closing input file %s\n",
               (use_stdin?"<stdin>":input_name));
    return 1;
  }
  return 0;
}
Ejemplo n.º 11
0
static int digest_times(pcapreport_ctx_t *ctx, 
                        pcapreport_stream_t * const st,
                        const pcaprec_hdr_t *pcap_pkt_hdr,
                        const ethernet_packet_t *epkt,
                        const ipv4_header_t *ipv4_header, 
                        const ipv4_udp_header_t *udp_header,
                        const byte *data,
                        const uint32_t len)
{
  int rv;
  const uint64_t ts_byte_start = st->ts_bytes;

  if (st->ts_r == NULL)
  {
    rv = build_TS_reader_with_fns(st,
                                  digest_times_read, 
                                  digest_times_seek, 
                                  &st->ts_r);
    if (rv)
    {
      print_err( "### pcapreport: Cannot create ts reader.\n");
      return 1;
    }
  }

  // Add all our data to the pool.
  {
    unsigned int pkts = len / 188;
    unsigned int pktlen = pkts * 188;

    if (pktlen != len)
      ++st->pkts_overlength;

    st->tmp_buf = (byte *)realloc(st->tmp_buf, st->tmp_len + pktlen);
    memcpy(&st->tmp_buf[st->tmp_len], data, pktlen);
    st->tmp_len += pktlen;
    st->ts_bytes += pktlen;
  }

  // Now read out all the ts packets we can.
  while (1)
  {
    byte *pkt;
    int rv;

    rv = read_next_TS_packet(st->ts_r, &pkt);
    if (rv == EOF)
    {
      // Got to EOF - return for more data
      return 0;
    }


    // Right. Split it ..
    {
      const uint64_t t_pcr = pkt_time(pcap_pkt_hdr);
      uint32_t pid;
      int pusi;
      byte *adapt;
      int adapt_len;
      byte *payload;
      int payload_len;

      rv = split_TS_packet(pkt, &pid, &pusi, &adapt, &adapt_len,
                           &payload, &payload_len);
      if (rv)
      {
        fprint_msg(">%d> WARNING: TS packet %d [ packet %d @ %d.%d s ] cannot be split.\n",
                   st->stream_no,
                   st->ts_counter, ctx->pkt_counter, 
                   pcap_pkt_hdr->ts_sec, pcap_pkt_hdr->ts_usec);
      }
      else
      {
        //int cc;

        // PCR ?
        if (adapt && adapt_len)
        {
          int has_pcr;
          uint64_t pcr;
          int64_t pcr_time_offset;

          get_PCR_from_adaptation_field(adapt, adapt_len, &has_pcr,
                                        &pcr);

          if (has_pcr)
          {
            int64_t skew;

            if (ctx->time_report)
            {
              fprint_msg(">%d> Found PCR %lld at %d.%d s \n", st->stream_no,
                         pcr, pcap_pkt_hdr->ts_sec, pcap_pkt_hdr->ts_usec);
            }

            if (st->pcr_pid == 0)
              st->pcr_pid = pid;

            if (pid != st->pcr_pid)
            {
              // *** If this happens often then fix to track each Pid
              if (!st->multiple_pcr_pids)
              {
                fprint_msg("!%d! Multiple pids detected: pids: %d,%d,...\n",
                  st->stream_no, st->pcr_pid, pid);
              }
              st->multiple_pcr_pids = TRUE;
            }
            else
            {
              // PCR pops out in 27MHz units. Let's do all our comparisons
              // in 90kHz.
              pcr /= 300;

              // fprint_msg("pcr = %lld t_pcr = %lld diff = %lld\n", 
              //            pcr, t_pcr, t_pcr - pcr);

              pcr_time_offset = ((int64_t)t_pcr - (int64_t)pcr);

              skew = st->section_last == NULL ? 0LL :
                pcr_time_offset - (st->section_last->time_start - st->section_last->pcr_start);

              if (st->section_last == NULL ||
                  skew > st->skew_discontinuity_threshold || 
                  skew < -st->skew_discontinuity_threshold)
              {
                pcapreport_section_t * const tsect = section_create(st);

                if (tsect->section_no != 0)
                {
                  fprint_msg(">%d> Skew discontinuity! Skew = %lld (> %lld) at"
                             " ts = %d network = %d (PCR %lld Time %d.%d)\n", 
                             st->stream_no,
                             skew, st->skew_discontinuity_threshold, 
                             st->ts_counter, ctx->pkt_counter,
                             pcr, pcap_pkt_hdr->ts_sec,
                             pcap_pkt_hdr->ts_usec);
                }

                tsect->pkt_final =
                tsect->pkt_start = ctx->pkt_counter;
                tsect->pcr_last =
                tsect->pcr_start = pcr;
                tsect->time_last =
                tsect->time_start = t_pcr;
                tsect->ts_byte_start =
                tsect->ts_byte_final = ts_byte_start;

                jitter_clear(&st->jitter);
                st->last_time_offset = 0;
              }
              else
              {
                pcapreport_section_t * const tsect = st->section_last;

                // Extract jitter over up to the last 10s.  skew will be within
                // an int by now
                unsigned int cur_jitter = jitter_add(&st->jitter, (int)skew,
                  (uint32_t)(t_pcr & 0xffffffffU), 90000 * 10);

                if (tsect->jitter_max < cur_jitter)
                  tsect->jitter_max = cur_jitter;

                if (ctx->time_report)
                {
                  int64_t rel_tim = t_pcr - tsect->time_start; // 90kHz
                  double skew_rate = (double)skew / ((double)((double)rel_tim / (60*90000)));
  
                  fprint_msg(">%d> [ts %d net %d ] PCR %lld Time %d.%d [rel %d.%d]  - skew = %lld (delta = %lld, rate = %.4g PTS/min) - jitter=%u\n",
                             st->stream_no,
                             st->ts_counter, ctx->pkt_counter,
                             pcr, 
                             pcap_pkt_hdr->ts_sec, pcap_pkt_hdr->ts_usec,
                             (int)(rel_tim / (int64_t)1000000), 
                             (int)rel_tim%1000000,
                             skew, pcr_time_offset - st->last_time_offset, 
                             skew_rate, cur_jitter);
                }

                if (st->csv_name != NULL)  // We should be outputting to file
                {
                  if (st->csv_file == NULL)
                  {
                    if ((st->csv_file = fopen(st->csv_name, "wt")) == NULL)
                    {
                      fprint_err("### pcapreport: Cannot open %s .\n", 
                                 st->csv_name);
                      exit(1);
                    }
                    fprintf(st->csv_file, "\"PKT\",\"Time\",\"PCR\",\"Skew\",\"Jitter\"\n");
                  }
                  fprintf(st->csv_file, "%d,%llu,%llu,%lld,%u\n", ctx->pkt_counter, t_pcr - ctx->time_start, pcr, skew, cur_jitter);
                }

                // Remember where we are for posterity
                tsect->pcr_last = pcr;
                tsect->time_last = t_pcr;

                st->last_time_offset = pcr_time_offset;
              }
            }
          }
        }
      }

      {
        pcapreport_section_t * const tsect = st->section_last;
        if (tsect != NULL)
        {
          tsect->time_final = t_pcr;
          tsect->ts_byte_final = st->ts_bytes;
          tsect->pkt_final = ctx->pkt_counter;
        }
      }

      ++st->ts_counter;
    }
  }
}
Ejemplo n.º 12
0
int main(int argc, char **argv)
{
    int    use_stdout = FALSE;
    int    use_stdin = FALSE;
    char  *input_name = NULL;
    char  *output_name = NULL;
    int    had_input_name = FALSE;
    int    had_output_name = FALSE;
    char  *action_switch = "None";

    EXTRACT   extract = EXTRACT_VIDEO; // What we're meant to extract
    int       input   = -1;    // Our input file descriptor
    FILE     *output  = NULL;  // The stream we're writing to (if any)
    int       max     = 0;     // The maximum number of TS packets to read (or 0)
    uint32_t  pid     = 0;     // The PID of the (single) stream to extract
    int       quiet   = FALSE; // True => be as quiet as possible
    int       verbose = FALSE; // True => output diagnostic/progress messages
    int       use_pes = FALSE;

    int    err = 0;
    int    ii = 1;

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

    while (ii < argc)
    {
        if (argv[ii][0] == '-')
        {
            if (!strcmp("--help",argv[ii]) || !strcmp("-h",argv[ii]) ||
                    !strcmp("-help",argv[ii]))
            {
                print_usage();
                return 0;
            }
            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("ts2es",ii);
                err = int_value("ts2es",argv[ii],argv[ii+1],TRUE,10,&max);
                if (err) return 1;
                ii++;
            }
            else if (!strcmp("-pes",argv[ii]) || !strcmp("-ps",argv[ii]))
            {
                use_pes = TRUE;
            }
            else if (!strcmp("-pid",argv[ii]))
            {
                CHECKARG("ts2es",ii);
                err = unsigned_value("ts2es",argv[ii],argv[ii+1],0,&pid);
                if (err) return 1;
                ii++;
                extract = EXTRACT_PID;
            }
            else if (!strcmp("-video",argv[ii]))
            {
                extract = EXTRACT_VIDEO;
            }
            else if (!strcmp("-audio",argv[ii]))
            {
                extract = EXTRACT_AUDIO;
            }
            else if (!strcmp("-stdin",argv[ii]))
            {
                use_stdin = TRUE;
                had_input_name = TRUE;  // so to speak
            }
            else if (!strcmp("-stdout",argv[ii]))
            {
                use_stdout = TRUE;
                had_output_name = TRUE;  // so to speak
                redirect_output_stderr();
            }
            else if (!strcmp("-err",argv[ii]))
            {
                CHECKARG("ts2es",ii);
                if (!strcmp(argv[ii+1],"stderr"))
                    redirect_output_stderr();
                else if (!strcmp(argv[ii+1],"stdout"))
                    redirect_output_stdout();
                else
                {
                    fprint_err("### ts2es: "
                               "Unrecognised option '%s' to -err (not 'stdout' or"
                               " 'stderr')\n",argv[ii+1]);
                    return 1;
                }
                ii++;
            }
            else
            {
                fprint_err("### ts2es: "
                           "Unrecognised command line switch '%s'\n",argv[ii]);
                return 1;
            }
        }
        else
        {
            if (had_input_name && had_output_name)
            {
                fprint_err("### ts2es: Unexpected '%s'\n",argv[ii]);
                return 1;
            }
            else if (had_input_name)  // shouldn't do this if had -stdout
            {
                output_name = argv[ii];
                had_output_name = TRUE;
            }
            else
            {
                input_name = argv[ii];
                had_input_name = TRUE;
            }
        }
        ii++;
    }

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

    if (!had_output_name)
    {
        fprint_err("### ts2es: "
                   "No output file specified for %s\n",action_switch);
        return 1;
    }

    // ============================================================
    // Testing PES output
    if (use_pes && extract == EXTRACT_PID)
    {
        print_err("### ts2es: -pid is not supported with -pes\n");
        return 1;
    }
    if (use_pes && use_stdout)
    {
        print_err("### ts2es: -stdout is not supported with -pes\n");
        return 1;
    }
    if (use_pes && use_stdin)
    {
        print_err("### ts2es: -stdin is not supported with -pes\n");
        return 1;
    }
    if (use_pes)
    {
        err = extract_av_via_pes(input_name,output_name,(extract==EXTRACT_VIDEO),
                                 quiet);
        if (err)
        {
            print_err("### ts2es: Error writing via PES\n");
            return 1;
        }
        return 0;
    }
    // ============================================================

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

    if (use_stdin)
        input = STDIN_FILENO;
    else
    {
        input = open_binary_file(input_name,FALSE);
        if (input == -1)
        {
            fprint_err("### ts2es: Unable to open input file %s\n",input_name);
            return 1;
        }
    }
    if (!quiet)
        fprint_msg("Reading from %s\n",(use_stdin?"<stdin>":input_name));

    if (had_output_name)
    {
        if (use_stdout)
            output = stdout;
        else
        {
            output = fopen(output_name,"wb");
            if (output == NULL)
            {
                if (!use_stdin) (void) close_file(input);
                fprint_err("### ts2es: "
                           "Unable to open output file %s: %s\n",output_name,
                           strerror(errno));
                return 1;
            }
        }
        if (!quiet)
            fprint_msg("Writing to   %s\n",(use_stdout?"<stdout>":output_name));
    }

    if (!quiet)
    {
        if (extract == EXTRACT_PID)
            fprint_msg("Extracting packets for PID %04x (%d)\n",pid,pid);
        else
            fprint_msg("Extracting %s\n",(extract==EXTRACT_VIDEO?"video":"audio"));
    }

    if (max && !quiet)
        fprint_msg("Stopping after %d TS packets\n",max);

    if (extract == EXTRACT_PID)
        err = extract_pid(input,output,pid,max,verbose,quiet);
    else
        err = extract_av(input,output,(extract==EXTRACT_VIDEO),
                         max,verbose,quiet);
    if (err)
    {
        print_err("### ts2es: Error extracting data\n");
        if (!use_stdin)  (void) close_file(input);
        if (!use_stdout) (void) fclose(output);
        return 1;
    }

    // And tidy up when we're finished
    if (!use_stdout)
    {
        errno = 0;
        err = fclose(output);
        if (err)
        {
            fprint_err("### ts2es: Error closing output file %s: %s\n",
                       output_name,strerror(errno));
            (void) close_file(input);
            return 1;
        }
    }
    if (!use_stdin)
    {
        err = close_file(input);
        if (err)
            fprint_err("### ts2es: Error closing input file %s\n",input_name);
    }
    return 0;
}
Ejemplo n.º 13
0
/*
 * Extract all the TS packets for either a video or audio stream.
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
static int extract_av(int   input,
                      FILE *output,
                      int   want_video,
                      int   max,
                      int   verbose,
                      int   quiet)
{
    int      err, ii;
    int      max_to_read = max;
    int      total_num_read = 0;
    uint32_t pid = 0;
    TS_reader_p tsreader = NULL;
    pmt_p       pmt = NULL;

    // Turn our file into a TS reader
    err = build_TS_reader(input,&tsreader);
    if (err) return 1;

    // First, find out what program streams we actually have
    for (;;)
    {
        int  num_read;

        // Give up if we've read more than our limit
        if (max > 0 && max_to_read <= 0)
            break;

        err = find_pmt(tsreader,max_to_read,verbose,quiet,&num_read,&pmt);
        if (err == EOF)
        {
            if (!quiet)
                print_msg("No program stream information in the input file\n");
            free_TS_reader(&tsreader);
            free_pmt(&pmt);
            return 0;
        }
        else if (err)
        {
            print_err("### Error finding program stream information\n");
            free_TS_reader(&tsreader);
            free_pmt(&pmt);
            return 1;
        }
        max_to_read -= num_read;
        total_num_read += num_read;

        // From that, find a stream of the type we want...
        // Note that the audio detection will accept either DVB or ADTS Dolby (AC-3)
        // stream types
        for (ii=0; ii < pmt->num_streams; ii++)
        {
            if (( want_video && IS_VIDEO_STREAM_TYPE(pmt->streams[ii].stream_type)) ||
                    (!want_video && (IS_AUDIO_STREAM_TYPE(pmt->streams[ii].stream_type))))
            {
                pid = pmt->streams[ii].elementary_PID;
                break;
            }
        }
        free_pmt(&pmt);

        // Did we find what we want? If not, go round again and look for the
        // next PMT (subject to the number of records we're willing to search)
        if (pid != 0)
            break;
    }

    if (pid == 0)
    {
        fprint_err("### No %s stream specified in first %d TS packets in input file\n",
                   (want_video?"video":"audio"),max);
        free_TS_reader(&tsreader);
        return 1;
    }

    if (!quiet)
        fprint_msg("Extracting %s PID %04x (%d)\n",(want_video?"video":"audio"),
                   pid,pid);

    // Amend max to take account of the packets we've already read
    max -= total_num_read;

    // And do the extraction.
    err = extract_pid_packets(tsreader,output,pid,max,verbose,quiet);
    free_TS_reader(&tsreader);
    return err;
}
Ejemplo n.º 14
0
/*
 * Extract all the TS packets for a nominated PID to another file.
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
static int extract_pid_packets(TS_reader_p  tsreader,
                               FILE        *output,
                               uint32_t     pid_wanted,
                               int          max,
                               int          verbose,
                               int          quiet)
{
    int    err;
    int    count = 0;
    int    extracted = 0;
    int    pes_packet_len = 0;
    int    got_pes_packet_len = FALSE;
    // It doesn't make sense to start outputting data for our PID until we
    // get the start of a packet
    int    need_packet_start = TRUE;

    for (;;)
    {
        uint32_t pid;
        int      payload_unit_start_indicator;
        byte    *adapt, *payload;
        int      adapt_len, payload_len;

        if (max > 0 && count >= max)
        {
            if (!quiet) fprint_msg("Stopping after %d packets\n",max);
            break;
        }

        err = get_next_TS_packet(tsreader,&pid,
                                 &payload_unit_start_indicator,
                                 &adapt,&adapt_len,&payload,&payload_len);
        if (err == EOF)
            break;
        else if (err)
        {
            print_err("### Error reading TS packet\n");
            return 1;
        }

        count++;

        // If the packet is empty, all we can do is ignore it
        if (payload_len == 0)
            continue;

        if (pid == pid_wanted)
        {
            byte  *data;
            int    data_len;
            size_t written;

            if (verbose)
            {
                fprint_msg("%4d: TS Packet PID %04x",count,pid);
                if (payload_unit_start_indicator)
                    print_msg(" (start)");
                else if (need_packet_start)
                    print_msg(" <ignored>");
                print_msg("\n");
            }


            if (payload_unit_start_indicator)
            {
                // It's the start of a PES packet, so we need to drop the header
                int offset;

                if (need_packet_start)
                    need_packet_start = FALSE;

                pes_packet_len = (payload[4] << 8) | payload[5];
                if (verbose) fprint_msg("PES packet length %d\n",pes_packet_len);
                got_pes_packet_len = (pes_packet_len > 0);

                if (IS_H222_PES(payload))
                {
                    // It's H.222.0 - payload[8] is the PES_header_data_length,
                    // so our ES data starts that many bytes after that field
                    offset = payload[8] + 9;
                }
                else
                {
                    // We assume it's MPEG-1
                    offset = calc_mpeg1_pes_offset(payload,payload_len);
                }
                data = &payload[offset];
                data_len = payload_len-offset;
                if (verbose) print_data(TRUE,"data",data,data_len,1000);
            }
            else
            {
                // If we haven't *started* a packet, we can't use this,
                // since it will just look like random bytes when written out.
                if (need_packet_start)
                {
                    continue;
                }

                data = payload;
                data_len = payload_len;
                if (verbose) print_data(TRUE,"Data",payload,payload_len,1000);

                if (got_pes_packet_len)
                {
                    // Try not to write more data than the PES packet declares
                    if (data_len > pes_packet_len)
                    {
                        data_len = pes_packet_len;
                        if (verbose) print_data(TRUE,"Reduced data",data,data_len,1000);
                        pes_packet_len = 0;
                    }
                    else
                        pes_packet_len -= data_len;
                }
            }
            if (data_len > 0)
            {
                // Windows doesn't seem to like writing 0 bytes, so be careful...
                written = fwrite(data,data_len,1,output);
                if (written != 1)
                {
                    fprint_err("### Error writing TS packet - units written = %d\n",
                               (int)written);
                    return 1;
                }
            }
            extracted ++;
        }
    }

    if (!quiet)
        fprint_msg("Extracted %d of %d TS packet%s\n",
                   extracted,count,(count==1?"":"s"));

    // If the user has forgotten to say -pid XX, or -video/-audio,
    // and are piping the output to another program, it can be surprising
    // if there is no data!
    if (quiet && extracted == 0)
        fprint_err("### No data extracted for PID %#04x (%d)\n",
                   pid_wanted,pid_wanted);
    return 0;
}
Ejemplo n.º 15
0
int main(int argc, char **argv)
{
  char   *input_name = NULL;
  int     had_input_name = FALSE;
  int     input = -1;
  int     verbose = FALSE;
  int     quiet = FALSE;
  int     err = 0;
  int     ii = 1;
  int     decided = FALSE;
  int     result = STREAM_IS_ERROR;
  
  if (argc < 2)
  {
    print_usage();
    return 0;
  }

  while (ii < argc)
  {
    if (argv[ii][0] == '-')
    {
      if (!strcmp("--help",argv[ii]) || !strcmp("-h",argv[ii]) ||
          !strcmp("-help",argv[ii]))
      {
        print_usage();
        return STREAM_IS_ERROR;
      }
      else if (!strcmp("-verbose",argv[ii]) || !strcmp("-v",argv[ii]))
      {
        verbose = TRUE;
        quiet = FALSE;
      }
      else if (!strcmp("-err",argv[ii]))
      {
        CHECKARG("stream_type",ii);
        if (!strcmp(argv[ii+1],"stderr"))
          redirect_output_stderr();
        else if (!strcmp(argv[ii+1],"stdout"))
          redirect_output_stdout();
        else
        {
          fprint_err("### stream_type: "
                     "Unrecognised option '%s' to -err (not 'stdout' or"
                     " 'stderr')\n",argv[ii+1]);
          return 1;
        }
        ii++;
      }
      else if (!strcmp("-quiet",argv[ii]) || !strcmp("-q",argv[ii]))
      {
        verbose = FALSE;
        quiet = TRUE;
      }
      else
      {
        fprint_err("### stream_type: "
                   "Unrecognised command line switch '%s'\n",argv[ii]);
        return STREAM_IS_ERROR;
      }
    }
    else
    {
      if (had_input_name)
      {
        fprint_err("### stream_type: Unexpected '%s'\n",argv[ii]);
        return STREAM_IS_ERROR;
      }
      else
      {
        input_name = argv[ii];
        had_input_name = TRUE;
      }
    }
    ii++;
  }
  
  if (!had_input_name)
  {
    print_err("### stream_type: No input file specified\n");
    return STREAM_IS_ERROR;
  }
  
  input = open_binary_file(input_name,FALSE);
  if (input == -1)
  {
    fprint_err("### stream_type: Unable to open input file %s\n",
               input_name);
    return 1;
  }

  if (!quiet)
    fprint_msg("Reading from %s\n",input_name);
  
  // Try to guess
  err = determine_packet_type(input,verbose,&decided,&result);
  if (err)
  {
    print_err("### Unable to decide on stream type due to error\n");
    return STREAM_IS_ERROR;
  }

  if (!quiet)
  {
    if (!decided)
    {
      print_msg("Unable to decide\n");
      result = STREAM_IS_UNSURE;
    }
    else
    {
      switch (result)
      {
      case STREAM_IS_TS:
        print_msg("It appears to be Transport Stream\n");
        break;
      case STREAM_IS_PS:
        print_msg("It appears to be Program Stream\n");
        break;
      case STREAM_IS_H262:
        print_msg("It appears to be Elementary Stream, MPEG-2 (H.262)\n");
        break;
      case STREAM_IS_H264:
        print_msg("It appears to be Elementary Stream, MPEG-4 (H.264)\n");
        break;
      case STREAM_IS_AVS:
        print_msg("It appears to be Elementary Stream, AVS\n");
        break;
      case STREAM_MAYBE_PES:
        print_msg("It looks likely to be PES\n");
        break;
      case STREAM_IS_UNSURE:
        print_msg("It is not recognised\n");
        break;
      default:
        fprint_msg("Unexpected decision value %d\n",result);
        result = STREAM_IS_ERROR;
        break;
      }
    }
  }
  return result;
}
Ejemplo n.º 16
0
int main(int argc, char **argv)
{
  int    had_video_name = FALSE;
  int    had_audio_name = FALSE;
  int    had_output_name = FALSE;
  char  *video_name = NULL;
  char  *audio_name = NULL;
  char  *output_name = NULL;
  int    err = 0;
  ES_p   video_es = NULL;
  access_unit_context_p h264_video_context = NULL;
  avs_context_p avs_video_context = NULL;
  int    audio_file = -1;
  TS_writer_p output1 = NULL;
//  TS_writer_p output2 = NULL;
  int    quiet = FALSE;
  int    verbose = FALSE;
  int    debugging = FALSE;
  int    audio_samples_per_frame = ADTS_SAMPLES_PER_FRAME;
  int    audio_sample_rate = CD_RATE;
  int    video_frame_rate = DEFAULT_VIDEO_FRAME_RATE;
  int    audio_type = AUDIO_ADTS;
  int    video_type = VIDEO_H264;
  int    pat_pmt_freq = 0;
  int    ii = 1;

#if TEST_PTS_DTS
  test_pts();
  return 0;
#endif

  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("-err",argv[ii]))
      {
        CHECKARG("esmerge",ii);
        if (!strcmp(argv[ii+1],"stderr"))
          redirect_output_stderr();
        else if (!strcmp(argv[ii+1],"stdout"))
          redirect_output_stdout();
        else
        {
          fprint_err("### esmerge: "
                     "Unrecognised option '%s' to -err (not 'stdout' or"
                     " 'stderr')\n",argv[ii+1]);
          return 1;
        }
        ii++;
      }
      else if (!strcmp("-verbose",argv[ii]) || !strcmp("-v",argv[ii]))
      {
        verbose = TRUE;
      }
      else if (!strcmp("-quiet",argv[ii]) || !strcmp("-q",argv[ii]))
      {
        quiet = TRUE;
      }
      else if (!strcmp("-x",argv[ii]))
      {
        debugging = TRUE;
        quiet = FALSE;
      }
      else if (!strcmp("-rate",argv[ii]))
      {
        CHECKARG("esmerge",ii);
        err = int_value("esmerge",argv[ii],argv[ii+1],TRUE,10,&audio_sample_rate);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-cd",argv[ii]))
      {
        audio_sample_rate = CD_RATE;
      }
      else if (!strcmp("-dat",argv[ii]))
      {
        audio_sample_rate = DAT_RATE;
      }
      else if (!strcmp("-vidrate",argv[ii]))
      {
        CHECKARG("esmerge",ii);
        err = int_value("esmerge",argv[ii],argv[ii+1],TRUE,10,&video_frame_rate);
        if (err) return 1;
        ii++;
      }
      else if (!strcmp("-adts",argv[ii]))
      {
        audio_type = AUDIO_ADTS;
      }
      else if (!strcmp("-l2",argv[ii]))
      {
        audio_type = AUDIO_L2;
      }
      else if (!strcmp("-ac3", argv[ii]))
      {
        audio_type = AUDIO_AC3;
      }
      else if (!strcmp("-h264",argv[ii]))
      {
        video_type = VIDEO_H264;
      }
      else if (!strcmp("-mp2adts", argv[ii]))
      {
        audio_type = AUDIO_ADTS_MPEG2;
      }
      else if (!strcmp("-mp4adts", argv[ii]))
      {
        audio_type = AUDIO_ADTS_MPEG4;
      }
      else if (!strcmp("-avs",argv[ii]))
      {
        video_type = VIDEO_AVS;
      }
      else if (!strcmp("-patpmtfreq", argv[ii]))
      {
        CHECKARG("esmerge",ii);
        err = int_value("esmerge", argv[ii], argv[ii+1], TRUE, 10, &pat_pmt_freq);
        if (err) { return 1; }
        ++ii;
      }
      else
      {
        fprint_err("### esmerge: "
                   "Unrecognised command line switch '%s'\n",argv[ii]);
        return 1;
      }
    }
    else
    {
      if (!had_video_name)
      {
        video_name = argv[ii];
        had_video_name = TRUE;
      }
      else if (!had_audio_name)
      {
        audio_name = argv[ii];
        printf("got audio name 123 %s\n",audio_name);
        had_audio_name = TRUE;
      }
      else if (!had_output_name)
      {
        output_name = argv[ii];
        had_output_name = TRUE;
      }
      else
      {
        fprint_err("### esmerge: Unexpected '%s'\n",argv[ii]);
        return 1;
      }
    }
    ii++;
  }

  if (!had_video_name)
  {
    print_err("### esmerge: No video input file specified\n");
    return 1;
  }
 /*
  if (!had_audio_name)
  {
    print_err("### esmerge: No audio input file specified\n");
    return 1;
  }*/
  if (!had_output_name)
  {
    print_err("### esmerge: No output file specified\n");
    return 1;
  }
  char output_name1[255];
  char output_name2[255];
  strcpy(output_name1, output_name);
  strcpy(output_name2, output_name);
  int num1=atoi(audio_name);
  char fileSerial1[20];
  char fileSerial2[20];
  sprintf(fileSerial1,"%d.ts", num1);
  sprintf(fileSerial2,"%d.te", num1);
  strcat(output_name1,fileSerial1);
  strcat(output_name2,fileSerial2);
  uint32_t timeElapsed=0;

  err = open_elementary_stream(video_name,&video_es);
  if (err)
  {
    print_err("### esmerge: "
              "Problem starting to read video as ES - abandoning reading\n");
    return 1;
  }

  if (video_type == VIDEO_H264)
  {
    err = build_access_unit_context(video_es,&h264_video_context);
    if (err)
    {
      print_err("### esmerge: "
                "Problem starting to read video as H.264 - abandoning reading\n");
      close_elementary_stream(&video_es);
      return 1;
    }
  }
  else if (video_type == VIDEO_AVS)
  {
    err = build_avs_context(video_es,&avs_video_context);
    if (err)
    {
      print_err("### esmerge: "
                "Problem starting to read video as H.264 - abandoning reading\n");
      close_elementary_stream(&video_es);
      return 1;
    }
  }
  else
  {
    print_err("### esmerge: Unknown video type\n");
    return 1;
  }

  /*
  audio_file = open_binary_file(audio_name,FALSE);
  if (audio_file == -1)
  {
    print_err("### esmerge: "
              "Problem opening audio file - abandoning reading\n");
    close_elementary_stream(&video_es);
    free_access_unit_context(&h264_video_context);
    free_avs_context(&avs_video_context);
    return 1;
  }*/

  err = tswrite_open(TS_W_FILE,output_name1,NULL,0,quiet,&output1);
  //err = tswrite_open(TS_W_FILE,output_name2,NULL,0,quiet,&output2);
  if (err)
  {
    fprint_err("### esmerge: "
               "Problem opening output file %s - abandoning reading\n",
               output_name);
    close_elementary_stream(&video_es);
    close_file(audio_file);
    free_access_unit_context(&h264_video_context);
    free_avs_context(&avs_video_context);
    return 1;
  }

/*  switch (audio_type)
  {
  case AUDIO_ADTS:
    audio_samples_per_frame = ADTS_SAMPLES_PER_FRAME;
    break;
  case AUDIO_L2:
    audio_samples_per_frame = L2_SAMPLES_PER_FRAME;
    break;
  case AUDIO_AC3:
    audio_samples_per_frame = AC3_SAMPLES_PER_FRAME;
    break;
  default:              // hmm - or we could give up...
    audio_samples_per_frame = ADTS_SAMPLES_PER_FRAME;
    break;
  }
*/
  if (!quiet)
  {
    fprint_msg("Reading video from %s\n",video_name);
    fprint_msg("Reading audio from %s (as %s)\n",audio_name,AUDIO_STR(audio_type));
    fprint_msg("Writing output to  %s\n",output_name);
    fprint_msg("Audio sample rate: %dHz (%.2fKHz)\n",audio_sample_rate,
               audio_sample_rate/1000.0);
    fprint_msg("Audio samples per frame: %d\n",audio_samples_per_frame);
    fprint_msg("Video frame rate: %dHz\n",video_frame_rate);
  }


  if (video_type == VIDEO_H264)
    err = merge_with_h264(h264_video_context,audio_file,output1,//output2,
                          audio_type,
                          audio_samples_per_frame,audio_sample_rate,
                          video_frame_rate,
                          pat_pmt_freq,
                          quiet,verbose,debugging,num1, &timeElapsed);
  else if (video_type == VIDEO_AVS)
    printf("disable");
    /*err = merge_with_avs(avs_video_context,audio_file,output,
                         audio_type,
                         audio_samples_per_frame,audio_sample_rate,
                         video_frame_rate,
                         pat_pmt_freq,
                         quiet,verbose,debugging);*/
  else
  {
    print_err("### esmerge: Unknown video type\n");
    return 1;
  }
  if (err)
  {
    print_err("### esmerge: Error merging video and audio streams\n");
    close_elementary_stream(&video_es);
    close_file(audio_file);
    free_access_unit_context(&h264_video_context);
    free_avs_context(&avs_video_context);
    (void) tswrite_close(output1,quiet);
    //(void) tswrite_close(output2,quiet);
    return 1;
  }

  FILE *pFileLen = fopen (output_name2,"w");
  fprintf(pFileLen, "%.2f", timeElapsed/100.0);
  fclose(pFileLen);

  close_elementary_stream(&video_es);
  close_file(audio_file);
  free_access_unit_context(&h264_video_context);
  free_avs_context(&avs_video_context);
  err = tswrite_close(output1,quiet);
  //err = tswrite_close(output2,quiet);
  if (err)
  {
    fprint_err("### esmerge: Error closing output %s\n",output_name);
    return 1;
  }
  return 0;
}
Ejemplo n.º 17
0
/*
 * Read TS packets until we have found the PCR PID for our program stream,
 * outputting packets (without using their PCR) as we go.
 *
 * - `tsreader` is the TS reader context
 * - `tswriter` is our (buffered) writer
 * - `pcr_pid` is the PID containing PCRs as indicated by the PMT
 * - `num_read` is how many TS packets we read
 * - if `max` is greater than zero, then at most `max` TS packets should
 *   be read from the input
 * - if `quiet` is true, then only error messages should be written out
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
static int find_PCR_PID(TS_reader_p  tsreader,
                        TS_writer_p  tswriter,
                        uint32_t    *pcr_pid,
                        uint32_t    *num_read,
                        int          max,
                        int          quiet)
{
  int     err;
  int     count = 0;
  byte   *data;
  uint32_t pid;
  int     payload_unit_start_indicator;
  byte   *adapt;
  int     adapt_len;
  byte   *payload;
  int     payload_len;
  int     got_PAT = FALSE;

  pidint_list_p  prog_list = NULL;
  pmt_p          pmt = NULL;
  uint32_t       pmt_pid = 0;  // safe initial value

  byte  *pat_data = NULL;
  int    pat_data_len = 0;
  int    pat_data_used = 0;

  byte  *pmt_data = NULL;
  int    pmt_data_len = 0;
  int    pmt_data_used = 0;
  int    pmt_program_number = -1;

  for (;;)
  {
    err = read_next_TS_packet(tsreader,&data);
    if (err == EOF)
    {
      fprint_err("### EOF (after %d TS packets), before finding program"
                 " information\n",count);
      if (pmt_data) free(pmt_data);
      return 1;
    }
    else if (err)
    {
      fprint_err("### Error reading TS packet %d\n",count+1);
      if (pmt_data) free(pmt_data);
      return 1;
    }
    count++;

    err = split_TS_packet(data,&pid,&payload_unit_start_indicator,
                          &adapt,&adapt_len,&payload,&payload_len);
    if (err)
    {
      fprint_err("### Error splitting TS packet %d\n",count);
      if (pmt_data) free(pmt_data);
      return 1;
    }

    // Whatever we've found, don't forget to write it out via the
    // circular buffer (and we *know* it doesn't have a PCR that is
    // useful to us, as yet)
    err = tswrite_write(tswriter,data,pid,FALSE,0);
    if (err)
    {
      fprint_err("### Error writing TS packet %d to circular buffer\n",
                 count);
      if (pmt_data) free(pmt_data);
      return 1;
    }

    if (pid == 0x0000)
    {
      if (!quiet) fprint_msg("Packet %d is PAT\n",count);
      if (payload_unit_start_indicator && pat_data)
      {
        // This is the start of a new PAT packet, but we'd already
        // started one, so throw its data away
        print_err("!!! Discarding previous (uncompleted) PAT data\n");
        free(pat_data);
        pat_data = NULL; pat_data_len = 0; pat_data_used = 0;
      }
      else if (!payload_unit_start_indicator && !pat_data)
      {
        // This is the continuation of a PAT packet, but we hadn't
        // started one yet
        print_err("!!! Discarding PAT continuation, no PAT started\n");
        continue;
      }

      err = build_psi_data(FALSE,payload,payload_len,pid,
                           &pat_data,&pat_data_len,&pat_data_used);
      if (err)
      {
        fprint_err("### Error %s PAT\n",
                   (payload_unit_start_indicator?"starting new":"continuing"));
        if (pat_data) free(pat_data);
        return 1;
      }

      // Do we need more data to complete this PAT?
      if (pat_data_len > pat_data_used)
        continue;

      err = extract_prog_list_from_pat(FALSE,pat_data,pat_data_len,&prog_list);
      if (err != 0)
      {
        free(pat_data);
        return err;
      }
      if (!quiet)
        report_pidint_list(prog_list,"Program list","Program",FALSE);

      if (prog_list->length > 1 && !quiet)
        print_msg("Multiple programs in PAT - using the first\n\n");

      pmt_pid = prog_list->pid[0];
      pmt_program_number = prog_list->number[0];

      got_PAT = TRUE;
      free_pidint_list(&prog_list);
      free(pat_data);
      pat_data = NULL; pat_data_len = 0; pat_data_used = 0;
    }
    else if (got_PAT && pid == pmt_pid)
    {
      if (!quiet)
        fprint_msg("Packet %d %s PMT with PID %04x\n",
                   count, payload_unit_start_indicator?"starts":"continues",
                   pmt_pid);

      if (payload_unit_start_indicator && pmt_data)
      {
        // This is the start of a new PMT packet, but we'd already
        // started one, so throw its data away
        print_err("!!! Discarding previous (uncompleted) PMT data\n");
        free(pmt_data);
        pmt_data = NULL; pmt_data_len = 0; pmt_data_used = 0;
      }
      else if (!payload_unit_start_indicator && !pmt_data)
      {
        // This is the continuation of a PMT packet, but we hadn't
        // started one yet
        print_err("!!! Discarding PMT continuation, no PMT started\n");
        continue;
      }

      err = build_psi_data(FALSE,payload,payload_len,pid,
                           &pmt_data,&pmt_data_len,&pmt_data_used);
      if (err)
      {
        fprint_err("### Error %s PMT\n",
                   (payload_unit_start_indicator?"starting new":"continuing"));
        if (pmt_data) free(pmt_data);
        return 1;
      }

      // Do we need more data to complete this PMT?
      if (pmt_data_len > pmt_data_used)
        continue;

      err = extract_pmt(FALSE,pmt_data,pmt_data_len,pmt_pid,&pmt);
      free(pmt_data);
      pmt_data = NULL;
      if (err) return err;

      if (pmt->program_number != pmt_program_number)
      {
        if (!quiet)
          fprint_msg("Discarding PMT program %d - looking for %d\n",
                     pmt->program_number, pmt_program_number);
        free_pmt(&pmt);
        continue;
      }

      if (!quiet)
        report_pmt(TRUE,"  ",pmt);
      *pcr_pid = pmt->PCR_pid;
      free_pmt(&pmt);
      if (!quiet)
        fprint_msg("Taking timing information from PID 0x%03x\n",*pcr_pid);
      *num_read = count;
      return 0;
    }

    if (max > 0 && count >= max)
    {
      fprint_err("### Stopping after %d TS packets, before finding program"
                 " information\n",max);
      if (pmt_data) free(pmt_data);
      return 1;
    }
  }
}
Ejemplo n.º 18
0
/*
 * Read TS packets and then output them, using the buffered approach
 * so that we read-ahead to get the next PCR, and thus have reliable
 * timing information.
 *
 * Assumes (strongly) that it is starting from the start of the file.
 *
 * - `tsreader` is the TS reader context
 * - `tswriter` is our (maybe buffered) writer
 * - if `pid_to_ignore` is non-zero, then any TS packets with that PID
 *   will not be written out (note: any PCR information in them may still
 *   be used)
 * - if `override_pcr_pid` is non-zero, then it is the PID to use for PCRs,
 *   ignoring any value found in a PMT
 * - if `max` is greater than zero, then at most `max` TS packets should
 *   be read from the input
 * - if `loop`, play the input file repeatedly (up to `max` TS packets
 *   if applicable)
 * - if `quiet` is true, then only error messages should be written out
 * - if `verbose` is true, then give extra progress messages
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
static int play_buffered_TS_packets(TS_reader_p  tsreader,
                                    TS_writer_p  tswriter,
                                    uint32_t     pid_to_ignore,
                                    uint32_t     override_pcr_pid,
                                    int          max,
                                    int          loop,
                                    int          quiet,
                                    int          verbose)
{
  int  err;
  int  total = 0;
  uint32_t count = 0;
  uint32_t pcr_pid;
  uint32_t   start_count = 0;  // which TS packet to loop from
  offset_t   start_posn = 0;

  // These are only used in the loop below, but the compiler grumbles if
  // they're uninitialised (it isn't sure if they're being set by the call
  // to read_buffered_TS_packet() or not). I don't want to have to keep
  // thinking about the compiler warning, but I also know that these values
  // *will* be set by the function, so I don't want them reinitialised
  // every time round the loop. So hoist them back up to here...
  byte    *data = NULL;
  uint32_t pid = 0;
  uint64_t pcr = 0;

  // Before we can use PCRs for timing, we need to read a PMT which tells us
  // what our video stream is (so we can get our PCRs therefrom).
  if (override_pcr_pid)
  {
    pcr_pid = override_pcr_pid;
    if (!quiet)
      fprint_msg("Forcing use of PCR PID 0x%03x (%d)\n",pcr_pid,pcr_pid);
  }
  else
  {
    err = find_PCR_PID(tsreader,tswriter,&pcr_pid,&start_count,max,quiet);
    if (err)
    {
      fprint_err("### Unable to find PCR PID for timing information\n"
                 "    Looked in first %d TS packets\n",max);
      return 1;
    }
  }

  // Once we've found that, we're ready to play our data
  err = prime_read_buffered_TS_packet(tsreader,pcr_pid);
  if (err) return 1;

  // If we're looping, remember the location of the first packet of (probable)
  // data - there's not much point rewinding before that point
  if (loop)
    start_posn = start_count * TS_PACKET_SIZE;

  count = start_count;
  for (;;)
  {
    err = read_buffered_TS_packet(tsreader,&count,&data,&pid,&pcr,
                                  max,loop,start_posn,start_count,quiet);
    if (err == EOF)  // shouldn't occur if `loop`
      break;
    else if (err)
    {
      if (tsreader->file != STDIN_FILENO)
      {
        fprint_err("### Last TS packet read was at " LLU_FORMAT "\n",
                   (uint64_t)count * TS_PACKET_SIZE);
      }
      return 1;
    }
    total ++;

    // If we've been asked to ignore this packet, we should be able to
    // just ignore it -- since all TS packets have their time associated
    // with them, we shouldn't need to send a "dummy" packet, just in
    // case it had time on it.
    if (pid_to_ignore != 0 && pid == pid_to_ignore)
      continue;

    // And write it out via the circular buffer
    err = tswrite_write(tswriter,data,pid,TRUE,pcr);
    if (err)
    {
      fprint_err("### Error writing TS packet %d to circular buffer\n",
                 count);
      return 1;
    }

    if (!quiet && verbose && total%TSPLAY_REPORT_EVERY == 0)
      fprint_msg("Transferred %d TS packets\n",total);
  }

  if (!quiet)
    fprint_msg("Transferred %d TS packet%s in total\n",total,(total==1?"":"s"));
  return 0;
}
Ejemplo n.º 19
0
/*
 * Read TS packets and then output them.
 *
 * Assumes (strongly) that it is starting from the start of the file.
 *
 * - `tsreader` is the TS reader context
 * - `tswriter` is our (maybe buffered) writer
 * - if `pid_to_ignore` is non-zero, then any TS packets with that PID
 *   will not be written out (note: any PCR information in them may still
 *   be used)
 * - if `max` is greater than zero, then at most `max` TS packets should
 *   be read from the input
 * - if `loop`, play the input file repeatedly (up to `max` TS packets
 *   if applicable)
 * - if `quiet` is true, then only error messages should be written out
 * - if `verbose` is true, then give extra progress messages
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
extern int play_TS_packets(TS_reader_p  tsreader,
                           TS_writer_p  tswriter,
                           uint32_t     pid_to_ignore,
                           int          max,
                           int          loop,
                           int          quiet,
                           int          verbose)
{
  int  err;
  int  total = 0;
  uint32_t count = 0;
  int  pcrs_used = 0;
  int  pcrs_ignored = 0;
  uint32_t pcr_pid;
  uint32_t   start_count = 0;  // which TS packet to loop from
  offset_t   start_posn = 0;

  // Before we can use PCRs for timing, we need to read a PMT which tells us
  // what our video stream is (so we can get our PCRs therefrom).
  err = find_PCR_PID(tsreader,tswriter,&pcr_pid,&start_count,max,quiet);
  if (err)
  {
    fprint_err("### Unable to find PCR PID for timing information\n"
               "    Looked in first %d TS packets\n",max);
    return 1;
  }

  // Once we've found that, we're ready to play our data

  // If we're looping, remember the location of the first packet of (probable)
  // data - there's not much point rewinding before that point
  if (loop)
    start_posn = start_count * TS_PACKET_SIZE;

  count = start_count;
  for (;;)
  {
    byte    *data;
    uint32_t pid;
    int      got_pcr;
    uint64_t pcr;

    err = read_TS_packet(tsreader,&count,&data,&pid,&got_pcr,&pcr,
                         max,loop,start_posn,start_count,quiet);
    if (err == EOF)  // shouldn't occur if `loop`
      break;
    else if (err)
    {
      if (tsreader->file != STDIN_FILENO)
      {
        fprint_err("### Last TS packet read was at " LLU_FORMAT "\n",
                   (uint64_t)count * TS_PACKET_SIZE);
      }
      return 1;
    }

    total ++;

    // We are only interested in timing information from our PCR PID stream
    if (got_pcr)
    {
      if (pid == pcr_pid)
        pcrs_used ++;
      else
      {
        pcrs_ignored ++;
        got_pcr = FALSE;
      }
    }

    if (pid_to_ignore != 0 && pid == pid_to_ignore)
    {
      // We want to "transmit" this packet, since that's the simplest
      // way of sending its timing information (if any) to the writer.
      // However, we don't want to *actually* send meaningful data.
      // The simplest thing is to ignore it if it doesn't have a PCR:
      // and otherwise, change it to a null packet, by resetting its PID.
      if (!got_pcr)
        continue;
      else
      {
        data[2]  = 0xFF;
        data[1] |= 0x1F;
      }
    }

    // And write it out via the circular buffer
    err = tswrite_write(tswriter,data,pid,got_pcr,pcr);
    if (err)
    {
      fprint_err("### Error writing TS packet %d to circular buffer\n",
                 count);
      return 1;
    }

    if (!quiet && verbose && total%TSPLAY_REPORT_EVERY == 0)
      fprint_msg("Transferred %d TS packets\n",total);
  }

  if (!quiet)
  {
    fprint_msg("Transferred %d TS packet%s in total\n",total,(total==1?"":"s"));
    fprint_msg("Used PCRs from %d packets, ignored PCRs from %d packets\n",
               pcrs_used,pcrs_ignored);
  }
  return 0;
}
Ejemplo n.º 20
0
/*
 * Report on the given file with characters representing packets
 *
 * - `ps` is the PS file we're reading
 * - if `max` is more than zero, then it is the maximum number of PS packs
 *   we want to read
 * - `verbose` is true if we want an explanation of the characters
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
static int report_ps_dots(PS_reader_p  ps,
                          int          max,
                          int          verbose)
{
  int   err;
  int   count = 0;
  int   num_packs = 0;
  offset_t posn;  // The location in the input file of the current packet
  byte  stream_id; // The packet's stream id
  int   end_of_file = FALSE;

  struct PS_packet      packet = {0};
  struct PS_pack_header header = {0};

  if (verbose)
    print_msg("Characters represent the following:\n"
           "    [    Pack header\n"
           "    H    System header\n"
           "    ]    MPEG_program_end_code\n"
           "    p<n> Private stream <n> (1 or 2)\n"
           "    v    Video stream 0\n"
           "    v<n> Video stream <n> (>0)\n"
           "    a    Audio stream 0\n"
           "    a<n> Audio stream <n> (>0)\n"
           "    M    Program stream map\n"
           "    D    Program stream directory\n"
           "    .    Padding\n"
           "    ?    Something else\n"
      );
  
  // Read the start of the first packet (we confidently expect this
  // to be a pack header)
  err = read_PS_packet_start(ps,FALSE,&posn,&stream_id);
  if (err == EOF)
  {
    print_err("### Error reading first pack header\n");
    print_err("    Unexpected end of PS at start of stream\n");
    return 1;
  }
  else if (err)
  {
    print_err("### Error reading first pack header\n");
    return 1;
  }

  if (stream_id != 0xba)
  {
    print_err("### Program stream does not start with pack header\n");
    fprint_err("    First packet has stream id %02X (",stream_id);
    print_stream_id(FALSE,stream_id);
    print_err(")\n");
    return 1;
  }

  // But given that, we can now happily loop reading in packs
  for (;;)
  {
    int  num_system_headers = 0;

    if (max > 0 && num_packs >= max)
    {
      fprint_msg("\nStopping after %d packs\n",num_packs);
      return 0;
    }

    num_packs ++;
    print_msg("[");
    fflush(stdout);
    
    err = read_PS_pack_header_body(ps,&header);
    if (err)
    {
      fprint_err("### Error reading data for pack header starting at "
                 OFFSET_T_FORMAT "\n",posn);
      return 1;
    }

    // Read (and, for the moment, at least, ignore) any system headers
    for (;;)
    {
      err = read_PS_packet_start(ps,FALSE,&posn,&stream_id);
      if (err == EOF)
      {
        end_of_file = TRUE;
        if (stream_id == 0xB9)
        {
          print_msg("]");
          fflush(stdout);
        }
        break;
      }
      else if (err)
        return 1;

      if (stream_id == 0xbb) // System header
      {
        print_msg("H");
        fflush(stdout);
        err = read_PS_packet_body(ps,stream_id,&packet);
        if (err)
        {
          fprint_err("### Error reading system header starting at "
                     OFFSET_T_FORMAT "\n",posn);
          return 1;
        }
        // For the moment, just ignore the system header content
        num_system_headers ++;
      }
      else
        break;
    }
    if (end_of_file)
      break;

    // We've finished with system headers - onto data (one fondly hopes)
    for (;;)
    {
      if (stream_id == 0xba)  // Start of the next pack
        break;

      if (stream_id == 0xBC)
        print_msg("M");
      else if (stream_id == 0xFF)
        print_msg("D");
      else if (stream_id == 0xBD)
        print_msg("p1");
      else if (stream_id == 0xBE)
        print_msg(".");
      else if (stream_id == 0xBF)
        print_msg("p2");
      else if (stream_id >= 0xC0 && stream_id <=0xDF)
      {
        int number = stream_id & 0x1F;
        if (number == 0)
          print_msg("a");
        else
          fprint_msg("a%x",number);
      }
      else if (stream_id >= 0xE0 && stream_id <= 0xEF)
      {
        int number = stream_id & 0x0F;
        if (number == 0)
          print_msg("v");
        else
          fprint_msg("v%x",number);
      }
      else
        print_msg("?");
      fflush(stdout);

      err = read_PS_packet_body(ps,stream_id,&packet);
      if (err)
      {
        fprint_err("### Error reading PS packet starting at "
                   OFFSET_T_FORMAT "\n",posn);
        return 1;
      }

      err = read_PS_packet_start(ps,FALSE,&posn,&stream_id);
      if (err == EOF)
      {
        if (stream_id == 0xB9)
        {
          print_msg("]");
          fflush(stdout);
        }
        end_of_file = TRUE;
        break;
      }
      else if (err)
        return 1;
          
    }
    if (end_of_file)
      break;
  }

  clear_PS_packet(&packet);
  fprint_msg("\nRead %d PS packet%s in %d pack%s\n",
             count,(count==1?"":"s"),
             num_packs,(num_packs==1?"":"s"));
  return 0;
}
Ejemplo n.º 21
0
/*
 * Try to decide if we *have* got program stream
 *
 * Returns 0 if nothing went wrong, 1 if something did.
 */
static int check_if_PS(int   input,
                       int   verbose,
                       int  *decided,
                       int  *result)
{
  int   err;
  byte  buf[10];
  int   stuffing_length;

  if (verbose)
  {
    print_msg("Is it Program Stream?\n");
    print_msg("  Trying to read pack header\n");
  }

  err = read_bytes(input,4,buf);
  if (err)
  {
    fprint_err("### %s trying to read start of first PS packet\n",
               (err==EOF?"EOF":"Error"));
    return 1;
  }

  if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1 || buf[3] != 0xba)
  {
    if (verbose)
      fprint_msg("  File starts %02X %02X %02X %02X, not 00 00 01 BA - not PS\n",
                 buf[0],buf[1],buf[2],buf[3]);
    return 0;
  }

  if (verbose)
    print_msg("  File starts 00 00 01 BA - could be PS,"
              " reading pack header body\n");
  
  err = read_bytes(input,8,buf);
  if (err)
  {
    fprint_err("### %s trying to read body of PS pack header\n",
               (err==EOF?"EOF":"Error"));
    return 1;
  }
  
  if ((buf[0] & 0xF0) == 0x20)
  {
    if (verbose)
      print_msg("  Looks like ISO/IEC 11171-1/MPEG-1 pack header\n");
  }
  else if ((buf[0] & 0xC0) == 0x40)
  {
    if (verbose)
      print_msg("  Looks like ISO/IEC 13818-1/H.222.0 pack header\n");
    err = read_bytes(input,2,&(buf[8]));
    if (err)
    {
      fprint_err("### %s trying to read last 2 bytes of body of PS pack header\n",
                 (err==EOF?"EOF":"Error"));
      return 1;
    }

    stuffing_length = buf[9] & 0x07;

    // And ignore that many stuffing bytes...
    if (stuffing_length > 0)
    {
      err = read_bytes(input,stuffing_length,buf);
      if (err)
      {
        fprint_err("### %s trying to read PS pack header stuffing bytes\n",
                   (err==EOF?"EOF":"Error"));
        return 1;
      }
    }
  }

  // We could check for reserved bits - maybe at another time

  if (verbose)
    print_msg("  OK, trying to read start of next packet\n");

  err = read_bytes(input,4,buf);
  if (err)
  {
    fprint_err("### %s trying to read start of next PS packet\n",
               (err==EOF?"EOF":"Error"));
    return 1;
  }

  if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1)
  {
    if (verbose)
      fprint_msg("  Next 'packet' starts %02X %02X %02X, not 00 00 01 - not PS\n",
                 buf[0],buf[1],buf[2]);
    return 0;
  }

  if (verbose)
    print_msg("  Start of second packet found at right place - looks like PS\n");

  *decided = TRUE;
  *result  = STREAM_IS_PS;
  return 0;
}