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

📄 encode_cbk.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *					GPAC Multimedia Framework * *			Authors: Cyril Concolato - Jean le Feuvre *				Copyright (c) 2005-200X ENST *					All rights reserved * *  This file is part of GPAC / ISO Media File Format 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/bifsengine.h>#ifndef GPAC_READ_ONLY#include <gpac/scene_manager.h>#include <gpac/bifs.h>#include <gpac/constants.h>struct __tag_bifs_engine{	GF_SceneGraph *sg;	GF_SceneManager	*ctx;	GF_SceneLoader load;	void *calling_object;	GF_StreamContext *sc;		GF_BifsEncoder *bifsenc;	u32 stream_ts_res;	/* TODO: maybe the currentAUCount should be a GF_List of u32 	to capture the number of AU per input BIFS stream */	u32 currentAUCount;	char encoded_bifs_config[20];	u32 encoded_bifs_config_size;};static GF_Err gf_sm_live_setup(GF_BifsEngine *codec){	GF_Err e;	char *data;	u32 data_len;	GF_InitialObjectDescriptor *iod;	u32	i, j, count, nbb;	GF_ESD *esd;	Bool is_in_iod, delete_desc, encode_names, delete_bcfg;	GF_BIFSConfig *bcfg;	e = GF_OK;	iod = (GF_InitialObjectDescriptor *) codec->ctx->root_od;	/*if no iod check we only have one bifs*/	if (!iod) {		count = 0;		i=0;		while ((codec->sc = (GF_StreamContext*)gf_list_enum(codec->ctx->streams, &i))) {			if (codec->sc->streamType == GF_STREAM_OD) count++;			codec->sc = NULL;		}		if (!iod && count>1) return GF_NOT_SUPPORTED;	}	codec->sc = NULL;	count = gf_list_count(codec->ctx->streams);	i=0;	while ((codec->sc = (GF_StreamContext*)gf_list_enum(codec->ctx->streams, &i))) {		if (codec->sc->streamType == GF_STREAM_SCENE) break;	}	if (!codec->sc) return GF_NOT_SUPPORTED;	if (!codec->sc->ESID) codec->sc->ESID = 1;	codec->bifsenc = gf_bifs_encoder_new(codec->ctx->scene_graph);	delete_desc = 0;	esd = NULL;	is_in_iod = 1;	if (iod) {		is_in_iod = 0;		j=0;		while ((esd = (GF_ESD*)gf_list_enum(iod->ESDescriptors, &j))) {			if (esd->decoderConfig && esd->decoderConfig->streamType == GF_STREAM_SCENE) {				if (!codec->sc->ESID) codec->sc->ESID = esd->ESID;				if (codec->sc->ESID == esd->ESID) {					is_in_iod = 1;					break;				}			}			/*special BIFS direct import from NHNT*/			else if (gf_list_count(iod->ESDescriptors)==1) {				codec->sc->ESID = esd->ESID;				is_in_iod = 1;				break;			}			esd = NULL;		}	}	if (!esd) {		delete_desc = 1;		esd = gf_odf_desc_esd_new(2);		gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);		esd->decoderConfig->decoderSpecificInfo = NULL;		esd->ESID = codec->sc->ESID;		esd->decoderConfig->streamType = GF_STREAM_SCENE;	}	delete_bcfg = 0;	/*should NOT happen (means inputctx is not properly setup)*/	if (!esd->decoderConfig->decoderSpecificInfo) {		bcfg = (GF_BIFSConfig*)gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG);		bcfg->pixelMetrics = codec->ctx->is_pixel_metrics;		bcfg->pixelWidth = codec->ctx->scene_width;		bcfg->pixelHeight = codec->ctx->scene_height;		delete_bcfg = 1;	}	/*regular retrieve from ctx*/	else if (esd->decoderConfig->decoderSpecificInfo->tag == GF_ODF_BIFS_CFG_TAG) {		bcfg = (GF_BIFSConfig *)esd->decoderConfig->decoderSpecificInfo;	}	/*should not happen either (unless loading from MP4 in which case BIFSc is not decoded)*/	else {		bcfg = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication);		delete_bcfg = 1;	}	/*NO CHANGE TO BIFSC otherwise the generated update will not match the input context, UNLESS NO NbBits	were specified*/	nbb = gf_get_bit_size(codec->ctx->max_node_id);	if (!bcfg->nodeIDbits) bcfg->nodeIDbits = nbb;	else if (bcfg->nodeIDbits<nbb) {		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.NodeIDBits too small (%d bits vs %d nodes)\n", bcfg->nodeIDbits, codec->ctx->max_node_id));	}	nbb = gf_get_bit_size(codec->ctx->max_route_id);	if (!bcfg->routeIDbits) bcfg->routeIDbits = nbb;	else if (bcfg->routeIDbits<nbb) {		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.RouteIDBits too small (%d bits vs %d routes)\n", bcfg->routeIDbits, codec->ctx->max_route_id));	}	nbb = gf_get_bit_size(codec->ctx->max_proto_id);	if (!bcfg->protoIDbits) bcfg->protoIDbits=nbb;	else if (bcfg->protoIDbits<nbb) {		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[BIFS] BIFSConfig.ProtoIDBits too small (%d bits vs %d protos)\n", bcfg->protoIDbits, codec->ctx->max_proto_id));	}	/*this is the real pb, not stored in cfg or file level, set at EACH replaceScene*/	encode_names = 0;	/* The BIFS Config that is passed here should be the BIFSConfig from the IOD */	gf_bifs_encoder_new_stream(codec->bifsenc, codec->sc->ESID, bcfg, encode_names, 0);	if (delete_bcfg) gf_odf_desc_del((GF_Descriptor *)bcfg);	if (!esd->slConfig) esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);	if (codec->sc->timeScale) esd->slConfig->timestampResolution = codec->sc->timeScale;	if (!esd->slConfig->timestampResolution) esd->slConfig->timestampResolution = 1000;	esd->ESID = codec->sc->ESID;	gf_bifs_encoder_get_config(codec->bifsenc, codec->sc->ESID, &data, &data_len);	if (esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);	esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);	esd->decoderConfig->decoderSpecificInfo->data = data;	esd->decoderConfig->decoderSpecificInfo->dataLength = data_len;		codec->stream_ts_res = esd->slConfig->timestampResolution;	memcpy(codec->encoded_bifs_config, data, data_len);	codec->encoded_bifs_config_size = data_len;	esd->decoderConfig->objectTypeIndication = gf_bifs_encoder_get_version(codec->bifsenc, codec->sc->ESID);			return e;}static GF_Err gf_sm_live_encode_bifs_au(GF_BifsEngine *codec, u32 currentAUCount, 						  GF_Err (*AUCallback)(void *, char *, u32 , u64)						  ){	GF_Err e;	u32	j, size, count;	char *data;	GF_AUContext *au;	if (!AUCallback) return GF_BAD_PARAM;	e = GF_OK;	count = gf_list_count(codec->sc->AUs);	for (j=currentAUCount; j<count; j++) {		au = (GF_AUContext *)gf_list_get(codec->sc->AUs, j);		/*in case using XMT*/		if (au->timing_sec) au->timing = (u64) (au->timing_sec * codec->stream_ts_res);		e = gf_bifs_encode_au(codec->bifsenc, codec->sc->ESID, au->commands, &data, &size);		AUCallback(codec->calling_object, data, size, au->timing);		free(data);		data = NULL;		if (e) break;	}	return e;}GF_EXPORTGF_Err gf_beng_aggregate_context(GF_BifsEngine *codec){	GF_Err	e;	/*make random access for storage*/	e = gf_sm_make_random_access(codec->ctx);	if (e) return GF_BAD_PARAM;	return GF_OK;}GF_EXPORTGF_Err gf_beng_save_context(GF_BifsEngine *codec, char *  ctxFileName){	u32	d_mode, do_enc;	char szF[GF_MAX_PATH], *ext;	GF_Err	e;	/*check if we dump to BT, XMT or encode to MP4*/	strcpy(szF, ctxFileName);	ext = strrchr(szF, '.');	d_mode = GF_SM_DUMP_BT;	do_enc = 0;	if (ext) {		if (!stricmp(ext, ".xmt") || !stricmp(ext, ".xmta")) d_mode = GF_SM_DUMP_XMTA;		else if (!stricmp(ext, ".mp4")) do_enc = 1;		ext[0] = 0;	}	if (do_enc) {		GF_ISOFile *mp4;		strcat(szF, ".mp4");		mp4 = gf_isom_open(szF, GF_ISOM_OPEN_WRITE, NULL);		e = gf_sm_encode_to_file(codec->ctx, mp4, NULL);		if (e) gf_isom_delete(mp4);		else gf_isom_close(mp4);	} else {		e = gf_sm_dump(codec->ctx, szF, d_mode);	}	return e;}GF_EXPORTGF_Err gf_beng_encode_from_string(GF_BifsEngine *codec, char *auString, GF_Err (*AUCallback)(void *, char *, u32 , u64 )){	GF_StreamContext *sc;	u32 i, count;	GF_Err e;	memset(&(codec->load), 0, sizeof(GF_SceneLoader));	codec->load.ctx = codec->ctx;		/* Assumes there is only one BIFS stream in the context	   TODO: check how to do it when several BIFS streams are encoded at the same time */	sc = NULL;	count = gf_list_count(codec->ctx->streams);	i = 0;	while ((sc = (GF_StreamContext*)gf_list_enum(codec->ctx->streams, &i))) {		if (sc->streamType == GF_STREAM_SCENE) break;		sc = NULL;	}	if (!sc) return GF_BAD_PARAM;	codec->currentAUCount = gf_list_count(sc->AUs);	codec->load.flags = GF_SM_LOAD_MPEG4_STRICT | GF_SM_LOAD_CONTEXT_READY;	codec->load.type = GF_SM_LOAD_BT;	e = gf_sm_load_string(&codec->load, auString, 0);	if (e) goto exit;	e = gf_sm_live_encode_bifs_au(codec, codec->currentAUCount, AUCallback); exit:	return e;}GF_EXPORTGF_Err gf_beng_encode_from_file(GF_BifsEngine *codec, char *auFile, GF_Err (*AUCallback)(void *, char *, u32 , u64 )){	GF_Err e;	GF_StreamContext *sc;	u32 i, count;	memset(&(codec->load), 0, sizeof(GF_SceneLoader));	codec->load.fileName = auFile;	codec->load.ctx = codec->ctx;	/* Assumes there is only one BIFS stream in the context	   TODO: check how to do it when several BIFS streams are encoded at the same time */	sc = NULL;	count = gf_list_count(codec->ctx->streams);	i=0;	while ((sc = (GF_StreamContext*)gf_list_enum(codec->ctx->streams, &i))) {		if (sc->streamType == GF_STREAM_SCENE) break;		sc = NULL;	}	if (!sc) return GF_BAD_PARAM;	codec->currentAUCount = gf_list_count(sc->AUs);	codec->load.flags = GF_SM_LOAD_MPEG4_STRICT | GF_SM_LOAD_CONTEXT_READY;	e = gf_sm_load_init(&codec->load);	if (!e) e = gf_sm_load_run(&codec->load);	gf_sm_load_done(&codec->load);	if (e) {		GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[BENG] cannot load AU File %s (error %s)\n", auFile, gf_error_to_string(e)));		goto exit;	}	e = gf_sm_live_encode_bifs_au(codec, codec->currentAUCount, AUCallback); 	if (e) goto exit;exit:	return e;}GF_EXPORTGF_Err gf_beng_encode_context(GF_BifsEngine *codec, GF_Err (*AUCallback)(void *, char *, u32 , u64 )){	return gf_sm_live_encode_bifs_au(codec, 0, AUCallback);} GF_EXPORTvoid gf_beng_terminate(GF_BifsEngine *codec){	if (codec->bifsenc) gf_bifs_encoder_del(codec->bifsenc);	if (codec->ctx) gf_sm_del(codec->ctx);	if (codec->sg) gf_sg_del(codec->sg);	free(codec);}GF_EXPORTvoid gf_beng_get_stream_config(GF_BifsEngine *codec, char **config, u32 *config_len){	*config = codec->encoded_bifs_config;	*config_len = codec->encoded_bifs_config_size;}GF_EXPORTGF_BifsEngine *gf_beng_init(void *calling_object, char * inputContext){	GF_BifsEngine *codec;	GF_Err e = GF_OK;	if (!inputContext) return NULL;	GF_SAFEALLOC(codec, GF_BifsEngine)	if (!codec) return NULL;	codec->calling_object = calling_object;	/*Step 1: create context and load input*/	codec->sg = gf_sg_new();	codec->ctx = gf_sm_new(codec->sg);	memset(&(codec->load), 0, sizeof(GF_SceneLoader));	codec->load.ctx = codec->ctx;	/*since we're encoding in BIFS we must get MPEG-4 nodes only*/	codec->load.flags = GF_SM_LOAD_MPEG4_STRICT;	codec->load.fileName = inputContext;	e = gf_sm_load_init(&(codec->load));	if (!e) e = gf_sm_load_run(&(codec->load));	gf_sm_load_done(&(codec->load));	if (e) {		GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[BENG] Cannot load context from %s (error %s)\n", inputContext, gf_error_to_string(e)));		goto exit;	}	e = gf_sm_live_setup(codec);	if (e!=GF_OK) {		GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[BENG] cannot init scene encoder for context (error %s)\n", gf_error_to_string(e)));		goto exit;	}	return codec;exit:	gf_beng_terminate(codec);	return NULL;}GF_EXPORTGF_BifsEngine *gf_beng_init_from_string(void *calling_object, char * inputContext, u32 width, u32 height, Bool usePixelMetrics){	GF_BifsEngine *codec;	GF_Err e = GF_OK;	if (!inputContext) return NULL;	GF_SAFEALLOC(codec, GF_BifsEngine)	if (!codec) return NULL;	codec->calling_object = calling_object;	/*Step 1: create context and load input*/	codec->sg = gf_sg_new();	codec->ctx = gf_sm_new(codec->sg);	memset(&(codec->load), 0, sizeof(GF_SceneLoader));	codec->load.ctx = codec->ctx;	/*since we're encoding in BIFS we must get MPEG-4 nodes only*/	codec->load.flags = GF_SM_LOAD_MPEG4_STRICT;	if (inputContext[0] == '<') {		if (strstr(inputContext, "<svg ")) codec->load.type = GF_SM_LOAD_SVG_DA;		else if (strstr(inputContext, "<saf ")) codec->load.type = GF_SM_LOAD_XSR;		else if (strstr(inputContext, "XMT-A") || strstr(inputContext, "X3D")) codec->load.type = GF_SM_LOAD_XMTA;	} else {		codec->load.type = GF_SM_LOAD_BT;	}	e = gf_sm_load_string(&codec->load, inputContext, 0);	if (e) {		GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[BENG] cannot load context from %s (error %s)\n", inputContext, gf_error_to_string(e)));		goto exit;	}	if (!codec->ctx->root_od) {		codec->ctx->is_pixel_metrics = usePixelMetrics;		codec->ctx->scene_width = width;		codec->ctx->scene_height = height;	}	e = gf_sm_live_setup(codec);	if (e!=GF_OK) {		GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[BENG] cannot init scene encoder for context (error %s)\n", gf_error_to_string(e)));		goto exit;	}	return codec;exit:	gf_beng_terminate(codec);	return NULL;}#endif

⌨️ 快捷键说明

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