📄 mpeg3demux.c
字号:
clock_ref |= ((i & 0x000003ff) << 5); clock_ref |= ((j & 0xf800) >> 11); clock_ref_ext = (j >> 1) & 0x1ff; demuxer->time = (double)(clock_ref + clock_ref_ext / 300) / 90000;/* Skip 3 bytes */ mpeg3io_read_int24(title->fs); i = mpeg3io_read_char(title->fs) & 0x7;/* stuffing */ mpeg3io_seek_relative(title->fs, i); } } else { mpeg3io_seek_relative(title->fs, 2); } return 0;}/* Program packet reading core */static int get_ps_pes_packet(mpeg3_demuxer_t *demuxer, unsigned int header){ unsigned long pts = 0, dts = 0; int stream_id; int pes_packet_length; long pes_packet_start; long decryption_offset; int i; mpeg3_t *file = demuxer->file; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; int scrambling = 0; stream_id = header & 0xff; pes_packet_length = mpeg3io_read_int16(title->fs); pes_packet_start = mpeg3io_tell(title->fs); if(stream_id != MPEG3_PRIVATE_STREAM_2 && stream_id != MPEG3_PADDING_STREAM) { if((mpeg3io_next_char(title->fs) >> 6) == 0x02) {/* Get MPEG-2 packet */ int pes_header_bytes = 0; int pts_dts_flags; int pes_header_data_length; demuxer->last_packet_decryption = mpeg3io_tell(title->fs); scrambling = mpeg3io_read_char(title->fs) & 0x30;//scrambling = 1;/* Reset scrambling bit for the mpeg3cat utility */// if(scrambling) demuxer->raw_data[demuxer->raw_offset - 1] &= 0xcf; pts_dts_flags = (mpeg3io_read_char(title->fs) >> 6) & 0x3; pes_header_data_length = mpeg3io_read_char(title->fs);/* Get Presentation and Decoding Time Stamps */ if(pts_dts_flags == 2) { pts = (mpeg3io_read_char(title->fs) >> 1) & 7; /* Only low 4 bits (7==1111) */ pts <<= 15; pts |= (mpeg3io_read_int16(title->fs) >> 1); pts <<= 15; pts |= (mpeg3io_read_int16(title->fs) >> 1); pes_header_bytes += 5; } else if(pts_dts_flags == 3) { pts = (mpeg3io_read_char(title->fs) >> 1) & 7; /* Only low 4 bits (7==1111) */ pts <<= 15; pts |= (mpeg3io_read_int16(title->fs) >> 1); pts <<= 15; pts |= (mpeg3io_read_int16(title->fs) >> 1); dts = (mpeg3io_read_char(title->fs) >> 1) & 7; /* Only low 4 bits (7==1111) */ dts <<= 15; dts |= (mpeg3io_read_int16(title->fs) >> 1); dts <<= 15; dts |= (mpeg3io_read_int16(title->fs) >> 1); pes_header_bytes += 10; }/* Skip unknown */ mpeg3io_seek_relative(title->fs, pes_header_data_length - pes_header_bytes); } else { int pts_dts_flags;/* Get MPEG-1 packet */ while(mpeg3io_next_char(title->fs) == 0xff) { mpeg3io_read_char(title->fs); }/* Skip STD buffer scale */ if((mpeg3io_next_char(title->fs) & 0x40) == 0x40) { mpeg3io_seek_relative(title->fs, 2); }/* Decide which timestamps are available */ pts_dts_flags = mpeg3io_next_char(title->fs); if(pts_dts_flags >= 0x30) {/* Get the presentation and decoding time stamp */ pts = get_timestamp(demuxer); dts = get_timestamp(demuxer); } else if(pts_dts_flags >= 0x20) {/* Get just the presentation time stamp */ pts = get_timestamp(demuxer); } else if(pts_dts_flags == 0x0f) {/* End of timestamps */ mpeg3io_read_char(title->fs); } else { return 1; /* Error */ } }/* Now extract the payload. */ if((stream_id >> 4) == 0xc || (stream_id >> 4) == 0xd) {/* Audio data *//* Take first stream ID if -1 */ pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start; if(demuxer->read_all) demuxer->astream_table[stream_id & 0x0f] = AUDIO_MPEG; else if(demuxer->astream == -1) demuxer->astream = stream_id & 0x0f; demuxer->pes_audio_time = demuxer->time; if(pts) demuxer->pes_audio_time = pts; if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio) { decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start; mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size, pes_packet_length, title->fs); demuxer->data_size += pes_packet_length; } else { mpeg3io_seek_relative(title->fs, pes_packet_length); } } else if((stream_id >> 4) == 0xe) {/* Video data *//* Take first stream ID if -1 */ pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start; if(demuxer->read_all) demuxer->vstream_table[stream_id & 0x0f] = 1; else if(demuxer->vstream == -1) demuxer->vstream = stream_id & 0x0f; demuxer->pes_video_time = demuxer->time;; if(pts) demuxer->pes_video_time = pts; if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video) {//printf(__FUNCTION__ " stream_id=%x size=%x\n", stream_id, pes_packet_length); decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start; mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size, pes_packet_length, title->fs); demuxer->data_size += pes_packet_length; } else { mpeg3io_seek_relative(title->fs, pes_packet_length); } } else if((stream_id == 0xbd || stream_id == 0xbf) && mpeg3io_next_char(title->fs) != 0xff && ((mpeg3io_next_char(title->fs) & 0xf0) != 0x20)) {/* DVD audio data *//* Get the audio format */ int format;//printf("get_ps_pes_packet 5 %x\n", packet_next_char(demuxer) & 0xf0); if((mpeg3io_next_char(title->fs) & 0xf0) == 0xa0) format = AUDIO_PCM; else format = AUDIO_AC3;// Picks up bogus data if (& 0xf) or (& 0x7f) stream_id = mpeg3io_next_char(title->fs); demuxer->pes_audio_time = demuxer->time; if(pts) demuxer->pes_audio_time = pts;//printf("get_ps_pes_packet %x\n", stream_id);/* Take first stream ID if not building TOC. */ if(demuxer->read_all) demuxer->astream_table[stream_id] = format; else if(demuxer->astream == -1) demuxer->astream = stream_id; if(stream_id == demuxer->astream && demuxer->do_audio) { demuxer->aformat = format; mpeg3io_read_int32(title->fs); pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start; decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start; mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size, pes_packet_length, title->fs); demuxer->data_size += pes_packet_length; } else { pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start; mpeg3io_seek_relative(title->fs, pes_packet_length); }//printf("get_ps_pes_packet 6 %d\n", demuxer->astream_table[0x20]); } else if(stream_id == 0xbc || 1) { pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start; mpeg3io_seek_relative(title->fs, pes_packet_length); } } else if(stream_id == MPEG3_PRIVATE_STREAM_2 || stream_id == MPEG3_PADDING_STREAM) { pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start; mpeg3io_seek_relative(title->fs, pes_packet_length); }// Advance 2048 bytes if scrambled. We might pick up a spurrius// packet start code in the scrambled data otherwise. if(scrambling && demuxer->last_packet_start + 0x800 > mpeg3io_tell(title->fs)) { mpeg3io_seek_relative(title->fs, demuxer->last_packet_start + 0x800 - mpeg3io_tell(title->fs)); }// Descramble if desired if(demuxer->data_size && scrambling) {//printf(__FUNCTION__ " data_size=%x decryption_offset=%x\n", demuxer->data_size, decryption_offset); if(mpeg3_decrypt_packet(title->fs->css, demuxer->data_buffer, decryption_offset)) { fprintf(stderr, "get_ps_pes_packet: Decryption not available\n"); return 1; } }//if(mpeg3io_tell(title->fs) - demuxer->last_packet_start != 0x800)// printf(__FUNCTION__ " packet size == %d\n", mpeg3io_tell(title->fs) - demuxer->last_packet_start); return 0;}int mpeg3demux_read_program(mpeg3_demuxer_t *demuxer){ int result = 0; int count = 0; mpeg3_t *file = demuxer->file; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; unsigned int header = 0; int pack_count = 0; demuxer->data_size = 0;//printf("mpeg3demux_read_program 1 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes); if(mpeg3io_eof(title->fs)) return 1;//printf("mpeg3demux_read_program 2 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);/* Search for next header *//* Parse packet until the next packet start code */ while(!result && !mpeg3io_eof(title->fs)) { header = mpeg3io_read_int32(title->fs); if(header == MPEG3_PACK_START_CODE) {// Start of next packet if(pack_count) { mpeg3io_seek_relative(title->fs, -4); break; } demuxer->last_packet_start = mpeg3io_tell(title->fs) - 4; result = get_pack_header(demuxer);//printf("mpeg3demux_read_program MPEG3_PACK_START_CODE %d\n", result); pack_count++; } else if(header == MPEG3_SYSTEM_START_CODE && pack_count) { result = get_system_header(demuxer);//printf("mpeg3demux_read_program MPEG3_SYSTEM_START_CODE %d\n", result); } else if((header >> 8) == MPEG3_PACKET_START_CODE_PREFIX && pack_count) { result = get_ps_pes_packet(demuxer, header);//printf("mpeg3demux_read_program MPEG3_PACKET_START_CODE_PREFIX %d %08x\n", result, header); } else {// Try again. mpeg3io_seek_relative(title->fs, -3); } }//printf("mpeg3demux_read_program 3 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);// Ignore errors in the parsing. Just quit if eof. result = 0; demuxer->last_packet_end = mpeg3io_tell(title->fs);/* * if(demuxer->last_packet_end - demuxer->last_packet_start != 0x800) * printf(__FUNCTION__ " packet_size=%x data_size=%x packet_start=%x\n", * demuxer->last_packet_end - demuxer->last_packet_start, * demuxer->data_size, * demuxer->last_packet_start); *///printf("mpeg3demux_read_program 5 %d\n", result);//printf("read_program 3\n");// if(!result) result = mpeg3io_eof(title->fs); return result;}static double lookup_time_offset(mpeg3_demuxer_t *demuxer, long byte){ int i; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; if(!title->timecode_table_size) return 0; for(i = title->timecode_table_size - 1; i >= 0 && title->timecode_table[i].start_byte > byte; i--) ; if(i < 0) i = 0; return title->timecode_table[i].absolute_start_time - title->timecode_table[i].start_time;}int mpeg3_advance_timecode(mpeg3_demuxer_t *demuxer){ mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; int result = 0; int do_seek = 0; int last_timecode = demuxer->current_timecode;//printf("mpeg3_advance_timecode 0\n");fflush(stdout);/* Don't do anything when constructing timecode table */ if(!title->timecode_table || !title->timecode_table_size || demuxer->read_all) return 0;//printf("mpeg3_advance_timecode 1\n");fflush(stdout); if(!demuxer->reverse) {/* Get inside the current timecode */ if(mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte) { mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); }/* Get the next timecode */ while(!result && (mpeg3io_tell(title->fs) >= title->timecode_table[demuxer->current_timecode].end_byte || demuxer->current_program != title->timecode_table[demuxer->current_timecode].program)) { demuxer->current_timecode++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -