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

📄 object_manager.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / Media terminal 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/terminal_dev.h>#include <gpac/constants.h>#include "media_memory.h"#include "media_control.h"#include "input_sensor.h"/*removes the channel ressources and destroy it*/void ODM_DeleteChannel(GF_ObjectManager *odm, struct _es_channel *ch);GF_EXPORTGF_ObjectManager *gf_odm_new(){	GF_ObjectManager *tmp;	GF_SAFEALLOC(tmp, GF_ObjectManager);	if (!tmp) return NULL;	tmp->channels = gf_list_new();	tmp->Audio_PL = (u8) -1;	tmp->Graphics_PL = (u8) -1;	tmp->OD_PL = (u8) -1;	tmp->Scene_PL = (u8) -1;	tmp->Visual_PL = (u8) -1;	tmp->ms_stack = gf_list_new();	tmp->mc_stack = gf_list_new();	tmp->mx = gf_mx_new();	return tmp;}void gf_odm_del(GF_ObjectManager *odm){	u32 i;	MediaSensorStack *media_sens;	gf_mx_p(odm->mx);	i=0;	while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i))) {		MS_Stop(media_sens);		/*and detach from stream object*/		media_sens->is_init = 0;	}	if (odm->mo) odm->mo->odm = NULL;	gf_list_del(odm->channels);	gf_list_del(odm->ms_stack);	gf_list_del(odm->mc_stack);	gf_odf_desc_del((GF_Descriptor *)odm->OD);	assert (!odm->net_service);	gf_mx_v(odm->mx);	gf_mx_del(odm->mx);	free(odm);}void gf_odm_lock(GF_ObjectManager *odm, u32 LockIt){	assert(odm);	if (LockIt) 		gf_mx_p(odm->mx);	else		gf_mx_v(odm->mx);}Bool gf_odm_lock_mo(GF_MediaObject *mo){	if (!mo || !mo->odm) return 0;	gf_odm_lock(mo->odm, 1);	/*the ODM may have been destroyed here !!*/	if (!mo->odm) return 0;	return 1;}GF_EXPORTvoid gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove){	GF_Channel *ch;	gf_odm_stop(odm, 1);	/*disconnect sub-scene*/	if (odm->subscene) gf_is_disconnect(odm->subscene, do_remove);	/*no destroy*/	if (!do_remove) return;	gf_odm_lock(odm, 1);	/*unload the decoders before deleting the channels to prevent any access fault*/	if (odm->codec) gf_term_remove_codec(odm->term, odm->codec);	if (odm->ocr_codec) gf_term_remove_codec(odm->term, odm->ocr_codec);	if (odm->oci_codec) gf_term_remove_codec(odm->term, odm->oci_codec);	/*then delete all the channels in this OD */	while (gf_list_count(odm->channels)) {		ch = (GF_Channel*)gf_list_get(odm->channels, 0);#if 0		if (ch->clock->mc && ch->clock->mc->stream && ch->clock->mc->stream->odm==odm) {			ch->clock->mc->stream = NULL;			ch->clock->mc = NULL;		}#endif		ODM_DeleteChannel(odm, ch);	}	/*delete the decoders*/	if (odm->codec) {		gf_codec_del(odm->codec);		odm->codec = NULL;	}	if (odm->ocr_codec) {		gf_codec_del(odm->ocr_codec);		odm->ocr_codec = NULL;	}	if (odm->oci_codec) {		gf_codec_del(odm->oci_codec);		odm->oci_codec = NULL;	}	/*then detach from network service*/	if (odm->net_service) {		if (odm->net_service->owner == odm) {			if (odm->net_service->nb_odm_users) odm->net_service->nb_odm_users--;			/*detach it!!*/			odm->net_service->owner = NULL;			/*try to assign a new root in case this is not scene shutdown*/			if (odm->net_service->nb_odm_users && odm->parentscene) {				GF_ObjectManager *new_root;				u32 i = 0;				while ((new_root = (GF_ObjectManager *)gf_list_enum(odm->parentscene->ODlist, &i)) ) {					if (new_root == odm) continue;					if (new_root->net_service != odm->net_service) continue;					new_root->net_service->owner = new_root;					break;				}			}		}		if (!odm->net_service->nb_odm_users) gf_term_close_services(odm->term, odm->net_service);		odm->net_service = NULL;	}	gf_odm_lock(odm, 0);	/*delete from the parent scene.*/	if (odm->parentscene) {		gf_is_remove_object(odm->parentscene, odm, do_remove);		if (odm->subscene) gf_is_del(odm->subscene);		gf_odm_del(odm);		return;	}		/*this is the scene root OD (may be a remote OD ..) */	if (odm->term->root_scene) {		GF_Event evt;		assert(odm->term->root_scene == odm->subscene);		gf_is_del(odm->subscene);		/*reset main pointer*/		odm->term->root_scene = NULL;		evt.type = GF_EVENT_CONNECT;		evt.connect.is_connected = 0;		GF_USER_SENDEVENT(odm->term->user, &evt);	}	/*delete the ODMan*/	gf_odm_del(odm);}/*setup service for OD (extract IOD and go)*/void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url){	u32 od_type;	char *ext;	char *sub_url = (char *) service_sub_url;	GF_Terminal *term;	GF_Descriptor *desc;	GF_IPMP_ToolList *toolList;	assert(odm->OD==NULL);	odm->net_service->nb_odm_users++;	if (odm->subscene) od_type = GF_MEDIA_OBJECT_SCENE;	else if (odm->mo) {		od_type = odm->mo->type;		if (!sub_url && odm->mo->URLs.count && odm->mo->URLs.vals[0].url) {			sub_url = odm->mo->URLs.vals[0].url;		}	}	else od_type = GF_MEDIA_OBJECT_UNDEF;	/*for remote ODs, get expected OD type in case the service needs to generate the IOD on the fly*/	if (odm->parentscene && odm->OD && odm->OD->URLString) {		GF_MediaObject *mo;		mo = gf_is_find_object(odm->parentscene, odm->OD->objectDescriptorID, odm->OD->URLString);		if (mo) od_type = mo->type;		ext = strchr(odm->OD->URLString, '#');		if (ext) sub_url = ext;	}	desc = odm->net_service->ifce->GetServiceDescriptor(odm->net_service->ifce, od_type, sub_url); 	/*create empty service descriptor, this will automatically create a dynamic scene*/	if (!desc) {		if (od_type != GF_MEDIA_OBJECT_SCENE)			return;		desc = gf_odf_desc_new(GF_ODF_OD_TAG);	}	if (!gf_list_count( ((GF_ObjectDescriptor*)desc)->ESDescriptors)) {		/*new subscene*/		if (!odm->subscene) {			assert(odm->parentscene);			odm->subscene = gf_is_new(odm->parentscene);			odm->subscene->root_od = odm;		}	}	toolList = NULL;	switch (desc->tag) {	case GF_ODF_IOD_TAG:	{		GF_InitialObjectDescriptor *the_iod = (GF_InitialObjectDescriptor *)desc;		odm->OD = (GF_ObjectDescriptor*)malloc(sizeof(GF_ObjectDescriptor));		memcpy(odm->OD, the_iod, sizeof(GF_ObjectDescriptor));		odm->OD->tag = GF_ODF_OD_TAG;		/*Check P&Ls of this IOD*/		odm->Audio_PL = the_iod->audio_profileAndLevel;		odm->Graphics_PL = the_iod->graphics_profileAndLevel;		odm->OD_PL = the_iod->OD_profileAndLevel;		odm->Scene_PL = the_iod->scene_profileAndLevel;		odm->Visual_PL = the_iod->visual_profileAndLevel;		odm->flags |= GF_ODM_HAS_PROFILES;		if (the_iod->inlineProfileFlag) odm->flags |= GF_ODM_INLINE_PROFILES;		toolList = the_iod->IPMPToolList;		free(the_iod);	}		break;	case GF_ODF_OD_TAG:		odm->Audio_PL = odm->Graphics_PL = odm->OD_PL = odm->Scene_PL = odm->Visual_PL = (u8) -1;		odm->OD = (GF_ObjectDescriptor *)desc;		break;	default:		gf_term_message(odm->term, odm->net_service->url, "MPEG4 Service Setup Failure", GF_ODF_INVALID_DESCRIPTOR);		goto err_exit;	}		if (toolList) {		Bool ipmp_failed = 0;/*		GF_IPMP_Tool *ipmpt;		i=0;		while ((ipmpt = gf_list_enum(toolList->ipmp_tools, &i))) {			if (!Term_CheckIPMPTool(odm->term, ipmpt)) {				ipmp_failed = 1;				break;			}		}*/		gf_odf_desc_del((GF_Descriptor *)toolList);		if (ipmp_failed) {			gf_term_message(odm->term, odm->net_service->url, "MPEG4 IPMP Setup Failure - cannot process content", GF_SERVICE_ERROR);			goto err_exit;		}	}	/*keep track of term since the setup may fail and the OD may be destroyed*/	term = odm->term;	gf_term_lock_net(term, 1);	gf_odm_setup_object(odm, odm->net_service);	gf_term_lock_net(term, 0);	return;err_exit:	if (!odm->parentscene) {		GF_Event evt;		evt.type = GF_EVENT_CONNECT;		evt.connect.is_connected = 0;		GF_USER_SENDEVENT(odm->term->user, &evt);	}}/*locate ESD by ID*/static GF_ESD *od_get_esd(GF_ObjectDescriptor *OD, u16 ESID){	GF_ESD *esd;	u32 i = 0;	while ((esd = (GF_ESD *)gf_list_enum(OD->ESDescriptors, &i)) ) {		if (esd->ESID==ESID) return esd;	}	return NULL;}static void ODM_SelectAlternateStream(GF_ObjectManager *odm, u32 lang_code, u8 stream_type){	u32 i;	GF_ESD *esd;	u16 def_id, es_id;	def_id = 0;	i=0;	while ( (esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {		if (esd->decoderConfig->streamType != stream_type) continue;		if (!esd->langDesc) {			if (!def_id) def_id = esd->ESID;			continue;		}		if (esd->langDesc->langCode==lang_code) {			def_id = esd->ESID;			break;		} else if (!def_id) {			def_id = esd->ESID;		}	}	/*remove all other media streams*/	i=0;	while ((esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {		if (esd->decoderConfig->streamType != stream_type) continue;		/*get base stream ID for this stream*/		es_id = esd->ESID;		if (esd->dependsOnESID && (esd->dependsOnESID != es_id)) {			es_id = esd->dependsOnESID;			while (es_id) {				GF_ESD *base = od_get_esd(odm->OD, es_id);				if (!base) break;				/*forbidden except for BIFS->OD*/				if (base->decoderConfig->streamType != stream_type) break;				if (!base->dependsOnESID) break;				es_id = base->dependsOnESID;			}		}		/*not part of same object as base, remove*/		if (es_id != def_id) {			gf_list_del_item(odm->OD->ESDescriptors, esd);			gf_odf_desc_del((GF_Descriptor*) esd);			i--;		}	}}/*Validate the streams in this OD, and check if we have to setup an inline scene*/GF_Err ODM_ValidateOD(GF_ObjectManager *odm, Bool *hasInline, Bool *externalClock){	u32 i;	u16 es_id;	GF_ESD *esd, *base_scene;	const char *sOpt;	u32 lang, nb_od, nb_ocr, nb_scene, nb_mp7, nb_ipmp, nb_oci, nb_mpj, nb_other, prev_st;	nb_od = nb_ocr = nb_scene = nb_mp7 = nb_ipmp = nb_oci = nb_mpj = nb_other = 0;	prev_st = 0;	*hasInline = 0;	*externalClock = 0;	/*step 1: validate OD*/	i=0;	while ((esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i))) {		/*check external clock refs*/		if (esd->OCRESID && (esd->OCRESID!=esd->ESID) && (od_get_esd(odm->OD, esd->OCRESID) == NULL) ) {			*externalClock = 1;		}		switch (esd->decoderConfig->streamType) {		case GF_STREAM_OD: nb_od++; break;		case GF_STREAM_OCR: nb_ocr++; break;		case GF_STREAM_SCENE: nb_scene++; break;		case GF_STREAM_MPEG7: nb_mp7++; break;		case GF_STREAM_IPMP: nb_ipmp++; break;		case GF_STREAM_OCI: nb_oci++; break;		case GF_STREAM_MPEGJ: nb_mpj++; break;		case GF_STREAM_PRIVATE_SCENE: nb_scene++; break;		/*all other streams shall not be mixed: text, video, audio, interaction, font*/		default: 			if (esd->decoderConfig->streamType!=prev_st) nb_other++;			prev_st = esd->decoderConfig->streamType;			break;		}	}	/*cf spec on stream aggregation*/	if (nb_other>1) return GF_ODF_INVALID_DESCRIPTOR;	/*no more than one base media type*/	if (nb_od && !nb_scene) return GF_ODF_INVALID_DESCRIPTOR; /*if OD we must have scene description*/	if (nb_other && nb_scene) return GF_ODF_INVALID_DESCRIPTOR; /*scene OR media*/	if (nb_ocr>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE OCR*/	if (nb_oci>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE OCI*/	if (nb_mp7>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE MPEG-7 - this is not in the spec, but since MPEG-7 = OCI++ this seems reasonable*/	if (nb_mpj>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE MPEG-J - this is not in the spec but well...*/	/*the rest should be OK*/	/*select independant streams - check language and (TODO) bitrate & term caps*/	sOpt = gf_cfg_get_key(odm->term->user->config, "Systems", "Language3CC");	if (!sOpt) {		gf_cfg_set_key(odm->term->user->config, "Systems", "Language3CC", "und");		sOpt = "und";	}	lang = (sOpt[0]<<16) | (sOpt[1]<<8) | sOpt[2];	if (gf_list_count(odm->OD->ESDescriptors)>1) {		ODM_SelectAlternateStream(odm, lang, GF_STREAM_SCENE);		ODM_SelectAlternateStream(odm, lang, GF_STREAM_OD);		ODM_SelectAlternateStream(odm, lang, GF_STREAM_VISUAL);		ODM_SelectAlternateStream(odm, lang, GF_STREAM_AUDIO);		ODM_SelectAlternateStream(odm, lang, GF_STREAM_IPMP);		ODM_SelectAlternateStream(odm, lang, GF_STREAM_INTERACT);		ODM_SelectAlternateStream(odm, lang, GF_STREAM_TEXT);	}		/*no scene, OK*/	if (!nb_scene) return GF_OK;	/*check if inline or animation stream*/	*hasInline = 1;	base_scene = NULL;	i=0;	while ( (esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {

⌨️ 快捷键说明

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