📄 mpeg2demux.c
字号:
(void) pthread_mutex_init(&mutex_decoders,NULL); (void) audio_system_init(); (void) video_system_init(); terminate=0; if (pthread_create(&demux_thread,NULL, transport_stream, NULL)) { fprintf(stderr,"Cannot create TS demultiplexer thread\n");; return 1; } return 0;}void mpeg2demux_done(){ void* result; terminate=1; if (pthread_join(demux_thread,&result)) /* wait for thread to exit */ { fprintf(stderr,"Cannot join TS demux thread\n");; exit(1); } while (program_map_table) { struct ProgramMapTableEntry *temp; temp = program_map_table->next; free(program_map_table); program_map_table = temp; } (void) video_system_done(); (void) audio_system_done(); if (pthread_mutex_destroy(&mutex_PMT)) { fprintf(stderr,"Cannot destroy PMT mutex\n");; exit(1); } if (debug) { fprintf(stdout,"demux terminated\n"); }}void printPAT(FILE* ostream) { int i; if (pthread_mutex_lock(&mutex_PMT)) { fprintf(stderr,"cannot lock PMT mutex\n");; exit(1); } fprintf(ostream, "Program Association Table (containing %d descriptions):\n", number_of_programs); for (i= 0; i < number_of_programs;i++) { fprintf(ostream,"program %u has PSI in PID %u (0x%x)\n", PAT[i].program_number, PAT[i].program_map_PID,PAT[i].program_map_PID); } if (pthread_mutex_unlock(&mutex_PMT)) { fprintf(stderr,"cannot unlock PMT mutex\n");; exit(1); }}void printPMT(FILE* ostream) { struct ProgramMapTableEntry* temp; if (pthread_mutex_lock(&mutex_PMT)) { fprintf(stderr,"cannot lock PMT mutex\n");; exit(1); } for (temp=program_map_table; temp; temp=temp->next) { struct stream_description *streams; fprintf(ostream,"Mappings for program number %u with PCR_PID %u (0x%x):\n",temp->program_number, temp->PCR_PID, temp->PCR_PID); for (streams=temp->streams; streams; streams=streams->next) { fprintf(ostream,"\telementary stream %u (0x%x) has type %u", streams->elementary_PID, streams->elementary_PID, streams->stream_type); switch (streams->stream_type) { case 0: fprintf(ostream," (reserved)"); break; case 1: fprintf(ostream," (MPEG 1 Video)"); break; case 2: fprintf(ostream," (MPEG 2 Video)"); break; case 3: fprintf(ostream," (MPEG 1 Audio)"); break; case 4: fprintf(ostream," (MPEG 2 Audio)"); break; case 5: fprintf(ostream," (private sections)"); break; case 6: fprintf(ostream," (PES private data)"); break; case 7: fprintf(ostream," (MHEG)"); break; case 8: fprintf(ostream," (DSM CC)"); break; case 9: fprintf(ostream," (ITU-T Rec. H.222.1)"); break; case 10: fprintf(ostream," (ISO/IEC 13818-6 type A)"); break; case 11: fprintf(ostream," (ISO/IEC 13818-6 type B)"); break; case 12: fprintf(ostream," (ISO/IEC 13818-6 type C)"); break; case 13: fprintf(ostream," (ISO/IEC 13818-6 type D)"); break; case 14: fprintf(ostream," (ISO/IEC 13818-1 auxiliary)"); break; default: fprintf(ostream," (reserved or user private)"); break; } fprintf(ostream,"\n"); } } if (pthread_mutex_unlock(&mutex_PMT)) { fprintf(stderr,"cannot unlock PMT mutex\n");; exit(1); }}void printPidTable(FILE* ostream) { unsigned int i; for (i=0; i < MAX_PIDS; i++) if (pidcount[i]) fprintf(ostream, "PID %u (0x%x) occured %u times\n", i, i, pidcount[i]);}static int get_adaptation_field(){ int length=getbits8(); /* get adaptation field length */ if (length) { /* int discontinuity_indicator=(nextbits8() >> 7); */ /* int random_access_indicator=(nextbits8() >> 6) & 1; */ /* int elem_prio_indicator=(nextbits8() >> 5) & 1; not used at this point; */ int pcr_flag=(getbits8() >> 4) & 1; /* get first byte */ if (pcr_flag){ unsigned long long clk_ref_base=getbits32(); unsigned int clk_ref_ext=getbits16(); clk_ref_base<<=1; /* Create space for bit */ clk_ref_base|=(clk_ref_ext >> 15); clk_ref_ext&=0x01ff; /* Only lower 9 bits */ if (pid==pcr_pid) { setSTC(clk_ref_base,clk_ref_ext); pcr_packets++; } skipbytes(length - 7); } else skipbytes(length - 1); } else { fprintf(stderr,"adaption field does only stuffing a byte. PID: %d\n", pid); } return 1;}static int get_payload(){ if (payload_unit_start_indicator){ if (pid==0) get_program_association_table(1); else if (nextbits24()==PACKET_START_CODE_PREFIX) { if (pthread_mutex_lock(&mutex_decoders)) /* lock decoders; they may not be reset now */ { fprintf(stderr,"cannot lock decoders mutex\n"); exit(1); } get_pes_packet(); if (pthread_mutex_unlock(&mutex_decoders)) /* unlock decoders; now they can safely be reset */ { fprintf(stderr,"cannot unlock decoders mutex\n"); exit(1); } } else switch (isProgramMapTable(pid)) { case 2:if (debug) {fprintf(stdout,"skipping Network Information Table\n");} break; case 0:break; //skipbytes(MPEG2_TS_Packet_size - bytecount);break; case 1:get_PMT_packet(1);break; default: fprintf(stderr,"internal error\n");exit(1); } } else { if (pid==0) get_program_association_table(0); else if (pid==audio_pid) { if (pthread_mutex_lock(&mutex_decoders)) /* lock decoders; they may not be reset now */ { fprintf(stderr,"cannot lock decoders mutex\n"); exit(1); } get_audio_data(); if (pthread_mutex_unlock(&mutex_decoders)) /* unlock decoders; now they can safely be reset */ { fprintf(stderr,"cannot unlock decoders mutex\n"); exit(1); } } else if (pid==video_pid) { if (pthread_mutex_lock(&mutex_decoders)) /* lock decoders; they may not be reset now */ { fprintf(stderr,"cannot lock decoders mutex\n"); exit(1); } get_video_data(); if (pthread_mutex_unlock(&mutex_decoders)) /* unlock decoders; now they can safely be reset */ { fprintf(stderr,"cannot unlock decoders mutex\n"); exit(1); } } else switch (isProgramMapTable(pid)) { case 2:if (debug) {fprintf(stdout,"skipping continuation of Network Information Table\n");}break; case 0:break; //skipbytes(MPEG2_TS_Packet_size - bytecount);break; case 1:get_PMT_packet(0);break; default: fprintf(stderr,"internal error\n");exit(1); } } return 1;}static void copy_PAT_temp2PAT(int prognum){ struct ProgramMapTableEntry **pmt_temp; int i; if (pthread_mutex_lock(&mutex_PMT)) /* lock tables before we modify them */ { fprintf(stderr,"cannot lock PMT mutex\n"); exit(1); } for (i=0; i < prognum; i++) { PAT[i].program_number=(PAT_temp[i<<2] << 8) | PAT_temp[(i<<2) +1]; PAT[i].program_map_PID=((PAT_temp[(i<<2)+2] & 0x1F) << 8) | PAT_temp[(i<<2) +3]; } number_of_programs = prognum; /* clean PMT now */ for (pmt_temp=&program_map_table; *pmt_temp;) { int number=(*pmt_temp)->program_number; int exists=0; /* does the program number exist in PAT? */ int j; for (j=0; j < prognum; j++) if (PAT[j].program_number==number) { exists=1; break; } if (!exists) /* program does not exist anymore -> we eliminate PMT entry */ { struct ProgramMapTableEntry *t2 = *pmt_temp; *pmt_temp=(*pmt_temp)->next; cleanPMTEntry(t2); free(t2); if (current_program == number) { fprintf(stderr,"program %d does not exist anymore", number); current_program = -1; set_pids_internal(-1,-1,-1); /* reset decoders */ } } else { pmt_temp=&(*pmt_temp)->next; } } if (pthread_mutex_unlock(&mutex_PMT)) /* unlock tables */ { fprintf(stderr, "cannot unlock PMT mutex\n"); exit(1); } /* cleanup pmt buffers */ for (i=0;i < PMT_BUFFERS;i++) { if ((pmt_buffer[i].pid != -1) && !isProgramMapTable(pmt_buffer[i].pid)) { pmt_buffer[i].pid = -1; } }}/* reads the rest of a PAT (as far as available in the current TS packet returns 1 if we should continue with the next TS packet afterwards of 0 if we shall continue this packet.*/static int get_program_association_table_rest(int expect_start){ int bytes_to_read=rest_of_pat_section <= rest_of_ts_packet()?rest_of_pat_section:rest_of_ts_packet(); if (PAT_position + bytes_to_read > PAT_temp + 4*(MAX_PROGRAMS+1)) { fprintf(stderr, "PAT too long, discarding\n"); PAT_position=0; return 1; } PAT_position += copybytes(PAT_position,bytes_to_read); if (!(rest_of_pat_section -= bytes_to_read)) /* if we completed a section... */ { PAT_position -= 4; /* remove CRC_32 */ PAT_have_bytes_of_header=0; /* we have to start new section afterwards */ if (current_pat_section == PAT_last_section) { /* we completed last section */ if (rest_of_ts_packet() && (nextbits8()!=0xff)) /* if we have a rest, it must be padding */ { fprintf(stderr,"PATs end is not padding\n"); PAT_position=0; /* we will have to start a new PAT afterwards */ return 1; } else { /* we read a complete PAT which is ok and make it the current one */ copy_PAT_temp2PAT((PAT_position-PAT_temp) / 4); PAT_position=0; /* we will have to start a new PAT afterwards */ return 1; } } if ((!expect_start) && (!rest_of_ts_packet() || nextbits8() == 0xff)) return 1; /* skip padding at end of ts packet */ } return 0; /* we have to continue reading this TS packet */}/* reads the (rest of the) PAT-header (as far as available in the current TS packet) and parses it if it completes It returns 1 if the PAT has an error and we shall discard what we already read and skip the rest of the current TS packet or 0 if the head is ok and we could continue reading this packet*/static int get_and_parse_program_association_table_header(){ int bytes_to_read=(8-PAT_have_bytes_of_header) <= rest_of_ts_packet()?8-PAT_have_bytes_of_header:rest_of_ts_packet(); PAT_have_bytes_of_header += copybytes(PAT_header+PAT_have_bytes_of_header,bytes_to_read); if (PAT_have_bytes_of_header==8) /* if we have a complete header now... */ { /* parse it */ int section_length; current_pat_section++; if (PAT_header[0]!=0) /* table id */ {fprintf(stderr,"incorrect table id in program association table\n");; return 1;} if ((PAT_header[1] >> 6) != 2) {fprintf(stderr,"syntax error in program association table\n");; return 1;} section_length=((PAT_header[1] & 0x0f) << 8) | PAT_header[2]; if ((section_length > 1021) || (rest_of_pat_section=section_length-5) % 4) {fprintf(stderr,"PAT section invalid long\n");; return 1;} transport_stream_id=PAT_header[3] << 8 | PAT_header[4]; if (PAT_header[6] != current_pat_section) { fprintf(stderr,"pat section number %d not monoton\n", (int) PAT_header[6]);; return 1; } if (current_pat_section) { /* not first section */ if ((PAT_header[5] & 0x3f) != PAT_version) { fprintf(stderr,"incorrect PAT version\n"); return 1; } if (PAT_last_section != PAT_header[7]) { fprintf(stderr,"last_section_number may not change within PAT\n"); return 1; } } else { /* first section */ if (PAT_header[5] & 1) /* current_next says current */ { PAT_version=PAT_header[5] & 0x3f; PAT_last_section=PAT_header[7]; } else {fprintf(stderr,"skipping next PAT\n");; return 1;} } } return 0;}static int get_program_association_table(int start){ int started=0; int start_position=0; if (start) /* if a new section starts in this packet */ { int pointer_field=getbits8(); /* get pointer_field */ start_position=rest_of_ts_packet()-pointer_field; if (PAT_position==0) /* if we have to start a new PAT */ { if (pointer_field) { fprintf(stderr,"skipping part of a PAT, waiting for new one\n");; return 1; } else { PAT_position=PAT_temp; current_pat_section=-1; /* next section number must be 0 */ rest_of_pat_section=0; /* we do not have to complete an old pat section, but can immediately start the new one */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -