Annotation of multiplexer/ts2pes.c, revision 1.3

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

LinuxTV legacy CVS <linuxtv.org/cvs>