Example #1
0
/*
 * Report on TS packets with a particular PID in the given file
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
static int report_single_pid(TS_reader_p  tsreader,
                             int          max,
                             int          quiet,
                             uint32_t      just_pid)
{
  int       err;
  int       count = 0;
  int       pid_count = 0;

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

    if (max > 0 && pid_count >= max)
    {
      printf("Stopping after %d packets with PID %0x\n",max,just_pid);
      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)
    {
      fprintf(stderr,"### Error reading TS packet %d at " OFFSET_T_FORMAT
              "\n",count,tsreader->posn - TS_PACKET_SIZE);
      return 1;
    }

    count ++;

    if (pid != just_pid)
      continue;

    pid_count ++;

    if (!quiet)
    {
      printf(OFFSET_T_FORMAT_8 ": TS Packet %2d PID %04x%s\n",
             tsreader->posn - TS_PACKET_SIZE,count,pid,
             (payload_unit_start_indicator?" [pusi]":""));

      if (adapt_len > 0)
        print_data(stdout,"    Adapt",adapt,adapt_len,adapt_len);
      print_data(stdout,  "  Payload",payload,payload_len,payload_len);
    }
  }
  printf("Read %d TS packet%s, %d with PID %0x\n",
         count,(count==1?"":"s"),pid_count,just_pid);
  return 0;
}
Example #2
0
/*
 * Report on the given file
 *
 * Returns 0 if all went well, 1 if something went wrong.
 */
static int report_ts(TS_reader_p  tsreader,
                     int          max,
                     int          verbose,
                     int          show_data,
                     int          report_timing)
{
  struct timing times = {0};
  pidint_list_p prog_list = NULL;
  pmt_p         pmt = NULL;
  int           err;
  int           count = 0;
  timing_p      time_ptr = NULL;

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

  uint32_t   unfinished_pmt_pid = 0;
  byte     *pmt_data = NULL;
  int       pmt_data_len = 0;
  int       pmt_data_used = 0;

  if (report_timing)
    time_ptr = ×

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

    if (max > 0 && count >= max)
    {
      printf("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)
    {
      fprintf(stderr,"### Error reading TS packet %d at " OFFSET_T_FORMAT
              "\n",count,tsreader->posn - TS_PACKET_SIZE);
      free_pidint_list(&prog_list);
      if (pmt_data) free(pmt_data);
      return 1;
    }

    count ++;

    if (verbose)
      printf(OFFSET_T_FORMAT_8 ": TS Packet %2d PID %04x%s",
             tsreader->posn - TS_PACKET_SIZE,count,pid,
             (payload_unit_start_indicator?" [pusi]":""));

    // Report on what we may
    if (verbose)
    {
      if (pid == 0x1fff)
        printf(" PADDING - ignored\n");
      else if (pid == 0x0000)
        printf(" PAT\n");
      else if (pid == 0x0001)
        printf(" Conditional Access Table - ignored\n");
      else if (pid >= 0x0002 && pid <= 0x000F)
        printf(" RESERVED - ignored\n");
      else if (pid_in_pidint_list(prog_list,pid))
        printf(" PMT\n");
      else if (pid_in_pmt(pmt,pid))
      {
        pmt_stream_p  stream = pid_stream_in_pmt(pmt,pid);
        if (stream == NULL)
        {
          fprintf(stderr,"### Internal error: stream for PID %0x returned NULL"
                  " in PMT\n",pid);
          report_pmt(stderr,"    ",pmt);
          free_pidint_list(&prog_list);
          free_pmt(&pmt);
          if (pmt_data) free(pmt_data);
          return 1;
        }
        printf(" stream type %02x (%s)\n",
               stream->stream_type,h222_stream_type_str(stream->stream_type));
      }
      else
        printf(" stream type not identified\n");
    }

    // Ignore padding packets
    if (pid == 0x1fff)
      continue;

    // Conditional Access Tables *might* contain a PCR - do we want
    // to ignore them anyway? Well, since I've never seen one, do so for now
    if (pid == 0x0001)
      continue;

    if (report_timing)
      report_adaptation_timing(time_ptr,adapt,adapt_len,count);
    else if (verbose)
      report_adaptation_field(adapt,adapt_len);

    if (pid == 0)
    {
      if (payload_unit_start_indicator && pat_data)
      {
        // Lose any data we started but didn't complete
        free(pat_data);
        pat_data = NULL; pat_data_len = 0; pat_data_used = 0;
      }
      else if (!payload_unit_start_indicator && !pat_data)
      {
        fprintf(stderr,"!!! Discarding partial (unstarted) PAT in TS"
                " packet at " OFFSET_T_FORMAT "\n",
                tsreader->posn - TS_PACKET_SIZE);
        continue;
      }

      err = build_psi_data(verbose,payload,payload_len,pid,
                           &pat_data,&pat_data_len,&pat_data_used);
      if (err)
      {
        fprintf(stderr,"### Error %s PAT in TS packet at " OFFSET_T_FORMAT "\n",
                (payload_unit_start_indicator?"starting new":"continuing"),
                tsreader->posn - TS_PACKET_SIZE);
        free_pidint_list(&prog_list);
        if (pat_data) free(pat_data);
        return 1;
      }

      // Still need more data for this PAT
      if (pat_data_len > pat_data_used)
        continue;

      // Free any earlier program list we'd read, now we've got a new one
      free_pidint_list(&prog_list);

      err = extract_prog_list_from_pat(verbose,pat_data,pat_data_len,&prog_list);
      if (err)
      {
        fprintf(stderr,"### Error extracting program list from PAT in TS"
                " packet at " OFFSET_T_FORMAT "\n",
                tsreader->posn - TS_PACKET_SIZE);
        free_pidint_list(&prog_list);
        if (pat_data) free(pat_data);
        return 1;
      }

      if (pat_data) free(pat_data);
      pat_data = NULL; pat_data_len = 0; pat_data_used = 0;
    }
    else if (pid_in_pidint_list(prog_list,pid))
    {
      // We don't cope with interleaved PMT's with different PIDs
      if (unfinished_pmt_pid != 0 && pid != unfinished_pmt_pid)
      {
        // We're already part way through a PMT packet, but it's not
        // the same PMT as the one in this TS packet
        if (payload_unit_start_indicator)
        {
          // This is the start (and maybe also the end) of a new PMT,
          // so let's read this one
          // - actually, we don't need to do anything here, as our
          // data will get "thrown away" further down
        }
        else
        {
          // This is the continuation of another PMT - let's ignore
          // it for now and hope we'll find the rest of the one we're
          // still waiting to finish
          fprintf(stderr,"!!! Discarding partial PMT with PID %04x in TS"
                  " packet at " OFFSET_T_FORMAT ", already building PMT with PID %04x\n",
                  unfinished_pmt_pid,
                  tsreader->posn - TS_PACKET_SIZE,pid);
          continue;
        }
      }

      if (payload_unit_start_indicator && pmt_data)
      {
        // Lose any data we started but didn't complete
        free(pmt_data);
        pmt_data = NULL; pmt_data_len = 0; pmt_data_used = 0;
      }
      else if (!payload_unit_start_indicator && !pmt_data)
      {
        fprintf(stderr,"!!! Discarding partial (unstarted) PMT in TS"
                " packet at " OFFSET_T_FORMAT "\n",
                tsreader->posn - TS_PACKET_SIZE);
        continue;
      }

      err = build_psi_data(verbose,payload,payload_len,pid,
                           &pmt_data,&pmt_data_len,&pmt_data_used);
      if (err)
      {
        fprintf(stderr,"### Error %s PMT in TS packet at " OFFSET_T_FORMAT "\n",
                (payload_unit_start_indicator?"starting new":"continuing"),
                tsreader->posn - TS_PACKET_SIZE);
        free_pidint_list(&prog_list);
        free_pmt(&pmt);
        if (pmt_data) free(pmt_data);
        return 1;
      }

      // Still need more data for this PMT
      if (pmt_data_len > pmt_data_used)
      {
        unfinished_pmt_pid = pid;
        continue;
      }

      // Free any earlier PMT data we'd read, now we've got a new one
      free_pmt(&pmt);

      // Which isn't unfinished anymore
      unfinished_pmt_pid = 0;

      err = extract_pmt(verbose,pmt_data,pmt_data_len,pid,&pmt);
      if (err)
      {
        fprintf(stderr,"### Error extracting stream list from PMT in TS"
                " packet at " OFFSET_T_FORMAT "\n",
                tsreader->posn - TS_PACKET_SIZE);
        free_pidint_list(&prog_list);
        free_pmt(&pmt);
        if (pmt_data) free(pmt_data);
        return err;
      }

      if (pmt_data) free(pmt_data);
      pmt_data = NULL; pmt_data_len = 0; pmt_data_used = 0;
#if 0
      printf("PMT data read as:\n");
      report_pmt(stdout,"  ",pmt);
      printf("\n");
#endif
    }
    else if (verbose)
    {
      pmt_stream_p  stream = pid_stream_in_pmt(pmt,pid);
      int stream_type;
      if (stream == NULL)
        stream_type = -1;
      else
        stream_type = stream->stream_type;
      report_payload(show_data,stream_type,payload,payload_len,
                     payload_unit_start_indicator);
      if (!show_data && payload_unit_start_indicator)
      {
        print_data(stdout,"  Data",payload,payload_len,20);
      }
#if 0   // XXX
        print_end_of_data(stdout,"      ",payload,payload_len,20);
#endif
    }
  }
  printf("Read %d TS packet%s\n",count,(count==1?"":"s"));
  free_pidint_list(&prog_list);
  free_pmt(&pmt);
  if (pmt_data) free(pmt_data);
  return 0;
}
Example #3
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;
}