📄 mpeg3demux.c
字号:
#include "libmpeg3.h"#include "mpeg3io.h"#include "mpeg3protos.h"#include "workarounds.h"#include <errno.h>#include <math.h>#include <stdlib.h>#include <string.h>#define ABS(x) ((x) >= 0 ? (x) : -(x))/* Don't advance pointer */static __inline unsigned char packet_next_char(mpeg3_demuxer_t *demuxer){//printf(__FUNCTION__ " called\n"); return demuxer->raw_data[demuxer->raw_offset];}/* Advance pointer */static unsigned char packet_read_char(mpeg3_demuxer_t *demuxer){ unsigned char result = demuxer->raw_data[demuxer->raw_offset++];//printf(__FUNCTION__ " called\n"); return result;}static __inline unsigned int packet_read_int16(mpeg3_demuxer_t *demuxer){ unsigned int a, b, result;//printf(__FUNCTION__ " called\n"); a = demuxer->raw_data[demuxer->raw_offset++]; b = demuxer->raw_data[demuxer->raw_offset++]; result = (a << 8) | b; return result;}static __inline unsigned int packet_next_int24(mpeg3_demuxer_t *demuxer){ unsigned int a, b, c, result;//printf(__FUNCTION__ " called\n"); a = demuxer->raw_data[demuxer->raw_offset]; b = demuxer->raw_data[demuxer->raw_offset + 1]; c = demuxer->raw_data[demuxer->raw_offset + 2]; result = (a << 16) | (b << 8) | c; return result;}static __inline unsigned int packet_read_int24(mpeg3_demuxer_t *demuxer){ unsigned int a, b, c, result;//printf(__FUNCTION__ " called\n"); a = demuxer->raw_data[demuxer->raw_offset++]; b = demuxer->raw_data[demuxer->raw_offset++]; c = demuxer->raw_data[demuxer->raw_offset++]; result = (a << 16) | (b << 8) | c; return result;}static __inline unsigned int packet_read_int32(mpeg3_demuxer_t *demuxer){ unsigned int a, b, c, d, result;//printf(__FUNCTION__ " called\n"); a = demuxer->raw_data[demuxer->raw_offset++]; b = demuxer->raw_data[demuxer->raw_offset++]; c = demuxer->raw_data[demuxer->raw_offset++]; d = demuxer->raw_data[demuxer->raw_offset++]; result = (a << 24) | (b << 16) | (c << 8) | d; return result;}static __inline unsigned int packet_skip(mpeg3_demuxer_t *demuxer, long length){//printf(__FUNCTION__ " called\n"); demuxer->raw_offset += length; return 0;}static int get_adaptation_field(mpeg3_demuxer_t *demuxer){ long length; int pcr_flag; demuxer->adaptation_fields++;/* get adaptation field length */ length = packet_read_char(demuxer); if(length > 0) {/* get first byte */ pcr_flag = (packet_read_char(demuxer) >> 4) & 1; if(pcr_flag) { unsigned long clk_ref_base = packet_read_int32(demuxer); unsigned int clk_ref_ext = packet_read_int16(demuxer); if (clk_ref_base > 0x7fffffff) { /* correct for invalid numbers */ clk_ref_base = 0; /* ie. longer than 32 bits when multiplied by 2 */ clk_ref_ext = 0; /* multiplied by 2 corresponds to shift left 1 (<<=1) */ } else { clk_ref_base <<= 1; /* Create space for bit */ clk_ref_base |= (clk_ref_ext >> 15); /* Take bit */ clk_ref_ext &= 0x01ff; /* Only lower 9 bits */ } demuxer->time = ((double)clk_ref_base + clk_ref_ext / 300) / 90000; if(length) packet_skip(demuxer, length - 7); } else packet_skip(demuxer, length - 1); } return 0;}static int get_program_association_table(mpeg3_demuxer_t *demuxer){ demuxer->program_association_tables++; demuxer->table_id = packet_read_char(demuxer); demuxer->section_length = packet_read_int16(demuxer) & 0xfff; demuxer->transport_stream_id = packet_read_int16(demuxer); packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0;}static int get_data_buffer(mpeg3_demuxer_t *demuxer){ while(demuxer->raw_offset < demuxer->raw_size && demuxer->data_size < MPEG3_RAW_SIZE) { demuxer->data_buffer[demuxer->data_size++] = demuxer->raw_data[demuxer->raw_offset++]; } return 0;}static int get_pes_packet_header(mpeg3_demuxer_t *demuxer, unsigned long *pts, unsigned long *dts){ unsigned int pes_header_bytes = 0; unsigned int pts_dts_flags; int pes_header_data_length;/* drop first 8 bits */ packet_read_char(demuxer); pts_dts_flags = (packet_read_char(demuxer) >> 6) & 0x3; pes_header_data_length = packet_read_char(demuxer);/* Get Presentation Time stamps and Decoding Time Stamps */ if(pts_dts_flags == 2) { *pts = (packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ *pts <<= 15; *pts |= (packet_read_int16(demuxer) >> 1); *pts <<= 15; *pts |= (packet_read_int16(demuxer) >> 1); pes_header_bytes += 5; } else if(pts_dts_flags == 3) { *pts = (packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ *pts <<= 15; *pts |= (packet_read_int16(demuxer) >> 1); *pts <<= 15; *pts |= (packet_read_int16(demuxer) >> 1); *dts = (packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ *dts <<= 15; *dts |= (packet_read_int16(demuxer) >> 1); *dts <<= 15; *dts |= (packet_read_int16(demuxer) >> 1); pes_header_bytes += 10; } demuxer->time = (double)*pts / 90000;//printf("get_pes_packet_header %f\n", demuxer->time);/* extract other stuff here! */ packet_skip(demuxer, pes_header_data_length - pes_header_bytes); return 0;}static int get_unknown_data(mpeg3_demuxer_t *demuxer){ packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0;}// Combine the pid and the stream id into one unit#define CUSTOM_ID(pid, stream_id) (((pid << 8) | stream_id) & 0xffff)static int get_pes_packet_data(mpeg3_demuxer_t *demuxer, unsigned int stream_id){ unsigned long pts = 0, dts = 0; get_pes_packet_header(demuxer, &pts, &dts);//printf("get_pes_packet_data %x\n", CUSTOM_ID(demuxer->pid, stream_id)); if(stream_id == 0xbd) {// Don't know if the next byte is the true stream id like in program stream stream_id = 0x0; if(demuxer->read_all) demuxer->astream_table[CUSTOM_ID(demuxer->pid, stream_id)] = AUDIO_AC3; if(demuxer->astream == -1) demuxer->astream = CUSTOM_ID(demuxer->pid, stream_id); if(CUSTOM_ID(demuxer->pid, stream_id) == demuxer->astream && demuxer->do_audio) {// get_pes_packet_header(demuxer, &pts, &dts); demuxer->pes_audio_time = pts; demuxer->audio_pid = demuxer->pid; return get_data_buffer(demuxer); } } else if((stream_id >> 4) == 12 || (stream_id >> 4) == 13) {/* Just pick the first available stream if no ID is set *///printf("get_pes_packet_data audio %x\n", stream_id); if(demuxer->read_all) demuxer->astream_table[CUSTOM_ID(demuxer->pid, stream_id)] = AUDIO_MPEG; if(demuxer->astream == -1) demuxer->astream = CUSTOM_ID(demuxer->pid, stream_id); if(CUSTOM_ID(demuxer->pid, stream_id) == demuxer->astream && demuxer->do_audio) {// get_pes_packet_header(demuxer, &pts, &dts); demuxer->pes_audio_time = pts; demuxer->audio_pid = demuxer->pid; return get_data_buffer(demuxer); } } else if((stream_id >> 4) == 14) {//printf("get_pes_packet_data video %x\n", stream_id);/* Just pick the first available stream if no ID is set */ if(demuxer->read_all) demuxer->vstream_table[CUSTOM_ID(demuxer->pid, stream_id)] = 1; else if(demuxer->vstream == -1) demuxer->vstream = (CUSTOM_ID(demuxer->pid, stream_id)); if(CUSTOM_ID(demuxer->pid, stream_id) == demuxer->vstream && demuxer->do_video) {// get_pes_packet_header(demuxer, &pts, &dts); demuxer->pes_video_time = pts; demuxer->video_pid = demuxer->pid; return get_data_buffer(demuxer); } } else { return get_unknown_data(demuxer); } packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0;}static int get_pes_packet(mpeg3_demuxer_t *demuxer){ unsigned int stream_id; demuxer->pes_packets++;/* Skip startcode */ packet_read_int24(demuxer); stream_id = packet_read_char(demuxer);/* Skip pes packet length */ packet_read_int16(demuxer); if(stream_id != MPEG3_PRIVATE_STREAM_2 && stream_id != MPEG3_PADDING_STREAM) { return get_pes_packet_data(demuxer, stream_id); } else if(stream_id == MPEG3_PRIVATE_STREAM_2) {/* Dump private data! */ fprintf(stderr, "stream_id == MPEG3_PRIVATE_STREAM_2\n"); packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0; } else if(stream_id == MPEG3_PADDING_STREAM) { packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); return 0; } else { fprintf(stderr, "unknown stream_id in pes packet"); return 1; } return 0;}static int get_payload(mpeg3_demuxer_t *demuxer){//printf("get_payload 1 %x %d\n", demuxer->pid, demuxer->payload_unit_start_indicator); if(demuxer->payload_unit_start_indicator) { if(demuxer->pid==0) get_program_association_table(demuxer); else if(packet_next_int24(demuxer) == MPEG3_PACKET_START_CODE_PREFIX) get_pes_packet(demuxer); else packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); } else {//printf("get_payload 2\n"); if(demuxer->pid == demuxer->audio_pid && demuxer->do_audio) { get_data_buffer(demuxer); } else if(demuxer->pid == demuxer->video_pid && demuxer->do_video) { get_data_buffer(demuxer); } else packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); } return 0;}/* Read a transport packet */static int read_transport(mpeg3_demuxer_t *demuxer){ mpeg3_t *file = (mpeg3_t*)demuxer->file; mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; int result = 0; unsigned int bits; int table_entry;//printf("read_transport 1 %d\n", file->packet_size);/* Packet size is known for transport streams */ demuxer->raw_size = file->packet_size; demuxer->raw_offset = 0; if(result) { perror("read_transport"); return 1; }//printf("read transport 1\n");// Search for Sync byte */ do { bits = mpeg3io_read_char(title->fs); }while(!mpeg3io_eof(title->fs) && !result && bits != MPEG3_SYNC_BYTE);//printf("read transport 2 bits=%x tell=%llx packet_size=%x\n", bits, mpeg3io_tell(title->fs), file->packet_size); if(bits == MPEG3_SYNC_BYTE && !result) { demuxer->raw_data[0] = MPEG3_SYNC_BYTE; result = mpeg3io_read_data(demuxer->raw_data + 1, file->packet_size - 1, title->fs); } else return 1; packet_read_char(demuxer); bits = packet_read_int24(demuxer) & 0x00ffffff;//printf("read transport 3 tell=%x bits=%x\n", mpeg3io_tell(title->fs), bits); demuxer->transport_error_indicator = (bits >> 23) & 0x1; demuxer->payload_unit_start_indicator = (bits >> 22) & 0x1; demuxer->pid = (bits >> 8) & 0x00001fff; demuxer->transport_scrambling_control = (bits >> 6) & 0x3; demuxer->adaptation_field_control = (bits >> 4) & 0x3; demuxer->continuity_counter = bits & 0xf;//printf("read_transport 4 %x\n", demuxer->pid); if(demuxer->transport_error_indicator) { fprintf(stderr, "demuxer->transport_error_indicator\n"); return 1; }//printf("read_transport 5 %x\n", demuxer->pid); if (demuxer->pid == 0x1fff) { demuxer->is_padding = 1; /* padding; just go to next */ return 0; } else { demuxer->is_padding = 0; }//printf("read_transport 6 %x\n", demuxer->pid);/* Get pid */ for(table_entry = 0, result = 0; table_entry < demuxer->total_pids; table_entry++) { if(demuxer->pid == demuxer->pid_table[table_entry]) { result = 1; break; } }//printf("read_transport 7 %x\n", demuxer->pid);/* Not in pid table */ if(!result) { demuxer->pid_table[table_entry] = demuxer->pid; demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; /* init */ demuxer->total_pids++;//printf("read_transport program id detected %x\n", demuxer->pid); } result = 0;#if 0/* Check counters */ if(demuxer->pid != MPEG3_PROGRAM_ASSOCIATION_TABLE && demuxer->pid != MPEG3_CONDITIONAL_ACCESS_TABLE && (demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3)) { if(demuxer->continuity_counters[table_entry] != demuxer->continuity_counter) {// fprintf(stderr, "demuxer->continuity_counters[table_entry] != demuxer->continuity_counter\n");/* Reset it */ demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; } if(++(demuxer->continuity_counters[table_entry]) > 15) demuxer->continuity_counters[table_entry] = 0; }#endif//printf("read_transport 8 %x %x\n", demuxer->adaptation_field_control, demuxer->pid); if(demuxer->adaptation_field_control == 2 || demuxer->adaptation_field_control == 3) result = get_adaptation_field(demuxer);// Need to enter in astream and vstream table:// PID ored with stream_id if(demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3) result = get_payload(demuxer); return result;}static int get_system_header(mpeg3_demuxer_t *demuxer){ mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; int length = mpeg3io_read_int16(title->fs); mpeg3io_seek_relative(title->fs, length); return 0;}static unsigned long get_timestamp(mpeg3_demuxer_t *demuxer){ unsigned long timestamp; mpeg3_title_t *title = demuxer->titles[demuxer->current_title];/* Only low 4 bits (7==1111) */ timestamp = (mpeg3io_read_char(title->fs) >> 1) & 7; timestamp <<= 15; timestamp |= (mpeg3io_read_int16(title->fs) >> 1); timestamp <<= 15; timestamp |= (mpeg3io_read_int16(title->fs) >> 1); return timestamp;}static int get_pack_header(mpeg3_demuxer_t *demuxer){ unsigned long i, j; unsigned long clock_ref, clock_ref_ext; mpeg3_title_t *title = demuxer->titles[demuxer->current_title];/* Get the time code */ if((mpeg3io_next_char(title->fs) >> 4) == 2) {/* MPEG-1 */ demuxer->time = (double)get_timestamp(demuxer) / 90000;/* Skip 3 bytes */ mpeg3io_read_int24(title->fs); } else if(mpeg3io_next_char(title->fs) & 0x40) { i = mpeg3io_read_int32(title->fs); j = mpeg3io_read_int16(title->fs); if(i & 0x40000000 || (i >> 28) == 2) { clock_ref = ((i & 0x38000000) << 3); clock_ref |= ((i & 0x03fff800) << 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -