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

📄 mpeg3demux.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 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 + -