Annotation of multiplexer/ts2pes.c, revision 1.1

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

LinuxTV legacy CVS <linuxtv.org/cvs>