Dies ist der Cache von Google von http://lpn.rnbhq.org/mirror2/bbdmux-large.C. Es handelt sich dabei um ein Abbild der Seite, wie diese am 29. Apr. 2009 22:53:14 GMT angezeigt wurde. Die aktuelle Seite sieht mittlerweile eventuell anders aus. Weitere Informationen

Nur-Text-Version
 
/*************************************************************************
    bbDMUX by Brent Beyeler, beyeler@home.com
*************************************************************************/
  /*  This file is part of bbtools
   *    *
   *    *  This is free software; you can redistribute it and/or modify
   *    *  it under the terms of the GNU General Public License as published by
   *    *  the Free Software Foundation; either version 2 of the License, or
   *    *  (at your option) any later version.
   *    *
   *    *  This is distributed in the hope that it will be useful,
   *    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *    *  GNU General Public License for more details.
   *    *
   *    *  You should have received a copy of the GNU General Public License
   *    *  along with vobcopy; if not, write to the Free Software
   *    *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
   *    */

#include "bits.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#undef SHOW_RESYNCHS

#define MPEG_PROGRAM_END_CODE    0x000001B9
#define PACK_START_CODE          0x000001BA
#define SYSTEM_HEADER_START_CODE 0x000001BB
#define PACKET_START_CODE_PREFIX 0x000001

#define PROGRAM_STREAM_MAP       0xBC
#define PRIVATE_STREAM_1         0xBD
#define PADDING_STREAM           0xBE
#define PRIVATE_STREAM_2         0xBF
#define ECM_STREAM               0xF0
#define EMM_STREAM               0xF1
#define PROGRAM_STREAM_DIRECTORY 0xFF
#define DSMCC_STREAM             0xF2
#define ITUTRECH222TYPEE_STREAM  0xF8

#define SUBSTREAM_AC3_0          0x80
#define SUBSTREAM_AC3_8          0x87
#define SUBSTREAM_DTS_0          0x88
#define SUBSTREAM_DTS_8          0x8F
#define SUBSTREAM_PCM_0          0xA0
#define SUBSTREAM_PCM_F          0xAF
#define SUBSTREAM_SUBPIC_0       0x20
#define SUBSTREAM_SUBPIC_1F      0x3F

#define BUFFER_SIZE              32768

static unsigned char buffer[BUFFER_SIZE];
static int bufidx;
static int outfp;
static char outname[256];
bool stdoutput;

void write_buffer()
{
  if (stdoutput)
  {
    if (fwrite(buffer, sizeof(unsigned char), bufidx + 1, stdout) != bufidx + 1)
    {
      fprintf(stderr, "Error writing to stdout..");
      exit (1);
    }
    bufidx = -1;
  }
  else
  {
    if (write(outfp, buffer, bufidx + 1) != bufidx + 1)
    {
      fprintf(stderr, "Error writing to output file %s.", outname);
      exit (1);
    }
    bufidx = -1;
  }
}

void flush_buffer()
{
  if (bufidx >= 0)
    write_buffer();
}

int main(int argc, char* argv[])
{
  unsigned long i, j, PES_packet_length, PES_header_data_length;
  unsigned long PTS_DTS_flags, ESCR_flag, ES_rate_flag, DSM_trick_mode_flag;
  unsigned long additional_copy_info_flag, PES_CRC_flag, PES_extension_flag;
  unsigned long PES_private_data_flag, pack_header_field_flag;
  unsigned long program_packet_sequence_counter_flag, PSTD_buffer_flag;
  unsigned long PES_extension_flag_2, PES_extension_field_length;
  unsigned long bytes_used, encrypted;
  int substream_to_get, stream_to_get, stream_id, substream_id;
  bool firsttime = true;
  unsigned long stream_packets[256], stream_bytes[256], pack_packets;
  unsigned long system_packets;
  unsigned long ac3_bytes[8], dts_bytes[8], pcm_bytes[16], subpic_bytes[32];;
  unsigned long substream_packets[256], substream_bytes[256];
  bool streams_found[256];
  bool stream_encrypted[256];
  bool substream_encrypted[256];
  bool substreams_found[256];
  bool vob_flag, mpeg2;
  char tmpStr[256];

  for (i = 0; i < 256; i++)
  {
    streams_found[i] = false;
    stream_packets[i] = 0;
    stream_bytes[i] = 0;
    substreams_found[i] = false;
    stream_encrypted[i] = false;
    substream_encrypted[i] = false;
    substream_packets[i] = 0;
    substream_bytes[i] = 0;
  }
  for (i = 0; i < 8; i++)
  {
    ac3_bytes[i] = 0;
    dts_bytes[i] = 0;
  }
  for (i = 0; i < 16; i++)
    pcm_bytes[i] = 0;
  for (i = 0; i < 32; i++)
    subpic_bytes[i] = 0;
  pack_packets = 0;
  system_packets = 0;
  outfp = 0;
  stream_to_get = -1;
  substream_to_get = -1;
  mpeg2 = false;
  bufidx = -1;

  fprintf(stderr, "bbDMUX - version 1.7, by Brent Beyeler (beyeler@home.com)\n");
  fprintf(stderr, "  speed increases by, Apachez and Christian Vogelgsang\n\n");
  fprintf(stderr, "  stdin/stdout support by Axel Philipsenburg\n\n");
  if (argc < 2 || argc == 3)
  {
    fprintf(stderr, "bbDUMX is an MPEG program stream de-multiplexor\n\n");
    fprintf(stderr, "Usage: bbDMUX  MPEG filename  <stream id  saved name>  <substream id>\n\n");
    fprintf(stderr, "You can replace MPEG filename and/or saved name with a dash '-' to have\n");
    fprintf(stderr, "bbDMUX take input from standard input and/or write output to standard output.\n");
    fprintf(stderr, "Examples:\n");
    fprintf(stderr, "  To get a list of the stream and substream id's present in an MPEG file\n");
    fprintf(stderr, "    bbDMUX  testfile.mpg\n\n");
    fprintf(stderr, "  To save a video stream (id 0xe0) to the file video.m2v\n");
    fprintf(stderr, "    bbDMUX  testfile.m2p  0xe0  video.m2v\n\n");
    fprintf(stderr, "  To save an audio stream (id 0xc0) to the file audio.m2a\n");
    fprintf(stderr, "    bbDMUX  testfile.mpg  0xc0  audio.m2a\n\n");
    fprintf(stderr, "  To save a private 1 stream (id 0xbd) to the file private1.pvt\n");
    fprintf(stderr, "    bbDMUX  testfile.m2p  0xbd  private1.pvt\n\n");
    fprintf(stderr, "  To save an AC3 audio stream (substream 0x80) to the file audio.ac3\n");
    fprintf(stderr, "    bbDMUX  testfile.vob  0xbd  audio.ac3  0x80\n");
    fprintf(stderr, "  To write an AC3 audio stream (substream 0x80) to standard output.\n");
    fprintf(stderr, "    bbDMUX  testfile.vob  0xbd  -  0x80\n");
    fprintf(stderr, "  To write an AC3 audio stream (substream 0x80) to standard output, taken from stdin.\n");
    fprintf(stderr, "    bbDMUX  -  0xbd  -  0x80\n");
    fprintf(stderr, "  To save an AC3 audio stream (substream 0x80) to the file audio.ac3, taken from stdin.\n");
    fprintf(stderr, "    bbDMUX  -  0xbd  audio.ac3  0x80\n");
	 exit (1);
  }

  init_getbits(argv[1]);
  strcpy(tmpStr, argv[1]);
  strlwr(tmpStr);
  vob_flag = (strstr(tmpStr, ".vob") != NULL);
  if (argc > 2)
  {
    sscanf(argv[2], "0x%x", &i);
    if (i < 0 || i > 0xFF)
    {
      fprintf(stderr, "Stream ID must be in the range 0..0xFF\n");
      exit (1);
    }
    stream_to_get = i;
    if (argc > 3)
    {
      if (strcmp(argv[3],"-") == 0)
      {
        stdoutput = true;
        strcpy(outname, "stdout");
        outfp = 0;
      }
      else
      {
        stdoutput = false;
        outfp = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE );
        if (outfp == -1)
        {
          fprintf(stderr, "Unable to open %s for output\n", argv[3]);
          exit (1);
        }
        strcpy(outname, argv[3]);
      }
    }
    else
    {
      fprintf(stderr, "An output filename must be specified\n");
      exit(1);
    }

    if (argc > 4)
    {
      sscanf(argv[4], "0x%x", &i);
      if (i < 0 || i > 0xFF)
      {
        fprintf(stderr, "Substream ID must be in the range 0..0xFF\n");
        exit (1);
      }
      substream_to_get = i;
      vob_flag = true;
    }
  }
  else
    fprintf(stderr, "Scanning for stream id's, press control-c to quit ...\n");

  if (stdoutput)
  {
      if ((vob_flag) && (stream_to_get == PRIVATE_STREAM_1) && (substream_to_get > -1))
        fprintf(stderr, "Saving stream 0x%02X, substream 0x%02X to stdout...\n", stream_to_get, substream_to_get);
      else
        fprintf(stderr, "Saving stream 0x%02X to stdout....\n", stream_to_get);
  }
  else
  {
    if (outfp)
      if ((vob_flag) && (stream_to_get == PRIVATE_STREAM_1) && (substream_to_get > -1))
        fprintf(stderr, "Saving stream 0x%02X, substream 0x%02X into file %s...\n", stream_to_get, substream_to_get, argv[3]);
      else
        fprintf(stderr, "Saving stream 0x%02X into file %s...\n", stream_to_get, argv[3]);
  }

  do
  {
    i = getbits(32);
//nextpass:
    switch (i)
    {
      case PACK_START_CODE:
        pack_packets++;
        if (firsttime)
        {
          mpeg2 = look_ahead(2) == 1; // check if MPEG-1 or MPEG-2
          if (mpeg2)
            if (strcmp(argv[1],"-") == 0)
              fprintf(stderr, "\nInputstream is an MPEG-2 Program Stream\n\n");
            else
              fprintf(stderr, "\nFile %s is an MPEG-2 Program Stream\n\n", argv[1]);
          else
            if (strcmp(argv[1],"-") == 0)
              fprintf(stderr, "\nInputstream is an MPEG-1 Program Stream\n\n");
            else
              fprintf(stderr, "\nFile %s is an MPEG-1 Program Stream\n\n", argv[1]);
          firsttime = false;
        }
        if (mpeg2)
        {
          getbits(32);   // MPEG2 pack header
          getbits(32);
          getbits(13);
          i = getbits(3);
          for (j = 0; j < i; j++)
            getbits(8);  // stuffing bytes
        }
        else
        {
          getbits(32);   // MPEG1 pack header
          getbits(32);
        }
        break;

      case SYSTEM_HEADER_START_CODE:
        system_packets++;
        getbits(32);   // system header
        getbits(32);
        while (look_ahead(1) == 1)
          getbits(24); // P-STD info
        break;

      case MPEG_PROGRAM_END_CODE:
        break;

      default:
        if ((i >> 8) != PACKET_START_CODE_PREFIX)
//        {
          break;
//#ifdef SHOW_RESYNCHS
//          if (argc > 3)
//          {
//            fprintf(stderr, "\nUnknown bits in stream = 0x%08X at byte %.0f\n", i, bitcount() / 8 - 4);
//            fprintf(stderr, "\nAttempting resynch ... ");
//          }
//#endif
//          if (seek_sync(PACKET_START_CODE_PREFIX, 24))
//          {
//            i = 0x00000100 | getbits(8);
//#ifdef SHOW_RESYNCHS
//            if (argc > 3)
//              fprintf(stderr, "succesfully resynched\n");
//#endif
//            goto nextpass;
//          }
//#ifdef SHOW_RESYNCHS
//          if (argc > 3)
//            fprintf(stderr, "could not resynch\n");
//          else
//#endif
//            fprintf(stderr, "\nUnknown bits in stream = 0x%08X at byte %.0f\n", i, bitcount() / 8 - 4);
//          if (outfp)
//          {
//            flush_buffer();
//            fclose(outfp);
//          }
//          exit(1);
//        }
        stream_id = i & 0x000000FF;
        stream_packets[stream_id]++;

        PES_packet_length = getbits(16);
        encrypted = 0;
        switch (stream_id)
        {
          case PROGRAM_STREAM_MAP:
          case ECM_STREAM:
          case EMM_STREAM:
          case PROGRAM_STREAM_DIRECTORY:
          case DSMCC_STREAM:
          case ITUTRECH222TYPEE_STREAM:
          case PRIVATE_STREAM_2:
          case PADDING_STREAM:
            if (stream_id == stream_to_get)
            {
              for (j = 0; j < PES_packet_length; j++)
              {
                buffer[++bufidx] = (unsigned char)getbits(8);
                if (bufidx == BUFFER_SIZE - 1)
                  write_buffer();
              }
            }
            for (j = 0; j < PES_packet_length; j++)
              getbits(8);
            stream_bytes[stream_id] += j;
            break;

          default:
            bytes_used = 0;
            if (!mpeg2)
            {
              /* flush stuffing bytes */
              while (look_ahead(8) == 0xff)
              {
                getbits(8);
                bytes_used++;
              }

              if (look_ahead(2) == 1)
              {
                /* Get STD buffer size */
                getbits(16);
                bytes_used += 2;
              }

              if (look_ahead(4) == 2)
              {
                /* Get presentation time stamp and flag it as present in packet*/
                getbits(32);
                getbits(8);
                bytes_used += 5;
              }
              else
                if (look_ahead(4) == 3)
                {
                  /* Get presentation time stamp and decoding time stamp */
                  getbits(32);
                  getbits(8);
                  getbits(32);
                  getbits(8);
                  bytes_used += 10;
                }
                else
                {
                  if (getbits(8) != 0x0f)
                  {
                    if (strcmp(argv[1],"-") == 0)
                      fprintf(stderr, "Invalid bits in MPEG-1 inputstream.");
                    else
                      fprintf(stderr, "Invalid bits in MPEG-1 file %s.", argv[1]);
                    exit (1);
                  }
                  bytes_used++;
                }
              stream_bytes[stream_id] += PES_packet_length - bytes_used;
              if (stream_id == stream_to_get)
              {
                for (j = 0; j < PES_packet_length - bytes_used; j++)
                {
                  buffer[++bufidx] = (unsigned char)getbits(8);
                  if (bufidx == BUFFER_SIZE - 1)
                     write_buffer();
                }
              }
              else
                for (j = 0; j < PES_packet_length - bytes_used; j++)
                  getbits(8);
            }
            else
            {
              getbits(2);
              encrypted = getbits(2);   // PES_scrambling_control
              getbits(4);
              PTS_DTS_flags = getbits(2);
              ESCR_flag = get1bit();
              ES_rate_flag = get1bit();
              DSM_trick_mode_flag = get1bit();
              additional_copy_info_flag = get1bit();
              PES_CRC_flag = get1bit();
              PES_extension_flag = get1bit();
              PES_header_data_length = getbits(8);
              if (PTS_DTS_flags > 1)
              {
                getbits(32);   // PTS stamp
                getbits(8);
                bytes_used += 5;
              }
              if (PTS_DTS_flags > 2)
              {
                getbits(32);   // DTS stamp
                getbits(8);
                bytes_used += 5;
              }

              if (ESCR_flag == 1)
              {
                getbits(32);
                getbits(16);
                bytes_used += 6;
              }

              if (ES_rate_flag == 1)
              {
                getbits(24);
                bytes_used += 3;
              }

              if (DSM_trick_mode_flag == 1)
              {
                getbits(8);
                bytes_used++;
              }

              if (additional_copy_info_flag == 1)
              {
                getbits(8);
                bytes_used++;
              }

              if (PES_CRC_flag == 1)
              {
                getbits(16);
                bytes_used += 2;
              }

              if (PES_extension_flag == 1)
              {
                PES_private_data_flag = get1bit();
                pack_header_field_flag = get1bit();
                program_packet_sequence_counter_flag = get1bit();
                PSTD_buffer_flag = get1bit();
                getbits(3);
                PES_extension_flag_2 = get1bit();
                bytes_used++;

                if (PES_private_data_flag == 1)
                {
                  for (j = 0; j < 128; j++)
                    getbits(8);
                  bytes_used += 128;
                }

                if (pack_header_field_flag == 1)
                {
                  fprintf(stderr, "    pack header field flag value not allowed in program streams\n");
                  exit(1);
                }

                if (program_packet_sequence_counter_flag == 1)
                {
                  getbits(16);
                  bytes_used += 2;
                }

                if (PSTD_buffer_flag == 1)
                {
                  getbits(16);
                  bytes_used += 2;
                }

                if (PES_extension_flag_2 == 1)
                {
                  get1bit();
                  PES_extension_field_length = getbits(7);
                  bytes_used++;
                  for (j = 0; j < PES_extension_field_length; j++)
                  {
                    getbits(8);
                    bytes_used++;
                  }
                }
              }
              for (j = 0; j < PES_header_data_length - bytes_used; j++)
                getbits(8);

              substream_id = getbits(8);
              stream_bytes[stream_id] += PES_packet_length - PES_header_data_length - 3;
              if ((stream_id == PRIVATE_STREAM_1) && (vob_flag))
              {
                substream_packets[substream_id]++;
                j = PES_packet_length - PES_header_data_length - 3;
                substream_bytes[substream_id] += j;
                if ((substream_id >= SUBSTREAM_AC3_0) && (substream_id <= SUBSTREAM_AC3_8))
                  ac3_bytes[substream_id - SUBSTREAM_AC3_0] += j - 4;
                if ((substream_id >= SUBSTREAM_DTS_0) && (substream_id <= SUBSTREAM_DTS_8))
                  dts_bytes[substream_id - SUBSTREAM_DTS_0] += j - 1;
                if ((substream_id >= SUBSTREAM_PCM_0) && (substream_id <= SUBSTREAM_PCM_F))
                  pcm_bytes[substream_id - SUBSTREAM_PCM_0] += j - 1;
                if ((substream_id >= SUBSTREAM_SUBPIC_0) && (substream_id <= SUBSTREAM_SUBPIC_1F))
                  subpic_bytes[substream_id - SUBSTREAM_SUBPIC_0] += j - 1;
              }
              if (stream_id == stream_to_get)
              {
                if ((stream_id == PRIVATE_STREAM_1) && (vob_flag) && (substream_to_get > -1))
                {
                  if (substream_id == substream_to_get)
                  {
                    if ((substream_id >= SUBSTREAM_AC3_0) && (substream_id <= SUBSTREAM_AC3_8))
                      getbits(24);  // discard the 4 AC3 ident bytes
                    else
                      if ((substream_id >= SUBSTREAM_DTS_0) && (substream_id <= SUBSTREAM_DTS_8))
                        getbits(8);  // discard the substream id byte
                      else
                        if ((substream_id >= SUBSTREAM_PCM_0) && (substream_id <= SUBSTREAM_PCM_F))
                          getbits(8);  // discard the substream id byte
                        else
                          if ((substream_id >= SUBSTREAM_SUBPIC_0) && (substream_id <= SUBSTREAM_SUBPIC_1F))
                            getbits(8);  // discard the substream id byte
                          else
                          {
                            buffer[++bufidx] = (unsigned char)substream_id;
                            if (bufidx == BUFFER_SIZE - 1)
                              write_buffer();
                            for (j = 0; j < 3; j++)
                            {
                              buffer[++bufidx] = (unsigned char)getbits(8);
                              if (bufidx == BUFFER_SIZE - 1)
                                write_buffer();
                            }
                          }

                    for (j = 0; j < PES_packet_length - PES_header_data_length - 7; j++)
                    {
                      buffer[++bufidx] = (unsigned char)getbits(8);
                      if (bufidx == BUFFER_SIZE - 1)
                        write_buffer();
                    }
                  }
                  else
                    for (j = 0; j < PES_packet_length - PES_header_data_length - 4; j++)
                      getbits(8);
                }
                else
                {
                  buffer[++bufidx] = (unsigned char)substream_id;
                  if (bufidx == BUFFER_SIZE - 1)
                    write_buffer();
                  for (j = 0; j < PES_packet_length - PES_header_data_length - 4; j++)
                  {
                    buffer[++bufidx] = (unsigned char)getbits(8);
                    if (bufidx == BUFFER_SIZE - 1)
                      write_buffer();
                  }
                }
              }
              else
                for (j = 0; j < PES_packet_length - PES_header_data_length - 4; j++)
                  getbits(8);
            }
            break;
        }
        if (argc == 2)
        {
          if ((!streams_found[stream_id]) || ((vob_flag) && (stream_id == PRIVATE_STREAM_1) && (!substreams_found[substream_id])))
          {
            switch (stream_id)
            {
              case PROGRAM_STREAM_MAP:
                fprintf(stderr, "Found stream id 0x%02X  = Program Stream Map\n", stream_id);
                break;
              case PRIVATE_STREAM_1:
                if (vob_flag)
                {
                  if ((substream_id >= SUBSTREAM_AC3_0) && (substream_id <= SUBSTREAM_AC3_8))
                    fprintf(stderr, "Found stream id 0x%02X  = Private Stream 1, substream 0x%02X, AC3 Audio stream %u\n", stream_id,  substream_id, substream_id - SUBSTREAM_AC3_0);
                  else
                    if ((substream_id >= SUBSTREAM_DTS_0) && (substream_id <= SUBSTREAM_DTS_8))
                      fprintf(stderr, "Found stream id 0x%02X  = Private Stream 1, substream 0x%02X, DTS Audio stream %u\n", stream_id, substream_id, substream_id - SUBSTREAM_DTS_0);
                    else
                      if ((substream_id >= SUBSTREAM_PCM_0) && (substream_id <= SUBSTREAM_PCM_F))
                        fprintf(stderr, "Found stream id 0x%02X  = Private Stream 1, substream 0x%02X, PCM Audio stream %u\n", stream_id, substream_id, substream_id - SUBSTREAM_PCM_0);
                      else
                        if ((substream_id >= SUBSTREAM_SUBPIC_0) && (substream_id <= SUBSTREAM_SUBPIC_1F))
                          fprintf(stderr, "Found stream id 0x%02X  = Private Stream 1, substream 0x%02X, Subpicture stream %u\n", stream_id, substream_id, substream_id - SUBSTREAM_SUBPIC_0);
                        else
                          fprintf(stderr, "Found stream id 0x%02X  = Private Stream 1, substream 0x%02X\n", stream_id, substream_id);
                  substreams_found[substream_id] = true;
                }
                else
                  fprintf(stderr, "Found stream id 0x%02X  = Private Stream 1\n", stream_id);
                break;
              case PRIVATE_STREAM_2:
                fprintf(stderr, "Found stream id 0x%02X  = Private Stream 2\n", stream_id);
                break;
              case ECM_STREAM:
                fprintf(stderr, "Found stream id 0x%02X  = ECM Stream\n", stream_id);
                break;
              case EMM_STREAM:
                fprintf(stderr, "Found stream id 0x%02X  = EMM Stream\n", stream_id);
                break;
              case PROGRAM_STREAM_DIRECTORY:
                fprintf(stderr, "Found stream id 0x%02X  = Program Stream Directory\n", stream_id);
                break;
              case DSMCC_STREAM:
                fprintf(stderr, "Found stream id 0x%02X  = DSMCC Stream\n", stream_id);
                break;
              case ITUTRECH222TYPEE_STREAM:
                fprintf(stderr, "Found stream id 0x%02X  = ITU-T Rec. H.222.1 type E\n", stream_id);
                break;
              case PADDING_STREAM:
                fprintf(stderr, "Found stream id 0x%02X  = Padding Stream\n", stream_id);
                break;
              default:
                if ((stream_id >= 0xE0) && (stream_id <= 0xEF))
                  fprintf(stderr, "Found stream id 0x%02X  = Video Stream %d\n", stream_id, stream_id - 0xE0);
                else
                  if ((stream_id >= 0xC0) && (stream_id <= 0xDF))
                    fprintf(stderr, "Found stream id 0x%02X  = MPEG Audio Stream %d\n", stream_id, stream_id - 0xC0);
                  else
                    fprintf(stderr, "Found stream id 0x%02X  = other stream\n", stream_id);
            }
            streams_found[stream_id] = true;
          }
          if ((stream_id == PRIVATE_STREAM_1) && (vob_flag))
          {
            if (encrypted)
            {
              if (!substream_encrypted[substream_id])
              {
                fprintf(stderr, "Stream id 0x%02X, substream 0x%02X is encrypted\n", stream_id, substream_id);
                substream_encrypted[substream_id] = true;
              }
            }
          }
          else
          {
            if (encrypted)
            {
              if (!stream_encrypted[stream_id])
              {
                fprintf(stderr, "Stream id 0x%02X is encrypted\n", stream_id);
                stream_encrypted[stream_id] = true;
              }
            }
          }
        }
    }
  } while ((i != MPEG_PROGRAM_END_CODE) && (!end_bs()));

  fprintf(stderr, "\nSummary:\n");
  fprintf(stderr, "\nMPEG Packs = %d\n", pack_packets);
  if (system_packets)
    fprintf(stderr, "System headers = %d\n", system_packets);
  for (i = 0; i < 256; i++)
  {
    if (stream_packets[i])
    {
      switch (i)
      {
        case PROGRAM_STREAM_MAP:
          fprintf(stderr, "Program Stream Map packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        case PRIVATE_STREAM_1:
          fprintf(stderr, "Private Stream 1 packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          if (vob_flag)
          {
            for (j = 0; j < 256; j++)
            {
              if (substream_packets[j])
              {
                if ((j >= SUBSTREAM_AC3_0) && (j <= SUBSTREAM_AC3_8))
                  fprintf(stderr, "    AC3 Audio stream %u packets = %u, total bytes = %u\n", j - SUBSTREAM_AC3_0, substream_packets[j], ac3_bytes[j - SUBSTREAM_AC3_0]);
                else
                  if ((j >= SUBSTREAM_DTS_0) && (j <= SUBSTREAM_DTS_8))
                    fprintf(stderr, "    DTS Audio stream %u packets = %u, total bytes = %u\n", j - SUBSTREAM_DTS_0, substream_packets[j], dts_bytes[j - SUBSTREAM_DTS_0]);
                  else
                    if ((j >= SUBSTREAM_PCM_0) && (j <= SUBSTREAM_PCM_F))
                      fprintf(stderr, "    PCM Audio stream %u packets = %u, total bytes = %u\n", j - SUBSTREAM_PCM_0, substream_packets[j], pcm_bytes[j - SUBSTREAM_PCM_0]);
                    else
                      if ((j >= SUBSTREAM_SUBPIC_0) && (j <= SUBSTREAM_SUBPIC_1F))
                        fprintf(stderr, "    Subpicture stream %u packets = %u, total bytes = %u\n", j - SUBSTREAM_SUBPIC_0, substream_packets[j], subpic_bytes[j - SUBSTREAM_SUBPIC_0]);
                      else
                        fprintf(stderr, "    Substream 0x%02X packets = %u, total bytes = %u\n", j, substream_packets[j], substream_bytes[j]);
              }
            }
          }
          break;
        case PRIVATE_STREAM_2:
          fprintf(stderr, "Private Stream 2 packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        case ECM_STREAM:
          fprintf(stderr, "ECM Stream packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        case EMM_STREAM:
          fprintf(stderr, "EMM Stream packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        case PROGRAM_STREAM_DIRECTORY:
          fprintf(stderr, "Program Stream Directory packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        case DSMCC_STREAM:
          fprintf(stderr, "DSMCC Stream packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        case ITUTRECH222TYPEE_STREAM:
          fprintf(stderr, "ITU-T Rec. H.222.1 type E packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        case PADDING_STREAM:
          fprintf(stderr, "Padding Stream packets = %u, total bytes = %u\n", stream_packets[i], stream_bytes[i]);
          break;
        default:
          if ((i >= 0xE0) && (i <= 0xEF))
            fprintf(stderr, "Video stream %d packets = %u, total bytes = %u\n", i - 0xE0, stream_packets[i], stream_bytes[i]);
          else
            if ((i >= 0xC0) && (i <= 0xDF))
              fprintf(stderr, "MPEG Audio stream %d packets = %u, total bytes = %u\n", i - 0xC0, stream_packets[i], stream_bytes[i]);
            else
              fprintf(stderr, "Other stream 0x%02X packets = %u, total bytes = %u\n", i, stream_packets[i], stream_bytes[i]);
      }
    }
  }
  finish_getbits();
  if (outfp)
  {
    flush_buffer();
    close(outfp);
  }
  return (0);
}