Annotation of multiplexer/ts2pes.c, revision 1.2

1.1       oskar       1: /*
                      2:  * read transport stream
                      3:  * Copyright (C) 1999-2004 Christian Wolff
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify          * it under the terms of the GNU General Public License as published by
                      6:  * the Free Software Foundation; either version 2 of the License, or             * (at your option) any later version.
                      7:  *
                      8:  * This program is distributed in the hope that it will be useful,
                      9:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     10:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 * GNU General Public License for more details.
                     11:  *
                     12:  * You should have received a copy of the GNU General Public License             * along with this program; if not, write to the Free Software
                     13:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     14:  */
                     15: 
1.2     ! oskar      16: #include <stdint.h>
1.1       oskar      17: #include "ts2pes.h"
                     18: #include "crc32.h"
                     19: 
                     20: unsigned long CRC;
                     21: 
                     22: // current stream parameters
                     23: 
                     24: #define TS_packet_length 188
                     25: 
                     26: // list of TS-Programs (as linked list)
                     27: ElementaryStream *first_ES=NULL;
                     28: 
                     29: // the curent valid PAT from PID 0x0000
                     30: ProgramAssociationTable *PAT=NULL;
                     31: // the intermediate PAT while building it from PID 0x0000
                     32: ProgramAssociationTable *current_PAT,*next_PAT;
                     33: 
                     34: // the curent valid CAT from PID 0x0001
                     35: ConditionalAccessTable *CAT=NULL;
                     36: // the intermediate CAT while building it from PID 0x0001
                     37: ConditionalAccessTable *current_CAT,*next_CAT;
                     38: 
                     39: // list of Programs (as linked list)
                     40: ProgramMapTable *first_PMT=NULL, *first_nextPMT=NULL, *phantom_PMT=NULL;
                     41: 
                     42: 
                     43: // -------------------------------------------------------------- //
                     44: //   List management function for transport stream packet headers
                     45: // -------------------------------------------------------------- //
                     46: 
                     47: ElementaryStream *find_ES(unsigned int PID) {  // find TSP with this PID
                     48:   ElementaryStream *ptr=first_ES;
                     49:   while (ptr!=NULL) {
                     50:     if ((ptr->TSP!=NULL) && (ptr->TSP->PID==PID)) return ptr;
                     51:     ptr=(ElementaryStream *)ptr->next;
                     52:   }
                     53:   return ptr;
                     54: }
                     55: 
                     56: ElementaryStream *new_ES(unsigned int PID) {  // find or create TSP with this PID
                     57:   ElementaryStream *ptr=first_ES;
                     58:   while (ptr!=NULL) {
                     59:     if ((ptr->TSP!=NULL) && (ptr->TSP->PID==PID)) return ptr;
                     60:     ptr=(ElementaryStream *)ptr->next;
                     61:   }
                     62:   if (first_ES==NULL) {
                     63:     first_ES=(ElementaryStream *)malloc(sizeof(ElementaryStream));
                     64:     ptr=first_ES;
                     65:   } else {
                     66:     ptr=first_ES;
                     67:     while (ptr->next!=NULL) ptr=(ElementaryStream *)ptr->next;
                     68:     ptr->next=malloc(sizeof(ElementaryStream));
                     69:     ptr=(ElementaryStream *)ptr->next;
                     70:   }
                     71:   if (ptr==NULL) return NULL;
                     72:   ptr->next=NULL;
                     73:   ptr->TSP=(TransportStreamProgram *)malloc(sizeof(TransportStreamProgram));
                     74:   if (ptr->TSP==NULL) return NULL;
                     75:   ptr->TSP->AF=NULL;
                     76:   ptr->TSP->continuity_counter=0x0F; // For continuity. First real CC is 0x00
                     77:   ptr->TSP->PID=PID;  // set PID
                     78:   ptr->Payload=NULL;
                     79:   ptr->payload_count=0;
                     80:   ptr->payload_length=0;
                     81:   return ptr;
                     82: }
                     83: 
                     84: void kill_ES(unsigned int PID) {  // search&destroy(tm Henry Rollins) TSP with this PID
                     85:   ElementaryStream *ptr=first_ES, *ptr0=NULL;
                     86:   while (ptr!=NULL) {
                     87:     if ((ptr->TSP!=NULL) && (ptr->TSP->PID==PID)) {
                     88:       if (ptr->TSP!=NULL) free(ptr->TSP);
                     89:       if (ptr->Payload!=NULL) free(ptr->Payload);
                     90:       if (ptr0==NULL) {
                     91:         first_ES=ptr->next;
                     92:         free(ptr);
                     93:         ptr=first_ES;
                     94:       } else {
                     95:         ptr0->next=ptr->next;
                     96:         free(ptr);
                     97:         ptr=ptr0;
                     98:       }
                     99:     }
                    100:     ptr0=ptr;
                    101:     if (ptr!=NULL) ptr=(ElementaryStream *)ptr->next;
                    102:   }
                    103: }
                    104: 
                    105: 
                    106: // -------------------------------------------------------------- //
                    107: //   List management functions for program map tables
                    108: // -------------------------------------------------------------- //
                    109: 
                    110: ProgramMapTable *find_PMT(ProgramMapTable **anker, unsigned int program_number) {  // find TSP with this program_number
                    111:   ProgramMapTable *ptr=*anker;
                    112:   while (ptr!=NULL) {
                    113:     if ((ptr->program_number==program_number)) return ptr;
                    114:     ptr=(ProgramMapTable *)ptr->next;
                    115:   }
                    116:   return ptr;
                    117: }
                    118: 
                    119: ProgramMapTable *new_PMT(ProgramMapTable **anker, unsigned int program_number) {  // find or create TSP with this program_number
                    120:   int i;
                    121:   ProgramMapTable *ptr=*anker;
                    122:   while (ptr!=NULL) {
                    123:     if ((ptr->program_number==program_number)) return ptr;
                    124:     ptr=(ProgramMapTable *)ptr->next;
                    125:   }
                    126:   if (*anker==NULL) {
                    127:     *anker=(ProgramMapTable *)malloc(sizeof(ProgramMapTable));
                    128:     ptr=*anker;
                    129:   } else {
                    130:     ptr=*anker;
                    131:     while (ptr->next!=NULL) ptr=(ProgramMapTable *)ptr->next;
                    132:     ptr->next=malloc(sizeof(ProgramMapTable));
                    133:     ptr=(ProgramMapTable *)ptr->next;
                    134:   }
                    135:   if (ptr==NULL) return NULL;
                    136:   ptr->next=NULL;
                    137:   ptr->descriptor_count=0;
                    138:   for (i=0; i<16; i++) ptr->descriptor[i]=NULL;
                    139:   ptr->program_count=0;
                    140:   for (i=0; i<256; i++) ptr->program[i]=NULL;
                    141:   ptr->program_number=program_number;  // set program_number
                    142:   return ptr;
                    143: }
                    144: 
                    145: void kill_PMT(ProgramMapTable **anker, unsigned int program_number) {  // search&destroy(tm Henry Rollins) TSP with this program_number
                    146:   ProgramMapTable *ptr=*anker, *ptr0=NULL;
                    147:   int i,j;
                    148:   while (ptr!=NULL) {
                    149:     if ((ptr->program_number==program_number)) {
                    150:       if (ptr0==NULL) {
                    151:         *anker=(ProgramMapTable *)ptr->next;
                    152:         ptr0=*anker;
                    153:       } else {
                    154:         ptr0->next=ptr->next;
                    155:       }
                    156:       for (i=0; i<16; i++) if (ptr->descriptor[i]!=NULL) {
                    157:         if (ptr->descriptor[i]->data!=NULL) free(ptr->descriptor[i]->data);
                    158:         free(ptr->descriptor[i]);
                    159:       }
                    160:       for (i=0; i<256; i++) if (ptr->program[i]!=NULL) {
                    161:         for (j=0; j<16; j++) if (ptr->program[i]->descriptor[j]!=NULL) {
                    162:           if (ptr->program[i]->descriptor[j]->data!=NULL) free(ptr->program[i]->descriptor[j]->data);
                    163:           free(ptr->program[i]->descriptor[j]);
                    164:         }
                    165:         free(ptr->program[i]);
                    166:       }
                    167:       free(ptr);
                    168:       ptr=ptr0;
                    169:     }
                    170:     ptr0=ptr;
                    171:     if (ptr!=NULL) ptr=(ProgramMapTable *)ptr->next;
                    172:   }
                    173: }
                    174: 
                    175: 
                    176: // -------------------------------------------------------------- //
                    177: //   debug output of header information
                    178: // -------------------------------------------------------------- //
                    179: 
                    180: void print_TP(TransportStreamProgram *TP) {  // debug output of TP-Header
                    181:   printf("- Transport Packet Header -\n\
                    182: transport_error_indicator:     %i\n\
                    183: payload_unit_start_indicator:  %i\n\
                    184: transport_priority:            %i\n\
                    185: PID:                           0x%04X\n\
                    186: transport_scrambling_control:  0x%02X\n\
                    187: adaption_field_control_1:      %i\n\
                    188: adaption_field_control_0:      %i\n\
                    189: continuity_counter:            0x%02X\n\
                    190: \n",
                    191:     ((TP->transport_error_indicator)?1:0),
                    192:     ((TP->payload_unit_start_indicator)?1:0),
                    193:     ((TP->transport_priority)?1:0),
                    194:     TP->PID,
                    195:     TP->transport_scrambling_control,
                    196:     ((TP->adaption_field_control_1)?1:0),
                    197:     ((TP->adaption_field_control_0)?1:0),
                    198:     TP->continuity_counter
                    199:   );
                    200: }
                    201: 
                    202: void print_AF(AdaptionField *AF) {  // debug output of AF
                    203:   int i;
                    204:   printf("- Adaption Field -\n\
                    205: discontinuity_indicator:               %i\n\
                    206: random_access_indicator:               %i\n\
                    207: elementary_stream_priority_indicator:  %i\n\
                    208: PCR_flag:                              %i\n\
                    209: OPCR_flag:                             %i\n\
                    210: splicing_point_flag:                   %i\n\
                    211: transport_private_data_flag:           %i\n\
                    212: adaption_field_extension_flag:         %i\n",
                    213:     ((AF->discontinuity_indicator)?1:0),
                    214:     ((AF->random_access_indicator)?1:0),
                    215:     ((AF->elementary_stream_priority_indicator)?1:0),
                    216:     ((AF->PCR_flag)?1:0),
                    217:     ((AF->OPCR_flag)?1:0),
                    218:     ((AF->splicing_point_flag)?1:0),
                    219:     ((AF->transport_private_data_flag)?1:0),
                    220:     ((AF->adaption_field_extension_flag)?1:0));
                    221:   if (AF->PCR_flag) printf("\
                    222: program_clock_reference_base:          %lld\n\
                    223: program_clock_reference_extension:     %d\n",
                    224:     AF->program_clock_reference_base,
                    225:     AF->program_clock_reference_extension);
                    226:   if (AF->OPCR_flag) printf("\
                    227: original_program_clock_reference_base: %lld\n\
                    228: original_program_clock_reference_extension: %d\n",
                    229:     AF->original_program_clock_reference_base,
                    230:     AF->original_program_clock_reference_extension);
                    231:   if (AF->splicing_point_flag) printf("SC:    %i\n",
                    232:     AF->splice_countdown);
                    233:   if (AF->transport_private_data_flag) {
                    234:     printf("\
                    235: transport_private_data_length:         %i\n",
                    236:       AF->transport_private_data_length);
                    237:     for (i=0; i<AF->transport_private_data_length; i++) {
                    238:       printf("%02X ",(AF->private_data_byte[i] & 0xFF));
                    239:       if (((i % 24)==23) || (i == AF->transport_private_data_length-1)) printf("\n");
                    240:     }
                    241:   }
                    242:   if (AF->adaption_field_extension_flag) {
                    243:     printf("\
                    244: adaption_field_extension_length:       %i\n\
                    245: ltw_flag:                              %i\n\
                    246: piecewise_rate_flag:                   %i\n\
                    247: seamless_splice_flag:                  %i\n",
                    248:       AF->adaption_field_extension_length,
                    249:       ((AF->ltw_flag)?1:0),
                    250:       ((AF->piecewise_rate_flag)?1:0),
                    251:       ((AF->seamless_splice_flag)?1:0));
                    252:     if (AF->ltw_flag) {
                    253:       printf("\
                    254: ltw_valid_flag:                        %i\n\
                    255: ltw_offset:                            %i\n",
                    256:         ((AF->ltw_valid_flag)?1:0),
                    257:         AF->ltw_offset);
                    258:     }
                    259:     if (AF->piecewise_rate_flag) {
                    260:       printf("\
                    261: piecewise_rate:                        %i\n",
                    262:         AF->piecewise_rate);
                    263:     }
                    264:     if (AF->seamless_splice_flag) {
                    265:       printf("\
                    266: splice_type:                           0x%01X\n\
                    267: DTS_next_AU:                           %lld\n",
                    268:         AF->splice_type,
                    269:         AF->DTS_next_AU);
                    270:     }
                    271:   }
                    272:   printf("\n");
                    273: }
                    274: 
                    275: void print_PAT(ProgramAssociationTable *PAT) {  // debug output of PAT
                    276:   int i;
                    277:   printf("- Program Association Table -\n\
                    278: table_id:                  %i\n\
                    279: section_syntax_indicator:  %i\n\
                    280: private_indicator:         %i\n\
                    281: section_length:            %i\n\
                    282: transport_stream_id:       0x%04X\n\
                    283: version_number:            %i\n\
                    284: current_next_indicator:    %i\n\
                    285: section_number:            %i\n\
                    286: last_section_number:       %i\n\
                    287: Table Size:                %i\n\
                    288:   PN     PID\n",
                    289:     PAT->table_id,
                    290:     ((PAT->section_syntax_indicator)?1:0),
                    291:     ((PAT->private_indicator)?1:0),
                    292:     PAT->section_length,
                    293:     PAT->transport_stream_id,
                    294:     PAT->version_number,
                    295:     ((PAT->current_next_indicator)?1:0),
                    296:     PAT->section_number,
                    297:     PAT->last_section_number,
                    298:     PAT->program_count);
                    299:   for (i=0; i<PAT->program_count; i++) {
                    300:     printf("  0x%04X 0x%04X\n",PAT->program_number[i],PAT->PID[i]);
                    301:   }
                    302:   printf("\n");
                    303: }
                    304: 
                    305: void print_CAT(ConditionalAccessTable *CAT) {  // debug output of CAT
                    306:   int i;
                    307:   printf("- Conditional Access Table -\n\
                    308: table_id:                  %i\n\
                    309: section_syntax_indicator:  %i\n\
                    310: private_indicator:         %i\n\
                    311: section_length:            %i\n\
                    312: version_number:            %i\n\
                    313: current_next_indicator:    %i\n\
                    314: section_number:            %i\n\
                    315: last_section_number:       %i\n\
                    316: Table Size:                %i\n\
                    317:   SysID  CA_PID\n",
                    318:     CAT->table_id,
                    319:     ((CAT->section_syntax_indicator)?1:0),
                    320:     ((CAT->private_indicator)?1:0),
                    321:     CAT->section_length,
                    322:     CAT->version_number,
                    323:     ((CAT->current_next_indicator)?1:0),
                    324:     CAT->section_number,
                    325:     CAT->last_section_number,
                    326:     CAT->descriptor_count);
                    327:   for (i=0; i<CAT->descriptor_count; i++) {
                    328:     printf("\
                    329:   0x%04X 0x%04X",
                    330:       CAT->CA_descriptor[i]->CA_system_ID,
                    331:       CAT->CA_descriptor[i]->CA_PID);
                    332:     show_descriptor(CAT->CA_descriptor[i]->descriptor,1);
                    333:     printf("\n");
                    334:   }
                    335:   printf("\n");
                    336: }
                    337: 
                    338: void print_PMT(ProgramMapTable *PMT) {  // debug output of PMT
                    339:   int i,j;
                    340:   Program *prog;           // temp. pointer
                    341:   printf("- Program Map Table -\n\
                    342: table_id:                  %i\n\
                    343: section_syntax_indicator:  %i\n\
                    344: private_indicator:         %i\n\
                    345: section_length:            %i\n\
                    346: program_number:            0x%04X\n\
                    347: version_number:            %i\n\
                    348: current_next_indicator:    %i\n\
                    349: section_number:            %i\n\
                    350: last_section_number:       %i\n\
                    351: PCR_PID:                   0x%04X\n\
                    352: Table Size:                %i\n\
                    353:   type PID\n",
                    354:     PMT->table_id,
                    355:     ((PMT->section_syntax_indicator)?1:0),
                    356:     ((PMT->private_indicator)?1:0),
                    357:     PMT->section_length,
                    358:     PMT->program_number,
                    359:     PMT->version_number,
                    360:     ((PMT->current_next_indicator)?1:0),
                    361:     PMT->section_number,
                    362:     PMT->last_section_number,
                    363:     PMT->PCR_PID,
                    364:     PMT->program_count);
                    365:   for (i=0; i<PMT->descriptor_count; i++) {
                    366:     show_descriptor(PMT->descriptor[i],1);
                    367:   }
                    368:   for (i=0; i<PMT->program_count; i++) {
                    369:     prog=PMT->program[i];
                    370:     printf("  0x%02X 0x%04X\n",prog->stream_type,prog->elementary_PID);
                    371:     for (j=0; j<prog->descriptor_count; j++) {
                    372:       show_descriptor(prog->descriptor[j],1);
                    373:     }
                    374:   }
                    375:   printf("\n");
                    376: }
                    377: 
                    378: void print_TSP(TransportStreamProgram *TSP) {  // debug output of whole TP
                    379:   print_TP(TSP);
                    380:   if (TSP->AF!=NULL) print_AF(TSP->AF);
                    381: }
                    382: 
                    383: 
                    384: // -------------------------------------------------------------- //
                    385: //   parsing of one PSI, collected from the TS-packet payload
                    386: // -------------------------------------------------------------- //
                    387: 
                    388: int parse_PSI(ElementaryStream *ES, unsigned int PSI, int verbose, int useCRC) {
                    389:   // header data for all PSI's
                    390:   unsigned char table_id;                 // Table ID
                    391:   unsigned int  section_syntax_indicator, // Section Syntax Indicator
                    392:                 private_indicator,        // Private Indicator
                    393:                 section_length,           // Section Length
                    394:                 PSI_word;                 // Transport Stream ID / Program Number / Table ID Extension
                    395:   unsigned char version_number;           // Version Number
                    396:   unsigned int  current_next_indicator,   // Current/Next Indicator
                    397:                 section_number,           // Section Number
                    398:                 last_section_number;      // Last Section Number
                    399: 
                    400:   ProgramMapTable *PMT, *ptr;  // current PMT
                    401: 
                    402:   int i,j,n,               // counters
                    403:       program_info_length, // ProgramInformationLength
                    404:       ES_info_length,      // ESinfolength
                    405:       desc_length;         // descriptor length
                    406:   unsigned char ch,        // single byte
                    407:       desc_tag;            // descriptor tag
                    408:   Program *prog;           // temp. pointer
                    409: 
                    410:   table_id=ES->Payload[0];
                    411:   section_syntax_indicator=ES->Payload[1] & 0x80;
                    412:   private_indicator=ES->Payload[1] & 0x40;
                    413:   section_length=((ES->Payload[1] << 8) | (ES->Payload[2] & 0xFF)) & 0x0FFF;
                    414:   if (section_syntax_indicator) {
                    415:     PSI_word=((ES->Payload[3] << 8) | (ES->Payload[4] & 0xFF)) & 0xFFFF;
                    416:     version_number=(ES->Payload[5] & 0x3E) >> 1;
                    417:     current_next_indicator=ES->Payload[5] & 0x01;  
                    418:     section_number=ES->Payload[6] & 0xFF;   
                    419:     last_section_number=ES->Payload[7] & 0xFF;  
                    420:   } else {
                    421:     PSI_word=0;
                    422:     version_number=0;
                    423:     current_next_indicator=0;  
                    424:     section_number=0;   
                    425:     last_section_number=0;  
                    426:   }
                    427: 
                    428:   if (section_length+3 > ES->payload_count) {
                    429:     if (verbose) printf("ERROR in PSI-header, section length shows %i byte, but there are only %i\n",
                    430:       section_length+3,
                    431:       ES->payload_count);
                    432:     return 0x0104;
                    433:   }
                    434:   if (section_syntax_indicator) 
                    435:     CRC=update_crc_32_block(CRC_INIT_32,ES->Payload,section_length+3);
                    436:   
                    437:   if (verbose) {
                    438:     printf("PSI Section: %i bytes\n",section_length+3);
                    439:     for (i=0; i<section_length+3; i++) {
                    440:       printf("%02X ",(ES->Payload[i] & 0xFF));
                    441:       if ((i % 24)==23) printf("\n");
                    442:     }
                    443:     printf("\n");
                    444:     if (section_syntax_indicator) 
                    445:       printf("CRC of section %i: 0x%08lX - %s\n",
                    446:         section_number,
                    447:         CRC,
                    448:         ((CRC==0x00000000L)?"OK":"NG"));  // if you do it wrong, you get CRC==0xC704DD7BL
                    449:   }
                    450: 
                    451:   if (section_syntax_indicator && CRC) {  // CRC error
                    452:     if (verbose) printf("ERROR in PSI - CRC error (0x%08lX)\n",CRC);
                    453:     if (useCRC) return 0x0204;
                    454:   }
                    455:   
                    456:   if (PSI==1) {  // This is a PAT
                    457:     if (table_id!=0x00) {
                    458:       if (verbose) printf("- WRONG Table ID 0x%02X in section, PSI-type=%i!\n",table_id,PSI);
                    459:       if (useCRC) return 0x0304;
                    460:     }
                    461:     if (!section_syntax_indicator || private_indicator) {
                    462:       if (verbose) printf("- SYNTAX error in section, PSI-type=%i!\n",PSI);
                    463:       if (useCRC) return 0x0404;
                    464:     }
                    465:     next_PAT->table_id=table_id;
                    466:     next_PAT->section_syntax_indicator=section_syntax_indicator;
                    467:     next_PAT->private_indicator=private_indicator;
                    468:     next_PAT->section_length=section_length;
                    469:     next_PAT->transport_stream_id=PSI_word;
                    470:     next_PAT->version_number=version_number;
                    471:     next_PAT->current_next_indicator=current_next_indicator;
                    472:     next_PAT->section_number=section_number;
                    473:     next_PAT->last_section_number=last_section_number;
                    474:     i=8;
                    475:     while (i+4<section_length) {
                    476:       ch=ES->Payload[i++];  // you'll never know the evaluation order...
                    477:       next_PAT->program_number[next_PAT->program_count]=((ch << 8) | (ES->Payload[i++] & 0xFF)) & 0xFFFF;
                    478:       ch=ES->Payload[i++];
                    479:       next_PAT->PID[next_PAT->program_count++]=((ch << 8) | (ES->Payload[i++] & 0xFF)) & 0x1FFF;
                    480:     }
                    481:     if (verbose) print_PAT(next_PAT);
                    482:     if (current_next_indicator && (section_number==last_section_number)) {  // our new PAT has completely arrived
                    483:       PAT=next_PAT;
                    484:       next_PAT=current_PAT;
                    485:       current_PAT=PAT;
                    486:       next_PAT->program_count=0;
                    487:     }
                    488:     
                    489:   } else if (PSI==2) {  // CAT
                    490:     //if (verbose) printf("- Conditional Access Table -\n\n");
                    491:     if (table_id!=0x01) {
                    492:       if (verbose) printf("- WRONG Table ID 0x%02X in section, PSI-type=%i!\n",table_id,PSI);
                    493:       if (useCRC) return 0x0304;
                    494:     }
                    495:     if (!section_syntax_indicator || private_indicator) {
                    496:       if (verbose) printf("- SYNTAX error in section, PSI-type=%i!\n",PSI);
                    497:       if (useCRC) return 0x0404;
                    498:     }
                    499:     next_CAT->table_id=table_id;
                    500:     next_CAT->section_syntax_indicator=section_syntax_indicator;
                    501:     next_CAT->private_indicator=private_indicator;
                    502:     next_CAT->section_length=section_length;
                    503:     next_CAT->version_number=version_number;
                    504:     next_CAT->current_next_indicator=current_next_indicator;
                    505:     next_CAT->section_number=section_number;
                    506:     next_CAT->last_section_number=last_section_number;
                    507:     i=8; 
                    508:     while ((i+2<=section_length) && (next_CAT->descriptor_count<256)) {
                    509:       n=next_CAT->descriptor_count;
                    510:       if (next_CAT->CA_descriptor[n]==NULL) {
                    511:         next_CAT->CA_descriptor[n]=(ConditionalAccessDescriptor *)malloc(sizeof(ConditionalAccessDescriptor));
                    512:         next_CAT->CA_descriptor[n]->descriptor=NULL;
                    513:       }
                    514:       desc_tag=ES->Payload[i++];
                    515:       desc_length=ES->Payload[i++] & 0xFF;
                    516:       if (next_CAT->CA_descriptor[n]==NULL) {
                    517:         next_CAT->CA_descriptor[n]->descriptor=(Descriptor *)malloc(sizeof(Descriptor));
                    518:         next_CAT->CA_descriptor[n]->descriptor->data=NULL;
                    519:       }
                    520:       next_CAT->CA_descriptor[n]->descriptor->tag=desc_tag;
                    521:       next_CAT->CA_descriptor[n]->descriptor->length=desc_length;
                    522:       if (desc_length>0) {
                    523:         if (i+desc_length>n) {
                    524:           if (verbose) printf("ERROR: insufficent data in descriptor\n");
                    525:           if (useCRC) return 0x0704;
                    526:         }
                    527:         next_CAT->CA_descriptor[n]->descriptor->data=(unsigned char *)realloc(next_CAT->CA_descriptor[n]->descriptor->data,desc_length*sizeof(unsigned char));
                    528:         for (j=0; j<desc_length; j++) {
                    529:           next_CAT->CA_descriptor[n]->descriptor->data[j]=ES->Payload[i++];
                    530:         }
                    531:         if (desc_length>=2) next_CAT->CA_descriptor[n]->CA_system_ID=((next_CAT->CA_descriptor[n]->descriptor->data[0] << 8) | (next_CAT->CA_descriptor[n]->descriptor->data[1] & 0xFF)) & 0xFFFF;
                    532:         else next_CAT->CA_descriptor[n]->CA_system_ID=0;
                    533:         if (desc_length>=4) next_CAT->CA_descriptor[n]->CA_PID=((next_CAT->CA_descriptor[n]->descriptor->data[2] << 8) | (next_CAT->CA_descriptor[n]->descriptor->data[3] & 0xFF)) & 0x1FFF;
                    534:         else next_CAT->CA_descriptor[n]->CA_PID=0x1FFF;
                    535:       }
                    536:       next_CAT->descriptor_count++;
                    537:     }
                    538: 
                    539: /*    
                    540:     while (i+4<section_length) {
                    541:       next_CAT->descriptor[next_CAT->descriptor_count].descriptor_tag=ES->Payload[i++];
                    542:       next_CAT->descriptor[next_CAT->descriptor_count].descriptor_length=ES->Payload[i++];
                    543:       ch=ES->Payload[i++]; 
                    544:       next_CAT->descriptor[next_CAT->descriptor_count].CA_system_ID=((ch << 8) | (ES->Payload[i++] & 0xFF)) & 0xFFFF;
                    545:       ch=ES->Payload[i++]; 
                    546:       next_CAT->descriptor[next_CAT->descriptor_count].CA_PID=((ch << 8) | (ES->Payload[i++] & 0xFF)) & 0x1FFF;
                    547:       next_CAT->descriptor[next_CAT->descriptor_count].descriptor_tag=ES->Payload[i++];
                    548:       n=next_CAT->descriptor[next_CAT->descriptor_count].descriptor_length;
                    549:       if (n>4) {
                    550:         next_CAT->descriptor[next_CAT->descriptor_count].private_data_length=n-4;
                    551:         next_CAT->descriptor[next_CAT->descriptor_count].private_data_byte=(char *)malloc(n-4);
                    552:         for (j=0; j<n-4; j++)
                    553:           next_CAT->descriptor[next_CAT->descriptor_count].private_data_byte[j]=ES->Payload[i++];
                    554:       } else next_CAT->descriptor[next_CAT->descriptor_count].private_data_length=0;
                    555:       next_CAT->descriptor_count++;
                    556:     }
                    557: */
                    558:     
                    559:     if (verbose) print_CAT(next_CAT);
                    560:     if (current_next_indicator && (section_number==last_section_number)) {  // our new CAT has completely arrived
                    561:       CAT=next_CAT;
                    562:       next_CAT=current_CAT;
                    563:       current_CAT=CAT;
                    564:       next_CAT->descriptor_count=0;
                    565:     }
                    566:     
                    567:   } else if (PSI==3) {  // PMT
                    568:     if (table_id!=0x02) {
                    569:       if (verbose) printf("- WRONG Table ID 0x%02X in section, PSI-type=%i!\n",table_id,PSI);
                    570:       if (useCRC) return 0x0304;
                    571:     }
                    572:     if (!section_syntax_indicator || private_indicator) {
                    573:       if (verbose) printf("- SYNTAX error in section, PSI-type=%i!\n",PSI);
                    574:       if (useCRC) return 0x0404;
                    575:     }
                    576:     PMT=new_PMT(&first_nextPMT,PSI_word);
                    577:     if (PMT==NULL) return 0x0503;
                    578:     PMT->table_id=table_id;
                    579:     PMT->section_syntax_indicator=section_syntax_indicator;
                    580:     PMT->private_indicator=private_indicator;
                    581:     PMT->section_length=section_length;
                    582:     PMT->program_number=PSI_word;
                    583:     PMT->version_number=version_number;
                    584:     PMT->current_next_indicator=current_next_indicator;
                    585:     PMT->section_number=section_number;
                    586:     PMT->last_section_number=last_section_number;
                    587:     PMT->PCR_PID=((ES->Payload[8] << 8) | (ES->Payload[9] & 0xFF)) & 0x1FFF;
                    588:     program_info_length=((ES->Payload[10] << 8) | (ES->Payload[11] & 0xFF)) & 0x0FFF;
                    589:     i=12; n=i+program_info_length;
                    590:     while ((i+2<=n) && (PMT->descriptor_count<16)) {
                    591:       desc_tag=ES->Payload[i++];
                    592:       desc_length=ES->Payload[i++] & 0xFF;
                    593:       if (PMT->descriptor[PMT->descriptor_count]==NULL) {
                    594:         PMT->descriptor[PMT->descriptor_count]=(Descriptor *)malloc(sizeof(Descriptor));
                    595:         PMT->descriptor[PMT->descriptor_count]->data=NULL;
                    596:       }
                    597:       PMT->descriptor[PMT->descriptor_count]->tag=desc_tag;
                    598:       PMT->descriptor[PMT->descriptor_count]->length=desc_length;
                    599:       if (desc_length>0) {
                    600:         if (i+desc_length>n) {
                    601:           if (verbose) printf("ERROR: insufficent data in descriptor %i+%i>=%i\n",i,desc_length,n);
                    602:           if (useCRC) return 0x0604;
                    603:         }
                    604:         PMT->descriptor[PMT->descriptor_count]->data=(unsigned char *)realloc(PMT->descriptor[PMT->descriptor_count]->data,desc_length*sizeof(unsigned char));
                    605:         for (j=0; j<desc_length; j++) {
                    606:           PMT->descriptor[PMT->descriptor_count]->data[j]=ES->Payload[i++];
                    607:         }
                    608:       }
                    609:       PMT->descriptor_count++;
                    610:     }
                    611:     i=n;
                    612:     while ((i+4<section_length) && (PMT->program_count<256)) {
                    613:       prog=PMT->program[PMT->program_count];
                    614:       if (prog==NULL) {
                    615:         prog=(Program *)malloc(sizeof(Program));
                    616:         PMT->program[PMT->program_count]=prog;
                    617:         prog->descriptor_count=0;
                    618:         for (j=0; j<16; j++) prog->descriptor[j]=NULL;
                    619:       }
                    620:       prog->stream_type=ES->Payload[i++];
                    621:       ch=ES->Payload[i++];  // you'll never know the evaluation order...
                    622:       prog->elementary_PID=((ch << 8) | (ES->Payload[i++] & 0xFF)) & 0x1FFF;
                    623:       ch=ES->Payload[i++];
                    624:       ES_info_length=((ch << 8) | (ES->Payload[i++] & 0xFF)) & 0x0FFF;
                    625:       n=i+ES_info_length;
                    626:       while ((i+2<=n) && (prog->descriptor_count<16)) {
                    627:         desc_tag=ES->Payload[i++];
                    628:         desc_length=ES->Payload[i++] & 0xFF;
                    629:         if (prog->descriptor[prog->descriptor_count]==NULL) {
                    630:           prog->descriptor[prog->descriptor_count]=(Descriptor *)malloc(sizeof(Descriptor));
                    631:           prog->descriptor[prog->descriptor_count]->data=NULL;
                    632:         }
                    633:         prog->descriptor[prog->descriptor_count]->tag=desc_tag;
                    634:         prog->descriptor[prog->descriptor_count]->length=desc_length;
                    635:         if (desc_length>0) {
                    636:           if (i+desc_length>n) {
                    637:             if (verbose) printf("ERROR: insufficent data in descriptor %i+%i>=%i\n",i,desc_length,n);
                    638:             if (useCRC) return 0x0704;
                    639:           }
                    640:           prog->descriptor[prog->descriptor_count]->data=(unsigned char *)realloc(prog->descriptor[prog->descriptor_count]->data,desc_length*sizeof(unsigned char));
                    641:           for (j=0; j<desc_length; j++) {
                    642:             prog->descriptor[prog->descriptor_count]->data[j]=ES->Payload[i++];
                    643:           }
                    644:         }
                    645:         prog->descriptor_count++;
                    646:       }
                    647:       PMT->program_count++;
                    648:       i=n;
                    649:     }
                    650:     if (verbose) print_PMT(PMT);
                    651:     if (current_next_indicator && (section_number==last_section_number)) {  // our new PMT has completely arrived
                    652:       kill_PMT(&first_PMT,PMT->program_number);  // kill outdated PMT
                    653:       ptr=first_PMT;  // move PMT from "next" to "current" list
                    654:       if (first_PMT==NULL) {
                    655:         first_PMT=PMT;
                    656:       } else {
                    657:         ptr=first_PMT;
                    658:         while (ptr->next!=NULL) ptr=(ProgramMapTable *)ptr->next;
                    659:         ptr->next=PMT;
                    660:       }
                    661:       if (first_nextPMT==PMT) {
                    662:         first_nextPMT=PMT->next;
                    663:       } else {
                    664:         ptr=first_nextPMT;
                    665:         while (ptr!=NULL) {
                    666:           if ((ptr->next==PMT)) {
                    667:             ptr->next=PMT->next;
                    668:           }
                    669:           ptr=(ProgramMapTable *)ptr->next;
                    670:         }
                    671:       }
                    672:       PMT->next=NULL;
                    673:     }
                    674:     
                    675:   } else if (PSI==4) {  // NIT
                    676:     if ((table_id<0x40) || (table_id>0xFE)) {
                    677:       if (verbose) printf("- WRONG Table ID 0x%02X in section, PSI-type=%i!\n",table_id,PSI);
                    678:       if (useCRC) return 0x0304;
                    679:     }
                    680:     if (!private_indicator) {
                    681:       if (verbose) printf("- SYNTAX error in section, PSI-type=%i!\n",PSI);
                    682:       if (useCRC) return 0x0404;
                    683:     }
                    684:     if (verbose) printf("- Network Information Table -\n\n");
                    685:   } else if (verbose) printf("- Internal error, Unknown PSI-id 0x%02X, table_id 0x%02X.\n",PSI,table_id);
                    686:   return 0;
                    687: }
                    688: 
                    689: 
                    690: // -------------------------------------------------------------- //
                    691: //   Parsing the TS-packet and calling parse_PSI 
                    692: //   or copy PES to stdout, if neccessary.
                    693: // parse_TP is analyzing one Transport Stream Packet at a time, 
                    694: // then the payload gets either sent to the parse_PSI function
                    695: // or, if it's a PES, is piped to stdout.
                    696: // -------------------------------------------------------------- //
                    697: 
                    698: int parse_TP(
                    699:   FILE* inputstream,            // mpeg-2 file
                    700:   int parse,                    // true: parse  false: skip packet
                    701:   int verbose,                  // true: debug output
                    702:   int pipe,                     // true: selected PES as binary  false: as Hexdump
                    703:   unsigned int select_program,  // number of the program to pipe out
                    704:   unsigned int select_stream,   // number of the stream in the PMT
                    705:   int useCRC) {                 // true: ignore CRC of PSI
                    706: 
                    707:   // Return codes:
                    708:   // 0x0000: OK
                    709:   // 0xXXEE: XX: error location  EE: error type
                    710:   // 0x0001: unexpected end of file
                    711:   // 0x0002: unexpected end of data
                    712:   // 0x0003: unexpected end of memory
                    713:   
                    714:   // bool evals to true if not 0
                    715:   
                    716:   unsigned char TP[TS_packet_length];  // one Transport Packet, raw
                    717:   
                    718:   ElementaryStream *ES;           // current ES
                    719: 
                    720:   TransportStreamProgram *TSP;    // current TSP
                    721:   
                    722:   unsigned int PID,   // Packet IDentification (13 bits)
                    723:                pointer_field;    // Pointer Field (1 byte, used in PSI-packets)
                    724:                
                    725:   AdaptionField *AF;        // current Adaption Field
                    726:   unsigned int AFL;      // Adaption Field Length
                    727:                
                    728:   int PSI,
                    729:       partlen;
                    730:   unsigned char table_id;                 // Table ID
                    731:   unsigned int  section_length;           // Section Length
                    732: 
                    733:   ProgramMapTable *PMT;  // current PMT
                    734: 
                    735:   Program *prog;           // temp. pointer
                    736: 
                    737:   unsigned int  PESprog;          // Elementary Stream Program Number
                    738:   unsigned char PEStype;          // Elementary Stream Media Type
                    739:   unsigned int  PESstream;        // Elementary Stream PMT-number
                    740:                
                    741:   int n,i,j,k;          // counters
                    742:   unsigned char ch;   // single byte
                    743:   int filechar;       
                    744: 
                    745:   if (!parse) verbose=0;  // skipping
                    746: 
                    747:   // scanning up to 1000 chars for the sync-character 0x47
                    748:   k=1000; i=0;
                    749:   while (((filechar=fgetc(inputstream))!=0x47) && (filechar>=0) && (k--)) {
                    750:     if (verbose) {
                    751:       printf("%02X ",filechar & 0xFF); // looking for sync byte
                    752:       if ((i++ % 24) == 23) printf("\n");
                    753:     }
                    754:   }
                    755:   if (k) { 
                    756:     if ((verbose) && (k<1000)) printf("\nSkipped %i byte looking for 0x47\n",1000-k);
                    757:     if (filechar<0) return 0x0001;
                    758:     TP[0]=filechar;
                    759:     
                    760:     // reading the remaining 187 bytes of the 188 byte TP-Packet
                    761:     if (fread(&TP[1],1,TS_packet_length-1,inputstream)!=TS_packet_length-1) return 0x0101;
                    762:       
                    763:     //if (!parse) return 0;  // skipping
                    764:     
                    765:     // finding/creating our TSP-structure for this PID
                    766:     PID=((TP[1] & 0x1F) << 8) | (TP[2] & 0xFF);
                    767:     ES=new_ES(PID);
                    768:     if (ES==NULL) return 0x0003;  // Insufficient Memory;
                    769:     TSP=ES->TSP;
                    770:     if (TSP==NULL) return 0x0103;  // Insufficient Memory;
                    771: 
                    772:     // parsing header parameters into TSP-structure
                    773:     TSP->transport_error_indicator=    TP[1] & 0x80;
                    774:     TSP->payload_unit_start_indicator= TP[1] & 0x40;
                    775:     TSP->transport_priority=           TP[1] & 0x20;
                    776:     //TSP->PID=((TP[1] & 0x1F) << 8) | (TP[2] & 0xFF);  // is already done
                    777:     TSP->transport_scrambling_control=(TP[3] >> 6) & 0x03;
                    778:     TSP->adaption_field_control_1=     TP[3] & 0x20;
                    779:     TSP->adaption_field_control_0=     TP[3] & 0x10;
                    780:     TSP->previous_cc=TSP->continuity_counter;
                    781:     TSP->continuity_counter=           TP[3] & 0x0F;
                    782:     
                    783:     // debugging output
                    784:     if (verbose) print_TP(TSP);
                    785: 
                    786:     if (TSP->transport_error_indicator) {
                    787:       if (verbose) printf("- Broken packet (transport_error_indicator)%s",(useCRC?", skipping...\n":""));
                    788:       if (useCRC) return 0;
                    789:     }
                    790:     
                    791:     if (PID==0x1FFF) {  // Null packet
                    792:       if (verbose) printf("- Null packet - %i byte\n\n",TS_packet_length-4);
                    793:       ES->payload_count=0;
                    794:       if (TSP->transport_scrambling_control)
                    795:         if (verbose) printf("- ERROR in transport_scrambling_control of null packet\n");
                    796:       if (!TSP->adaption_field_control_0 || TSP->adaption_field_control_1)
                    797:         if (verbose) printf("- ERROR in adaption_field_control of null packet\n");
                    798:       return 0;
                    799:     }
                    800:     
                    801:     if (!(TSP->adaption_field_control_1 && (TP[5] & 0x80))) {  // AF discontinuity_indicator?
                    802:       if (TSP->adaption_field_control_0 && (TSP->continuity_counter==TSP->previous_cc)) {
                    803:         if (verbose) printf("- Duplicate Packet - skipping...\n");
                    804:         return 0;
                    805:       }
                    806:       if (TSP->adaption_field_control_0 && (TSP->continuity_counter!=((TSP->previous_cc+1)&0x0F))) {
                    807:         if (verbose) printf("ERROR: Missing Packet(s): %i\n",(TSP->continuity_counter-TSP->previous_cc)&0x0F);
                    808:       }
                    809:     }
                    810: 
                    811:     // parsing Adaption Field, if any, and storing it into our TSP
                    812:     if (TSP->adaption_field_control_1) {  // Adaption Field present
                    813:       AFL=TP[4] & 0xFF;
                    814:       TSP->AF=(AdaptionField *)malloc(sizeof(AdaptionField));
                    815:       if ((AF=TSP->AF)==NULL) return 0x0203;
                    816:       if (AFL) {
                    817:         AF->discontinuity_indicator=TP[5] & 0x80;
                    818:         AF->random_access_indicator=TP[5] & 0x40;
                    819:         AF->elementary_stream_priority_indicator=TP[5] & 0x20;
                    820:         AF->PCR_flag=TP[5] & 0x10;
                    821:         AF->OPCR_flag=TP[5] & 0x08;
                    822:         AF->splicing_point_flag=TP[5] & 0x04;
                    823:         AF->transport_private_data_flag=TP[5] & 0x02;
                    824:         AF->adaption_field_extension_flag=TP[5] & 0x01;
                    825: 
                    826:         n=6;  // from here on we don't have static positions anymore
                    827:         
                    828:         if (AF->PCR_flag && ((n+6) <= (AFL+5))) {
                    829:           AF->program_clock_reference_base=TP[n++] & 0x000000FFULL;  // Bit 32-25
                    830:           AF->program_clock_reference_base=(AF->program_clock_reference_base << 8) | (TP[n++] & 0x000000FFULL);  // Bit 24-17
                    831:           AF->program_clock_reference_base=(AF->program_clock_reference_base << 8) | (TP[n++] & 0x000000FFULL);  // Bit 16-9
                    832:           AF->program_clock_reference_base=(AF->program_clock_reference_base << 8) | (TP[n++] & 0x000000FFULL);  // Bit 8-1
                    833:           ch=TP[n++];
                    834:           AF->program_clock_reference_base=(AF->program_clock_reference_base << 1) | ((ch >> 7) & 0x00000001ULL);  // Bit 0
                    835:           AF->program_clock_reference_extension=ch & 0x01;
                    836:           AF->program_clock_reference_extension=(AF->program_clock_reference_extension << 8) | (TP[n++] & 0xFF);
                    837:         } else if (AF->PCR_flag) return 0x0102;
                    838:         
                    839:         if (AF->OPCR_flag && ((n+6) <= (AFL+5))) {
                    840:           AF->original_program_clock_reference_base=TP[n++] & 0x000000FFULL;  // Bit 32-25
                    841:           AF->original_program_clock_reference_base=(AF->original_program_clock_reference_base << 8) | (TP[n++] & 0x000000FFULL);  // Bit 24-17
                    842:           AF->original_program_clock_reference_base=(AF->original_program_clock_reference_base << 8) | (TP[n++] & 0x000000FFULL);  // Bit 16-9
                    843:           AF->original_program_clock_reference_base=(AF->original_program_clock_reference_base << 8) | (TP[n++] & 0x000000FFULL);  // Bit 8-1
                    844:           ch=TP[n++];
                    845:           AF->original_program_clock_reference_base=(AF->original_program_clock_reference_base << 1) | ((ch >> 7) & 0x00000001ULL);  // Bit 0
                    846:           AF->original_program_clock_reference_extension=ch & 0x01;
                    847:           AF->original_program_clock_reference_extension=(AF->original_program_clock_reference_extension << 8) | (TP[n++] & 0xFF);
                    848:         } else if (AF->OPCR_flag) return 0x0202;
                    849:         
                    850:         if (AF->splicing_point_flag && (n < (AFL+5))) {
                    851:           AF->splice_countdown=TP[n++] & 0xFF;
                    852:         } else if (AF->splicing_point_flag) return 0x0302;
                    853:         
                    854:         if (AF->transport_private_data_flag && (n < (AFL+5))) {
                    855:           AF->transport_private_data_length=TP[n++] & 0xFF;
                    856:           if (n+AF->transport_private_data_length > AFL) return 0x0402;
                    857:           for (i=0; (i<AF->transport_private_data_length) && (n<AFL); i++) {
                    858:             AF->private_data_byte[i]=TP[n++];
                    859:           }
                    860:         } else if (AF->transport_private_data_flag) return 0x0502;
                    861:         
                    862:         if (AF->adaption_field_extension_flag && (n < (AFL+5))) {
                    863:           AF->adaption_field_extension_length=TP[n++] & 0xFF;
                    864:           if (n+AF->adaption_field_extension_length > (AFL+5)) return 0x0602;
                    865:           ch=TP[n++];
                    866:           AF->ltw_flag=ch & 0x80;
                    867:           AF->piecewise_rate_flag=ch & 0x40;
                    868:           AF->seamless_splice_flag=ch & 0x20;
                    869:           if (AF->ltw_flag) {
                    870:             ch=TP[n++];
                    871:             AF->ltw_valid_flag=ch & 0x80;
                    872:             AF->ltw_offset=((ch & 0x7F) << 8) | (TP[n++] & 0xFF);
                    873:           }
                    874:           if (AF->piecewise_rate_flag) {
                    875:             AF->piecewise_rate=TP[n++] & 0x3F; 
                    876:             AF->piecewise_rate=(AF->piecewise_rate << 8) | (TP[n++] & 0xFF); 
                    877:             AF->piecewise_rate=(AF->piecewise_rate << 8) | (TP[n++] & 0xFF); 
                    878:           }
                    879:           if (AF->seamless_splice_flag) {
                    880:             ch=TP[n++];
                    881:             AF->splice_type=(ch >> 4) & 0x0F;
                    882:             AF->DTS_next_AU=(ch >> 1) & 0x07ULL;  // Bit 32-30
                    883:             AF->DTS_next_AU=(AF->DTS_next_AU << 8) | (TP[n++] & 0xFFULL);  // Bit 29-22
                    884:             AF->DTS_next_AU=(AF->DTS_next_AU << 7) | ((TP[n++] >> 1) & 0x7FULL);  // Bit 21-15
                    885:             AF->DTS_next_AU=(AF->DTS_next_AU << 8) | (TP[n++] & 0xFFULL);  // Bit 14-7
                    886:             AF->DTS_next_AU=(AF->DTS_next_AU << 7) | ((TP[n++] >> 1) & 0x7FULL);  // Bit 6-0
                    887:           }
                    888:         } else if (AF->adaption_field_extension_flag) return 0x0702;
                    889: 
                    890:         // debugging output        
                    891:         if (verbose) {
                    892:           //printf("Adaption Field Length: %i bytes\n",AFL);
                    893:           //for (i=0; i<AFL; i++) {
                    894:           //  printf("%02X ",(TP[i+5] & 0xFF));
                    895:           //  if (((i % 24)==23) || (i == AFL-1)) printf("\n");
                    896:           //}
                    897:           print_AF(AF);
                    898:         }
                    899:         
                    900:       }
                    901:       AFL++; // AFL includes now the AFL-byte itself
                    902:     } else AFL=0;
                    903: 
                    904:     if (TSP->adaption_field_control_0) {  // Payload present
                    905:     
                    906:       n=AFL+4;  // offset of Payload in TP[]
                    907:       
                    908:       // determine payload type: PES or PSI?
                    909:       // PSI-type: 0:PES 1:PAT 2:CAT 3:PMT 4:NIT 5:Null -1:Unknown
                    910:       if (PID==0x0000) PSI=1;          // is the PSI a PAT?
                    911:       else if (PID==0x0001) PSI=2;     // is the PSI a CAT?
                    912:       else if (PID==0x1FFF) PSI=-2;    // Null Packet? Already sorted out, but anyhow...
                    913:       else {
                    914:         PSI=-1;    // default to Unknown
                    915:         if (PAT!=NULL) {
                    916:           for (i=0; i<PAT->program_count; i++) {  // unless the PID is in the current PAT
                    917:             if (PID==PAT->PID[i]) 
                    918:               PSI=((PAT->program_number[i])?3:4); // Program Number 0 means NIT, otherwise PMT
                    919:           }
                    920:         }
                    921:         if (CAT!=NULL) {
                    922:           for (i=0; i<CAT->descriptor_count; i++) {  // PES-PID can be in CAT, too. (ECM and EMM)
                    923:             if (PID==CAT->CA_descriptor[i]->CA_PID) {
                    924:               PSI=0;  // ECM or EMM, has to go to the PES-decoder
                    925:               PESprog=0; // Program Number
                    926:               PEStype=0; // Stream Media Type
                    927:               PESstream=0;
                    928:             }
                    929:           }
                    930:         }
                    931:         PMT=first_PMT;
                    932:         while (PMT!=NULL) {  // check all current PMT's
                    933:           for (i=0; i<PMT->program_count; i++) {  // or the PID is in the current PMT, then it's a PES
                    934:             if (PID==PMT->program[i]->elementary_PID) {
                    935:               PSI=0;                       // it's a PES
                    936:               PESprog=PMT->program_number; // Program Number
                    937:               PEStype=PMT->program[i]->stream_type; // Stream Media Type
                    938:               PESstream=i+1;
                    939:             }
                    940:           }
                    941:           PMT=(ProgramMapTable *)PMT->next;
                    942:         }
                    943:       }
                    944:       
                    945:       if (PSI<0) {  // unknown PSI, let's see if we already guessed the PID
                    946:         if (phantom_PMT!=NULL) {
                    947:           for (i=0; i<phantom_PMT->program_count; i++) {  // or the PID is in the current PMT, then it's a PES
                    948:             if (PID==phantom_PMT->program[i]->elementary_PID) {
                    949:               PSI=0;                       // it's a PES
                    950:               PESprog=phantom_PMT->program_number; // Program Number
                    951:               PEStype=phantom_PMT->program[i]->stream_type; // Stream Media Type
                    952:               PESstream=i+1;
                    953:               if (verbose) printf("  previous GUESS: PES # %i, type 0x%02X\n",PESstream,PEStype);
                    954:             }
                    955:           }
                    956:         }
                    957:       }
                    958: 
                    959:       if (PSI<0) {  // unknown PSI, let's try to guess what it might be
                    960:         if (TSP->payload_unit_start_indicator) {  // a new payload block, only here we have a chance
                    961:           if ((!TP[n]) && (!TP[n+1]) && (TP[n+2]=0x01)) {
                    962:             PSI=0;  // Packet start code prefix, it's a PES
                    963:             PESprog=0xFFFF; // Program Number
                    964:             PEStype=0xFF;   // Stream Media Type
                    965:             PESstream=0;
                    966:             if ((TP[n+3] & 0xF0) == 0xE0) {
                    967:               PEStype=0x02;  // MPEG-2 Video
                    968:             } else if ((TP[n+3] & 0xE0) == 0xC0) {
                    969:               PEStype=0x04;  // MPEG-2 Audio
                    970:             }
                    971:             if (phantom_PMT!=NULL) {
                    972:               prog=phantom_PMT->program[phantom_PMT->program_count];
                    973:               if (prog==NULL) {
                    974:                 prog=(Program *)malloc(sizeof(Program));
                    975:                 phantom_PMT->program[phantom_PMT->program_count]=prog;
                    976:                 prog->descriptor_count=0;
                    977:                 for (j=0; j<16; j++) prog->descriptor[j]=NULL;
                    978:               }
                    979:               prog->elementary_PID=PID;
                    980:               prog->stream_type=PEStype;
                    981:               phantom_PMT->program_count++;
                    982:               PESstream=phantom_PMT->program_count;
                    983:             }
                    984:             if (verbose) printf("  GUESS: PES # %i, type 0x%02X\n",PESstream,PEStype);
                    985:           } else {
                    986:             pointer_field=TP[n];
                    987:             if (n+pointer_field+1<TS_packet_length) {
                    988:               table_id=TP[n+pointer_field+1];
                    989:               if (table_id==0x02) PSI=3;  // might be a PMT
                    990:               else if (table_id==0xFF) PSI=5;  // might be a Null PSI
                    991:               else if (table_id>=0x40) PSI=4;  // might be a NIT
                    992:               if (verbose && (PSI>0)) printf("  GUESS: PSI, %s, table_id 0x%02X\n",((PSI==3)?"PMT":((PSI==4)?"NIT":"Null PSI")),table_id);
                    993:             }
                    994:           }
                    995:         }
                    996:       }
                    997: 
                    998:       if (PSI<0) {
                    999:          if (verbose) printf("- ERROR packet with Unknown PID.\n");
                   1000:       } else if (PSI) {
                   1001:         pointer_field=((TSP->payload_unit_start_indicator)?TP[n++] & 0xFF:0);
                   1002:         while (n<TS_packet_length) {
                   1003:           if (ES->payload_count>=1) {  // this PSI has already started
                   1004:             table_id=ES->Payload[0];
                   1005:             if (ES->payload_count>=2) {
                   1006:               section_length=((ES->Payload[1] << 8) | (TP[n] & 0xFF)) & 0x0FFF;
                   1007:             } else if (ES->payload_count>=3) {
                   1008:               section_length=((ES->Payload[1] << 8) | (ES->Payload[2] & 0xFF)) & 0x0FFF;
                   1009:             } else {
                   1010:               section_length=((TP[n] << 8) | (TP[n+1] & 0xFF)) & 0x0FFF;
                   1011:             }
                   1012:           } else {
                   1013:             table_id=TP[n];
                   1014:             section_length=((TP[n+1] << 8) | (TP[n+2] & 0xFF)) & 0x0FFF;
                   1015:           }
                   1016:           if (table_id==0xFF) {  // stuffing bytes
                   1017:             i=n;
                   1018:             while (TP[n]==0xFF) n++;
                   1019:             ES->payload_count=0;
                   1020:             if (verbose) printf("- PSI section - %i stuffing bytes\n",n-i);
                   1021:           } else {
                   1022:             partlen=TS_packet_length-n;
                   1023:             if (partlen+ES->payload_count>section_length+3) partlen=section_length+3-ES->payload_count;
                   1024:             if ((ES->payload_length - ES->payload_count) < partlen) {  // we need more memory
                   1025:               ES->Payload=(char *)realloc(ES->Payload,ES->payload_count+partlen);
                   1026:               if (ES->Payload==NULL) return 0x0203;
                   1027:               ES->payload_length=ES->payload_count+partlen;
                   1028:             }
                   1029:             for (i=0; i<partlen; i++) {
                   1030:               ES->Payload[ES->payload_count++]=TP[n++];
                   1031:               //if (verbose) {
                   1032:               //  printf("- Payload - for PID 0x%04X (PSI) now %i byte\n",PID,ES->payload_count);
                   1033:               //  for (i=0; i<ES->payload_count; i++) {
                   1034:               //    printf("%02X ",(ES->Payload[i] & 0xFF));
                   1035:               //    if ((i % 24)==23) printf("\n");
                   1036:               //  }
                   1037:               //  printf("\n");
                   1038:               //}
                   1039:             }
                   1040:             if (ES->payload_count>=section_length+3) {  // section complete
                   1041:               parse_PSI(ES,PSI,verbose,useCRC);
                   1042:               ES->payload_count=0;  // PSI done, dispose.
                   1043:             } else {
                   1044:               if (verbose) printf("Incomplete PSI section, appending %i byte to buffer, now %i byte.\n",partlen,ES->payload_count);
                   1045:             }
                   1046:           }
                   1047:         }
                   1048: 
                   1049:       } else if (parse) {
                   1050:         if (verbose || !pipe) {
                   1051:           if (verbose || ((select_program==PESprog) && (select_stream==PESstream))) {
                   1052:             printf("PES packet:\nProgram: 0x%04X\nStream:  %i\nType:    0x%02X\n",PESprog,PESstream,PEStype);
                   1053:             printf("- PES fragment - %i byte\n",TS_packet_length-n);
                   1054:             for (i=0; i<TS_packet_length-n; i++) {
                   1055:               printf("%02X ",(TP[n+i] & 0xFF));
                   1056:               if ((i % 24)==23) printf("\n");
                   1057:             }
                   1058:             printf("\n");
                   1059:           }
                   1060:         } else if (pipe && ((select_program==PESprog) && (select_stream==PESstream))) {
                   1061:           while (n<TS_packet_length) putchar(TP[n++]);  // ... und dafuer der ganze Aufwand.
                   1062:         }
                   1063:       }
                   1064:     }
                   1065:     if (verbose) printf("\n");
                   1066:   }
                   1067:   return 0;
                   1068: }
                   1069: 
                   1070: char *StreamType(unsigned char stream_type) {
                   1071:   if (stream_type==0x00) return "ITU-T | ISO/IEC reserved";
                   1072:   else if (stream_type==0x01) return "ISO/IEC 11172-2 Video";
                   1073:   else if (stream_type==0x02) return "ITU-T Rec. H.262 | ISO/IEC 13818-2 Video";
                   1074:   else if (stream_type==0x03) return "ISO/IEC 11172-3 Audio";
                   1075:   else if (stream_type==0x04) return "ISO/IEC 13818-3 Audio";
                   1076:   else if (stream_type==0x05) return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections";
                   1077:   else if (stream_type==0x06) return "ITU-T Rec. H.222.0 | ISO/IEC 13818-3 PES private data";
                   1078:   else if (stream_type==0x07) return "ISO/IEC 13522 MHEG";
                   1079:   else if (stream_type==0x08) return "DSM CC";
                   1080:   else if (stream_type==0x09) return "ITU-T Rec. H.222.1";
                   1081:   else if (stream_type==0x0A) return "ISO/IEC 13818-6 Type A";
                   1082:   else if (stream_type==0x0B) return "ISO/IEC 13818-6 Type B";
                   1083:   else if (stream_type==0x0C) return "ISO/IEC 13818-6 Type C";
                   1084:   else if (stream_type==0x0D) return "ISO/IEC 13818-6 Type D";
                   1085:   else if (stream_type==0x0E) return "ISO/IEC 13818-1 auxiliary";
                   1086:   else if (stream_type>=0x80) return "User private";
                   1087:   else return "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 reserved";
                   1088: }
                   1089: 
                   1090: 
                   1091: // -------------------------------------------------------------- //
                   1092: //   main: opening file and repeat calling parse_TP
                   1093: // -------------------------------------------------------------- //
                   1094: 
                   1095: int main (int argc, char* argv[]) {
                   1096: 
                   1097:   FILE* inputstream;
                   1098:   int i,j,filearg,startpacket,stoppacket,err,verbose,pipe,useCRC;
                   1099:   unsigned int prog,stream;
                   1100:   char buf[256];
                   1101:   
                   1102:   ProgramMapTable *PMT;  // current PMT
                   1103: 
                   1104:   i=1;
                   1105:   filearg=0;
                   1106:   prog=0;
                   1107:   stream=0;
                   1108:   verbose=0;
                   1109:   pipe=0;
                   1110:   startpacket=0;
                   1111:   stoppacket=0;
                   1112:   useCRC=0;
                   1113:   while (i<argc) {
                   1114:     if (argv[i][0]=='-') {  // option
                   1115:       if (argv[i][1]=='v') verbose=1;    // verbose on
                   1116:       else if (argv[i][1]=='p') pipe=1;  // pipe on
                   1117:       else if (argv[i][1]=='c') useCRC=1;  // CRC on
                   1118:       else if (argv[i][1]=='s') {        // select a program
                   1119:         i++;
                   1120:         for (j=0; (j<strlen(argv[i])) && (argv[i][j]!='/'); j++);
                   1121:         if (j<strlen(argv[i])) {
                   1122:           prog=atoi(strncpy(buf,argv[i],j));
                   1123:           stream=atoi(strcpy(buf,&argv[i][j+1]));
                   1124:         }
                   1125:       } else {  // unknown option
                   1126:         printf("\
                   1127: Usage: %s [-v] [-p] [-c] [-s <prog>/<stream>] [<file> [<first packet> <last packet> | <packet>]]\n\
                   1128: -v: verbose on\n\
                   1129: -p: pipe on (only raw output)\n\
                   1130: -c: use CRC on PSI\n\
                   1131: -s <prog>/<stream>: show/pipe only the <stream>th PES-stream of program <prog>\n\
                   1132: ",argv[0]);
                   1133:       }
                   1134:     } else if (!filearg) filearg=i;
                   1135:     else if (!startpacket) startpacket=atoi(argv[i]);
                   1136:     else if (!stoppacket) stoppacket=atoi(argv[i]);
                   1137:     i++;
                   1138:   }
                   1139: 
                   1140:   if (filearg) {
                   1141:     if ((inputstream=fopen(argv[filearg],"r"))==NULL) {
                   1142:       printf("Couldn't open file %s\n",argv[1]);
                   1143:       exit (0);
                   1144:     }
                   1145:   } else inputstream=stdin;
                   1146: 
                   1147:   gen_crc32_table();
                   1148:   
                   1149:   if (startpacket) {
                   1150:     if (!stoppacket) stoppacket=startpacket;
                   1151:   } else stoppacket=-1;
                   1152:   
                   1153:   current_PAT=(ProgramAssociationTable *)malloc(sizeof(ProgramAssociationTable));
                   1154:   next_PAT=(ProgramAssociationTable *)malloc(sizeof(ProgramAssociationTable));
                   1155:   PAT=NULL;
                   1156:   current_PAT->program_count=0;
                   1157:   next_PAT->program_count=0;
                   1158:   
                   1159:   current_CAT=(ConditionalAccessTable *)malloc(sizeof(ConditionalAccessTable));
                   1160:   next_CAT=(ConditionalAccessTable *)malloc(sizeof(ConditionalAccessTable));
                   1161:   CAT=NULL;
                   1162:   current_CAT->descriptor_count=0;
                   1163:   for (i=0; i<256; i++) current_CAT->CA_descriptor[i]=NULL;
                   1164:   next_CAT->descriptor_count=0;
                   1165:   for (i=0; i<256; i++) next_CAT->CA_descriptor[i]=NULL;
                   1166:   
                   1167:   phantom_PMT=(ProgramMapTable *)malloc(sizeof(ProgramMapTable));  // PMT for guessed channels
                   1168:   phantom_PMT->program_number=0xFFFF;
                   1169:   phantom_PMT->program_count=0;
                   1170:   
                   1171:   err=0;
                   1172:   for (i=0; ((stoppacket<0) || (i<stoppacket)) && (err==0); i++) {
                   1173:     if ((startpacket<=(i+1)) && verbose) printf("--- Packet %i --- %ld\n",i+1,ftell(inputstream));
                   1174:     err=parse_TP(inputstream,(startpacket<=(i+1)),verbose,pipe,prog,stream,useCRC);
                   1175:   }
                   1176:   if (err && verbose) printf("\nError in packet %i at %ld: 0x%04X (%s)\n",i,ftell(inputstream),err,(((err & 0xFF)==0x01)?"End of File":(((err & 0xFF)==0x02)?"Data Format Error":"Unknown Error")));
                   1177:   
                   1178:   if (!pipe) {
                   1179:     if (PAT!=NULL) {
                   1180:       printf("Transport stream ID: 0x%04X\n",PAT->transport_stream_id);
                   1181:       if (PAT->program_count>0) {
                   1182:         printf("  Contains %i Program%s:\n",PAT->program_count,((PAT->program_count==1)?"":"s"));
                   1183:         for (i=0; i<PAT->program_count; i++) {
                   1184:           printf("    %i\n",PAT->program_number[i]);
                   1185:         }
                   1186:       }
                   1187:     }
                   1188:     PMT=first_PMT;
                   1189:     while (PMT!=NULL) {
                   1190:       printf("  Program %i with %i stream%s\n",PMT->program_number,PMT->program_count,((PMT->program_count==1)?"":"s"));
                   1191:       for (i=0; i<PMT->descriptor_count; i++) {
                   1192:         printf("    ");
                   1193:         show_descriptor(PMT->descriptor[i],0);
                   1194:       }
                   1195:       for (i=0; i<PMT->program_count; i++) {
                   1196:         printf("    Stream %i, Type: %s (0x%02X)\n",
                   1197:           i+1,
                   1198:           StreamType(PMT->program[i]->stream_type),
                   1199:           PMT->program[i]->stream_type);
                   1200:         for (j=0; j<PMT->program[i]->descriptor_count; j++) {
                   1201:           printf("      ");
                   1202:           show_descriptor(PMT->program[i]->descriptor[j],0);
                   1203:         }
                   1204:       }
                   1205:       PMT=(ProgramMapTable *)PMT->next;
                   1206:     }
                   1207:   }
                   1208:   fclose(inputstream);
                   1209: 
                   1210:   return 0;
                   1211: }

LinuxTV legacy CVS <linuxtv.org/cvs>