⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg3demux.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#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 + -