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

📄 av_parsers.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / Media Tools sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/internal/media_dev.h>#include <gpac/internal/ogg.h>#include <gpac/constants.h>#include <gpac/math.h>/*	MPEG-4 video (14496-2)*/#define M4V_VO_START_CODE					0x00#define M4V_VOL_START_CODE					0x20#define M4V_VOP_START_CODE					0xB6#define M4V_VISOBJ_START_CODE				0xB5#define M4V_VOS_START_CODE					0xB0#define M4V_GOV_START_CODE					0xB3#define M4V_UDTA_START_CODE					0xB2#define M2V_PIC_START_CODE					0x00#define M2V_SEQ_START_CODE					0xB3#define M2V_EXT_START_CODE					0xB5#define M2V_GOP_START_CODE					0xB8struct __tag_m4v_parser{	GF_BitStream *bs;	Bool mpeg12;	u32 current_object_type;	u32 current_object_start;	u32 tc_dec, prev_tc_dec, tc_disp, prev_tc_disp;};GF_EXPORTGF_M4VParser *gf_m4v_parser_new(char *data, u32 data_size, Bool mpeg12video){	GF_M4VParser *tmp;	if (!data || !data_size) return NULL;	GF_SAFEALLOC(tmp, GF_M4VParser);	tmp->bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);	tmp->mpeg12 = mpeg12video;	return tmp;}GF_M4VParser *gf_m4v_parser_bs_new(GF_BitStream *bs, Bool mpeg12video){	GF_M4VParser *tmp;	GF_SAFEALLOC(tmp, GF_M4VParser);	tmp->bs = bs;	tmp->mpeg12 = mpeg12video;	return tmp;}GF_EXPORTvoid gf_m4v_parser_del(GF_M4VParser *m4v){	gf_bs_del(m4v->bs);	free(m4v);}#define M4V_CACHE_SIZE		4096s32 M4V_LoadObject(GF_M4VParser *m4v){	u32 v, bpos, found;	char m4v_cache[M4V_CACHE_SIZE];	u64 end, cache_start, load_size;	if (!m4v) return 0;	bpos = 0;	found = 0;	load_size = 0;	end = 0;	cache_start = 0;	v = 0xffffffff;	while (!end) {		/*refill cache*/		if (bpos == (u32) load_size) {			if (!gf_bs_available(m4v->bs)) break;			load_size = gf_bs_available(m4v->bs);			if (load_size>M4V_CACHE_SIZE) load_size=M4V_CACHE_SIZE;			bpos = 0;			cache_start = gf_bs_get_position(m4v->bs);			gf_bs_read_data(m4v->bs, m4v_cache, (u32) load_size);		}		v = ( (v<<8) & 0xFFFFFF00) | ((u8) m4v_cache[bpos]);		bpos++;		if ((v & 0xFFFFFF00) == 0x00000100) {			end = cache_start+bpos-4;			found = 1;			break;		}	}	if (!found) return -1;	m4v->current_object_start = (u32) end;	gf_bs_seek(m4v->bs, end+3);	m4v->current_object_type = gf_bs_read_u8(m4v->bs);	return (s32) m4v->current_object_type;}GF_EXPORTconst char *gf_m4v_get_profile_name(u8 video_pl){	switch (video_pl) {	case 0x00: return "Reserved (0x00) Profile";	case 0x01: return "Simple Profile @ Level 1";	case 0x02: return "Simple Profile @ Level 2";	case 0x03: return "Simple Profile @ Level 3";	case 0x08: return "Simple Profile @ Level 0";	case 0x10: return "Simple Scalable Profile @ Level 0";	case 0x11: return "Simple Scalable Profile @ Level 1";	case 0x12: return "Simple Scalable Profile @ Level 2";	case 0x15: return "AVC/H264 Profile";	case 0x21: return "Core Profile @ Level 1";	case 0x22: return "Core Profile @ Level 2";	case 0x32: return "Main Profile @ Level 2";	case 0x33: return "Main Profile @ Level 3";	case 0x34: return "Main Profile @ Level 4";	case 0x42: return "N-bit Profile @ Level 2";	case 0x51: return "Scalable Texture Profile @ Level 1";	case 0x61: return "Simple Face Animation Profile @ Level 1";	case 0x62: return "Simple Face Animation Profile @ Level 2";	case 0x63: return "Simple FBA Profile @ Level 1";	case 0x64: return "Simple FBA Profile @ Level 2";	case 0x71: return "Basic Animated Texture Profile @ Level 1";	case 0x72: return "Basic Animated Texture Profile @ Level 2";	case 0x81: return "Hybrid Profile @ Level 1";	case 0x82: return "Hybrid Profile @ Level 2";	case 0x91: return "Advanced Real Time Simple Profile @ Level 1";	case 0x92: return "Advanced Real Time Simple Profile @ Level 2";	case 0x93: return "Advanced Real Time Simple Profile @ Level 3";	case 0x94: return "Advanced Real Time Simple Profile @ Level 4";	case 0xA1: return "Core Scalable Profile @ Level1";	case 0xA2: return "Core Scalable Profile @ Level2";	case 0xA3: return "Core Scalable Profile @ Level3";	case 0xB1: return "Advanced Coding Efficiency Profile @ Level 1";	case 0xB2: return "Advanced Coding Efficiency Profile @ Level 2";	case 0xB3: return "Advanced Coding Efficiency Profile @ Level 3";	case 0xB4: return "Advanced Coding Efficiency Profile @ Level 4";	case 0xC1: return "Advanced Core Profile @ Level 1";	case 0xC2: return "Advanced Core Profile @ Level 2";	case 0xD1: return "Advanced Scalable Texture @ Level1";	case 0xD2: return "Advanced Scalable Texture @ Level2";	case 0xE1: return "Simple Studio Profile @ Level 1";	case 0xE2: return "Simple Studio Profile @ Level 2";	case 0xE3: return "Simple Studio Profile @ Level 3";	case 0xE4: return "Simple Studio Profile @ Level 4";	case 0xE5: return "Core Studio Profile @ Level 1";	case 0xE6: return "Core Studio Profile @ Level 2";	case 0xE7: return "Core Studio Profile @ Level 3";	case 0xE8: return "Core Studio Profile @ Level 4";	case 0xF0: return "Advanced Simple Profile @ Level 0";	case 0xF1: return "Advanced Simple Profile @ Level 1";	case 0xF2: return "Advanced Simple Profile @ Level 2";	case 0xF3: return "Advanced Simple Profile @ Level 3";	case 0xF4: return "Advanced Simple Profile @ Level 4";	case 0xF5: return "Advanced Simple Profile @ Level 5";	case 0xF7: return "Advanced Simple Profile @ Level 3b";	case 0xF8: return "Fine Granularity Scalable Profile @ Level 0";	case 0xF9: return "Fine Granularity Scalable Profile @ Level 1";	case 0xFA: return "Fine Granularity Scalable Profile @ Level 2";	case 0xFB: return "Fine Granularity Scalable Profile @ Level 3";	case 0xFC: return "Fine Granularity Scalable Profile @ Level 4";	case 0xFD: return "Fine Granularity Scalable Profile @ Level 5";	case 0xFE: return "Not part of MPEG-4 Visual profiles";	case 0xFF: return "No visual capability required";	default: return "ISO Reserved Profile";	}}GF_EXPORTvoid gf_m4v_rewrite_pl(char **o_data, u32 *o_dataLen, u8 PL){	u32 pos = 0;	unsigned char *data = (unsigned char *)*o_data;	u32 dataLen = *o_dataLen;	while (pos+4<dataLen) {		if (!data[pos] && !data[pos+1] && (data[pos+2]==0x01) && (data[pos+3]==M4V_VOS_START_CODE)) {			data[pos+4] = PL;			return;		}		pos ++;	}	/*emulate VOS at beggining*/	(*o_data) = (char *)malloc(sizeof(char)*(dataLen+5));	(*o_data)[0] = 0;	(*o_data)[1] = 0;	(*o_data)[2] = 1;	(*o_data)[3] = (char) M4V_VOS_START_CODE;	(*o_data)[4] = PL;	memcpy( (*o_data + 5), data, sizeof(char)*dataLen);	free(data);	(*o_dataLen) = dataLen + 5;}static GF_Err M4V_Reset(GF_M4VParser *m4v, u32 start){	gf_bs_seek(m4v->bs, start);	m4v->current_object_start = start;	m4v->current_object_type = 0;	return GF_OK;}static GF_Err gf_m4v_parse_config_mpeg12(GF_M4VParser *m4v, GF_M4VDecSpecInfo *dsi){	char p[4];	s32 o_type;	u8 go, par;	if (!m4v || !dsi) return GF_BAD_PARAM;	memset(dsi, 0, sizeof(GF_M4VDecSpecInfo));	dsi->VideoPL = 0;	go = 1;	while (go) {		o_type = M4V_LoadObject(m4v);		switch (o_type) {		case M2V_SEQ_START_CODE:			dsi->RAP_stream = 1;			gf_bs_read_data(m4v->bs, p, 4);			dsi->width = (p[0] << 4) | ((p[1] >> 4) & 0xf);			dsi->height = ((p[1] & 0xf) << 8) | p[2];			dsi->VideoPL = 0x6A;			par = (p[3] >> 4) & 0xf;			switch (par) {			case 2: dsi->par_num = 4; dsi->par_den = 3; break;			case 3: dsi->par_num = 16; dsi->par_den = 9; break;			case 4: dsi->par_num = 2; dsi->par_den = 21; break;			default: dsi->par_den = dsi->par_num = 0; break;			}			switch (p[3] & 0xf) {			case 0: break;			case 1: dsi->fps = 24000.0/1001.0; break;			case 2: dsi->fps = 24.0; break;			case 3: dsi->fps = 25.0; break;			case 4: dsi->fps = 30000.0/1001.0; break;			case 5: dsi->fps = 30.0; break;			case 6: dsi->fps = 50.0; break;			case 7: dsi->fps = ((60.0*1000.0)/1001.0); break;			case 8: dsi->fps = 60.0; break;			case 9: dsi->fps = 1; break;			case 10: dsi->fps = 5; break;			case 11: dsi->fps = 10; break;			case 12: dsi->fps = 12; break;			case 13: dsi->fps = 15; break;			}			break;		case M2V_EXT_START_CODE:			gf_bs_read_data(m4v->bs, p, 4);			if ( ((p[0] >> 4) & 0xf) == 1) {			  dsi->VideoPL = 0x65;			  dsi->height = ((p[1] & 0x1) << 13) | ((p[2] & 0x80) << 5) | (dsi->height & 0x0fff);			  dsi->width = (((p[2] >> 5) & 0x3) << 12) | (dsi->width & 0x0fff);			}			break;		case M2V_PIC_START_CODE:			go = 0;			break;		default:			break;		/*EOS*/		case -1:			go = 0;			m4v->current_object_start = (u32) gf_bs_get_position(m4v->bs);			break;		}	}	M4V_Reset(m4v, 0);	return GF_OK;}static const struct { u32 w, h; } m4v_sar[6] = { { 0,   0 }, { 1,   1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 } };static u8 m4v_get_sar_idx(u32 w, u32 h){	u32 i;	for (i=0; i<6; i++) {		if ((m4v_sar[i].w==w) && (m4v_sar[i].h==h)) return i;	}	return 0xF;}static GF_Err gf_m4v_parse_config_mpeg4(GF_M4VParser *m4v, GF_M4VDecSpecInfo *dsi){	s32 o_type;	u8 go, verid, par;	s32 clock_rate;	if (!m4v || !dsi) return GF_BAD_PARAM;	memset(dsi, 0, sizeof(GF_M4VDecSpecInfo));	go = 1;	while (go) {		o_type = M4V_LoadObject(m4v);		switch (o_type) {		/*vosh*/		case M4V_VOS_START_CODE:			dsi->VideoPL = (u8) gf_bs_read_u8(m4v->bs);			break;		case M4V_VOL_START_CODE:			verid = 0;			dsi->RAP_stream = gf_bs_read_int(m4v->bs, 1);			dsi->objectType = gf_bs_read_int(m4v->bs, 8);			if (gf_bs_read_int(m4v->bs, 1)) {				verid = gf_bs_read_int(m4v->bs, 4);				gf_bs_read_int(m4v->bs, 3);			}			par = gf_bs_read_int(m4v->bs, 4);			if (par == 0xF) {				dsi->par_num = gf_bs_read_int(m4v->bs, 8);				dsi->par_den = gf_bs_read_int(m4v->bs, 8);			} else if (par<6) {				dsi->par_num = m4v_sar[par].w;				dsi->par_den = m4v_sar[par].h;			}			if (gf_bs_read_int(m4v->bs, 1)) {				gf_bs_read_int(m4v->bs, 3);				if (gf_bs_read_int(m4v->bs, 1)) gf_bs_read_int(m4v->bs, 79);			}			dsi->has_shape = gf_bs_read_int(m4v->bs, 2);			if (dsi->has_shape && (verid!=1) ) gf_bs_read_int(m4v->bs, 4);			gf_bs_read_int(m4v->bs, 1);			/*clock rate*/			dsi->clock_rate = gf_bs_read_int(m4v->bs, 16);			/*marker*/			gf_bs_read_int(m4v->bs, 1);			clock_rate = dsi->clock_rate-1;			if (clock_rate >= 65536) clock_rate = 65535;			if (clock_rate > 0) {				for (dsi->NumBitsTimeIncrement = 1; dsi->NumBitsTimeIncrement < 16; dsi->NumBitsTimeIncrement++)	{						if (clock_rate == 1) break;					clock_rate = (clock_rate >> 1);				}			} else {				/*fix from vivien for divX*/				dsi->NumBitsTimeIncrement = 1;			}						/*fixed FPS stream*/			dsi->time_increment = 0;			if (gf_bs_read_int(m4v->bs, 1)) {				dsi->time_increment = gf_bs_read_int(m4v->bs, dsi->NumBitsTimeIncrement);			}			if (!dsi->has_shape) {				gf_bs_read_int(m4v->bs, 1);				dsi->width = gf_bs_read_int(m4v->bs, 13);				gf_bs_read_int(m4v->bs, 1);				dsi->height = gf_bs_read_int(m4v->bs, 13);			} else {				dsi->width = dsi->height = 0;			}			/*shape will be done later*/			gf_bs_align(m4v->bs);			break;		case M4V_VOP_START_CODE:		case M4V_GOV_START_CODE:			go = 0;			break;		/*EOS*/		case -1:			go = 0;			m4v->current_object_start = (u32) gf_bs_get_position(m4v->bs);			break;		/*don't interest us*/		case M4V_UDTA_START_CODE:		default:			break;		}	}	return GF_OK;}GF_EXPORTGF_Err gf_m4v_parse_config(GF_M4VParser *m4v, GF_M4VDecSpecInfo *dsi){	if (m4v->mpeg12) {		return gf_m4v_parse_config_mpeg12(m4v, dsi);	} else {		return gf_m4v_parse_config_mpeg4(m4v, dsi);	}}static GF_Err gf_m4v_parse_frame_mpeg12(GF_M4VParser *m4v, GF_M4VDecSpecInfo dsi, u8 *frame_type, u32 *time_inc, u32 *size, u32 *start, Bool *is_coded){	u8 go, hasVOP, firstObj, val;	s32 o_type;	if (!m4v || !size || !start || !frame_type) return GF_BAD_PARAM;	*size = 0;	firstObj = 1;	hasVOP = 0;	*is_coded = 0;	m4v->current_object_type = (u32) -1;	*frame_type = 0;	M4V_Reset(m4v, m4v->current_object_start);	go = 1;		while (go) {		o_type = M4V_LoadObject(m4v);		switch (o_type) {		case M2V_PIC_START_CODE:			/*done*/			if (hasVOP) {				go = 0;				break;			}			if (firstObj) {				*start = m4v->current_object_start;				firstObj = 0;			}			hasVOP = 1;			*is_coded = 1;			val = gf_bs_read_u8(m4v->bs);			val = gf_bs_read_u8(m4v->bs);			*frame_type = ( (val >> 3) & 0x7 ) - 1;			break;		case M2V_GOP_START_CODE:			if (firstObj) {				*start = m4v->current_object_start;				firstObj = 0;			}			if (hasVOP) go = 0;			break;		case M2V_SEQ_START_CODE:			if (firstObj) {				*start = m4v->current_object_start;				firstObj = 0;			}			if (hasVOP) {				go = 0;				break;			}			/**/			break;		default:			break;		case -1:			*size = (u32) gf_bs_get_position(m4v->bs) - *start;			return GF_EOS;		}	}	*size = m4v->current_object_start - *start;	return GF_OK;}static GF_Err gf_m4v_parse_frame_mpeg4(GF_M4VParser *m4v, GF_M4VDecSpecInfo dsi, u8 *frame_type, u32 *time_inc, u32 *size, u32 *start, Bool *is_coded){	u8 go, hasVOP, firstObj, secs;	s32 o_type;	u32 vop_inc = 0;	if (!m4v || !size || !start || !frame_type) return GF_BAD_PARAM;	*size = 0;	firstObj = 1;	hasVOP = 0;	*is_coded = 0;	m4v->current_object_type = (u32) -1;	*frame_type = 0;	M4V_Reset(m4v, m4v->current_object_start);	go = 1;	while (go) {		o_type = M4V_LoadObject(m4v);		switch (o_type) {		case M4V_VOP_START_CODE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -