📄 mpeg2demux.c
字号:
PAT_have_bytes_of_header=0; } } } if (!PAT_position) { fprintf(stderr,"skipping chunk of PAT, because it did not start yet\n"); return 1; } while (rest_of_ts_packet()) { if (rest_of_pat_section) /* do we have to complete an old section? */ { if (get_program_association_table_rest(start && !started)) return 1; } else if (PAT_have_bytes_of_header < 8) /* we have to read a PAT head */ { if (PAT_have_bytes_of_header==0) { if (start) { if ((!started) && (start_position != rest_of_ts_packet())) { fprintf(stderr,"Pointer field at beginning of packet containing PAT was not correct\n"); PAT_position=0; return 1; } else started=1; } else { fprintf(stderr,"Packet with starting PAT section did not contain payload unit start indicator\n"); PAT_position=0; return 1; } } if (get_and_parse_program_association_table_header()) { fprintf(stderr,"waiting for next PAT because of this error\n"); PAT_position=0; return 1; } } } return 1;}static int get_pes_packet_data(int stream_id){ unsigned long long pts,dts; int have_pts; if ((stream_id >> 4) == 12 || (stream_id >> 4) == 13){ /* Just pick the first available stream if no ID is set */ if (audio_pid==-2) audio_pid=pid; if (pid==audio_pid){ get_pes_packet_header(&pts, &dts, &have_pts); if (have_pts) { audio_pts.timestamp=pts; audio_pts.have_timestamp=1; } return get_audio_data(); } } else if ((stream_id >> 4) == 14){ /* Just pick the first available stream if no ID is set */ if (video_pid==-2) video_pid=pid; if (pid==video_pid){ if ((videobufferend + 1) % VIDEOPESPACKETSINBUFFER == videobufferstart) { /* if buffer is full */ fprintf(stderr,"Video buffer overrun! Discarding pes packet\n"); } else { videobufferend++; videobufferend %= VIDEOPESPACKETSINBUFFER; /* advance ringbuffercounter */ if (sem_post(&videobuffer_sem)) { fprintf(stderr,"Cannot V semaphore\n");; exit(0); } } get_pes_packet_header(&pts, &videobuffer[videobufferend].dts,&videobuffer[videobufferend].havedts); videobuffer[videobufferend].continuation=0; videobuffer[videobufferend].length=0; videobuffer[videobufferend].flags = 0; return get_video_data(); } } else { return 1; } /* skipbytes(MPEG2_TS_Packet_size - bytecount); */ return 1;}static int get_pes_packet_header(unsigned long long *pts, unsigned long long *dts, int *havepts){ unsigned int pes_header_bytes=0; short PTS_DTS_flags; int PES_header_data_length; *havepts=0; (void) getbits8(); /* drop first 8 bits */ PTS_DTS_flags=(getbits8() >> 6) & 0x3; PES_header_data_length=getbits8(); /* Get Presentation Time stamps and Decoding Time Stamps */ if (PTS_DTS_flags==2){ *pts=(getbits8() >> 1) & 7; /* Only low 3 bits (7==111) */ *pts<<=15; *pts|=(getbits16() >> 1); *pts<<=15; *pts|=(getbits16() >> 1); pes_header_bytes+=5; *dts=*pts; /* if dts is not explicitly encoded, its equal to pts */ *havepts=1; } else if (PTS_DTS_flags==3){ *pts=(getbits8() >> 1) & 7; /* Only low 3 bits (7==111) */ *pts<<=15; *pts|=(getbits16() >> 1); *pts<<=15; *pts|=(getbits16() >> 1); *havepts=1; *dts=(getbits8() >> 1) & 7; /* Only low 3 bits (7==111) */ *dts<<=15; *dts|=(getbits16() >> 1); *dts<<=15; *dts|=(getbits16() >> 1); pes_header_bytes+=10; } skipbytes(PES_header_data_length - pes_header_bytes); return 1;}static int get_pes_packet(){ unsigned int stream_id; (void) getbits24(); /* skip startcode */ stream_id=getbits8(); /* int pes_packet_length= Not used at this point; just drop */ (void) getbits16(); if (stream_id!=PRIVATE_STREAM_2 && stream_id!=PADDING_STREAM){ return get_pes_packet_data(stream_id); } else if (stream_id==PRIVATE_STREAM_2){ fprintf(stderr,"private stream\n"); //skipbytes(MPEG2_TS_Packet_size - bytecount); } else if (stream_id==PADDING_STREAM){ //skipbytes(MPEG2_TS_Packet_size - bytecount); } else { fprintf(stderr,"unknown stream_id in pes packet\n"); // skipbytes(MPEG2_TS_Packet_size - bytecount); } return 1;}static int get_PMT_packet(int section_start){ int bufferindex=get_PMT_Buffer_Index(pid); if (bufferindex == -1) { fprintf(stderr,"cannot read PMT, because no buffer is free\n"); return 0; } if (section_start) /* if payload_start_indictor says, that we start a new section */ { if (getbits8()!=0) { fprintf(stderr,"cannot handle packets with pmt section starts not aligned with payload start\n"); pmt_buffer[bufferindex].pid=-1; return 0; } pmt_buffer[bufferindex].pid=pid; pmt_buffer[bufferindex].byte_count=0; } else { if (pmt_buffer[bufferindex].pid != pid) { fprintf(stderr,"cannot continue PMT section in PID %d, because there is no beginning in buffer\n",pid); return 0; } } /* read PMT section */ pmt_buffer[bufferindex].byte_count += copybytes(pmt_buffer[bufferindex].buffer+pmt_buffer[bufferindex].byte_count,rest_of_ts_packet()); /* check if section is complete */ if (pmt_buffer[bufferindex].byte_count> 12) /* do we have a complete section header ?*/ { unsigned int section_length=((pmt_buffer[bufferindex].buffer[1] & 0x0f) << 8) | pmt_buffer[bufferindex].buffer[2]; if (section_length > 1021) /* section too long */ { fprintf(stderr,"Discarding PMT section, because section length says: %d (max 1021 allowed)\n",section_length); pmt_buffer[bufferindex].pid=-1; /* clear buffer; */ return 0; } else if (pmt_buffer[bufferindex].byte_count >= section_length+3) { /* we have a complete section -> interpret it */ struct ProgramMapTableEntry *pmt_entry; int program_number; int PCR_PID; int program_info_length; unsigned int current_index; pmt_buffer[bufferindex].pid=-1; /* clear buffer; when this method terminates (whether with or without error), this buffer is consumed */ if (pmt_buffer[bufferindex].buffer[0] != 2) { fprintf(stderr,"incorrect table_id in program map table\n");; return 0; } if ((pmt_buffer[bufferindex].buffer[1] >> 4) != 11) { fprintf(stderr,"syntax error in program map table\n");; return 0; } program_number=(pmt_buffer[bufferindex].buffer[3] << 8) | pmt_buffer[bufferindex].buffer[4]; if (!(pmt_buffer[bufferindex].buffer[5] & 1)) { fprintf(stderr,"skipping next program map table\n");; return 0; } if (pmt_buffer[bufferindex].buffer[6] || pmt_buffer[bufferindex].buffer[7]) { fprintf(stderr,"error in PMT: section number or last section number != 0\n");; return 0; } PCR_PID=((pmt_buffer[bufferindex].buffer[8] << 8) | pmt_buffer[bufferindex].buffer[9]) & 0x1fff; program_info_length=((pmt_buffer[bufferindex].buffer[10] << 8) | pmt_buffer[bufferindex].buffer[11]) & 0x0fff; current_index=12+program_info_length; /* here we start to read stream definitions */ if (pthread_mutex_lock(&mutex_PMT)) /* lock PMT to ensure that nobody reads it while we modify it */ { fprintf(stderr,"cannot lock PMT mutex\n");; exit(1); } pmt_entry = getProgramMapTableEntry(program_number); if (pmt_entry) { cleanPMTEntry(pmt_entry); } else { pmt_entry = malloc(sizeof(struct ProgramMapTableEntry)); if (!pmt_entry) { fprintf(stderr,"cannot malloc program map table entry.\n"); exit(1); } pmt_entry->next=program_map_table; pmt_entry->streams=NULL; program_map_table=pmt_entry; } pmt_entry->PCR_PID = PCR_PID; pmt_entry->program_number = program_number; while (current_index+4 < section_length+3) /* while we are before CRC */ { int ES_info_length; struct stream_description *hilf=malloc(sizeof(struct stream_description)); if (hilf) { hilf->stream_type=pmt_buffer[bufferindex].buffer[current_index++]; hilf->elementary_PID=(pmt_buffer[bufferindex].buffer[current_index++] << 8) & 0x1fff; hilf->elementary_PID |= pmt_buffer[bufferindex].buffer[current_index++]; hilf->next=pmt_entry->streams; pmt_entry->streams=hilf; } else { fprintf(stderr,"cannot malloc stream description.\n"); current_index += 3; } ES_info_length=(pmt_buffer[bufferindex].buffer[current_index++] << 8) & 0x0fff; ES_info_length |= pmt_buffer[bufferindex].buffer[current_index++]; current_index += ES_info_length; /* skip info */ } if (current_program == program_number) { int new_v = getVideoPid(pmt_entry); int new_a = getAudioPid(pmt_entry); if ((video_pid != new_v) || (audio_pid != new_a) || (pcr_pid != PCR_PID)) { fprintf(stderr,"program %d changed pids, restarting decoders\n", program_number); set_pids_internal(new_v, new_a, PCR_PID); } } if ((current_program == -1) && ((track_program == program_number) || (track_program == -2) || ((track_program == -3) && (program_number == getFirstProgram())))) { int new_v = getVideoPid(pmt_entry); int new_a = getAudioPid(pmt_entry); if ((track_program == program_number) || (track_program == -3) || ((new_v != -1) && (new_a != -1))) { if (new_v == -1) { fprintf(stderr,"program has no video\n"); } if (new_a == -1) { fprintf(stderr,"program has no audio\n"); } if (debug) { fprintf(stdout,"start decoding program %d with video: %d, audio: %d, pcr: %d\n", program_number, new_v, new_a, PCR_PID); } current_program = program_number; set_pids_internal(new_v, new_a, PCR_PID); } } if (pthread_mutex_unlock(&mutex_PMT)) /* unlock PMT */ { fprintf(stderr,"cannot unlock PMT mutex\n");; exit(1); } if (current_index+4 != section_length+3 ) {fprintf(stderr,"section length incorrect\n");; return 0;} current_index+=4; /* skip CRC_32 */ if ((current_index < pmt_buffer[bufferindex].byte_count) && (pmt_buffer[bufferindex].buffer[current_index] != 0xff)) /* rest must be padding */ {fprintf(stderr,"illegal data at end of program map table section\n");;return 0;} return 1; } else return 1; /* wait for next part of this section (header is already complete, but body incomplete) */ } else return 1; /* wait for next part of this section (header incomplete) */}static int get_audio_data() { (void) audiobufferfill(); audio_packets++; return 1;}static int get_video_data(){ unsigned int length=rest_of_ts_packet(); struct videobuffer_entry *currentbuffer=&videobuffer[videobufferend]; if (length <= (VIDEOBUFFER_ENTRY_SIZE - currentbuffer->length)) currentbuffer->length += copybytes(currentbuffer->buffer+currentbuffer->length,length); else { /* fprintf(stderr,"Video PES packet too long -> splitted\n"); */ if ((videobufferend + 1) % VIDEOPESPACKETSINBUFFER == videobufferstart) { /* if buffer is full */ fprintf(stderr,"Video buffer overrun! Discarding packet\n"); } else { videobufferend++; videobufferend %= VIDEOPESPACKETSINBUFFER; /* advance ringbuffercounter */ if (sem_post(&videobuffer_sem)) { fprintf(stderr,"Cannot V semaphore\n"); exit(0); } videobuffer[videobufferend].havedts=0; videobuffer[videobufferend].continuation=1; videobuffer[videobufferend].length=copybytes(videobuffer[videobufferend].buffer,length); videobuffer[videobufferend].flags = 0; } } video_packets++; return 1;}static int head_read(unsigned long *head){ if (audio_header_bytes_read == 4) /* if we already have four bytes, then we shift */ { audio_hbuf[0]=audio_hbuf[1];audio_hbuf[1]=audio_hbuf[2];audio_hbuf[2]=audio_hbuf[3]; audio_header_bytes_read=3; skipped_mpegaudio_bytes++; /* we skipped a byte now */ } while (audio_header_bytes_read < 4) { if (rest_of_ts_packet() > 0) audio_hbuf[audio_header_bytes_read++]=getbits8(); else return 0; } *head = ((unsigned long) audio_hbuf[0] << 24) | ((unsigned long) audio_hbuf[1] << 16) | ((unsigned long) audio_hbuf[2] << 8) | (unsigned long) audio_hbuf[3]; return 1;}/* * Exception from GNU General Public License: * This function (head_check) is a modification of that function * taken from mpg123.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -