📄 scene_manager.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Scene Management 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/scene_manager.h>#include <gpac/constants.h>#include <gpac/media_tools.h>#include <gpac/bifs.h>#include <gpac/xml.h>#include <gpac/internal/scenegraph_dev.h>static Bool gf_node_in_table_by_tag(u32 tag, u32 NDTType){ if (!tag) return 0; if (tag==TAG_ProtoNode) return 1; else if (tag<=GF_NODE_RANGE_LAST_MPEG4) { u32 i; u32 gf_bifs_get_node_type(u32 NDT_Tag, u32 NodeTag, u32 Version); for (i=0;i<GF_BIFS_LAST_VERSION; i++) { if (gf_bifs_get_node_type(NDTType, tag, i+1)) return 1; } return 0; } else if (tag<=GF_NODE_RANGE_LAST_X3D) { Bool X3D_IsNodeInTable(u32 NDT_Tag, u32 NodeTag); return X3D_IsNodeInTable(NDTType, tag); } return 0;}Bool gf_node_in_table(GF_Node *node, u32 NDTType){ u32 tag = node ? node->sgprivate->tag : 0; if (tag==TAG_ProtoNode) { tag = gf_sg_proto_get_render_tag(((GF_ProtoInstance *)node)->proto_interface); if (tag==TAG_UndefinedNode) return 1; } return gf_node_in_table_by_tag(tag, NDTType);}GF_EXPORTGF_SceneManager *gf_sm_new(GF_SceneGraph *graph){ GF_SceneManager *tmp; if (!graph) return NULL; GF_SAFEALLOC(tmp, GF_SceneManager); tmp->streams = gf_list_new(); tmp->scene_graph = graph; return tmp;}GF_EXPORTGF_StreamContext *gf_sm_stream_new(GF_SceneManager *ctx, u16 ES_ID, u8 streamType, u8 objectType){ u32 i; GF_StreamContext *tmp; i=0; while ((tmp = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) { /*we MUST use the same ST*/ if (tmp->streamType!=streamType) continue; /*if no ESID/OTI specified this is a base layer (default stream created by parsers) if ESID/OTI specified this is a stream already setup */ if ( tmp->ESID==ES_ID ){ //tmp->objectType = objectType; return tmp; } } GF_SAFEALLOC(tmp, GF_StreamContext); tmp->AUs = gf_list_new(); tmp->ESID = ES_ID; tmp->streamType = streamType; tmp->objectType = objectType; tmp->timeScale = 1000; gf_list_add(ctx->streams, tmp); return tmp;}GF_StreamContext *gf_sm_stream_find(GF_SceneManager *ctx, u16 ES_ID){ u32 i, count; if (!ES_ID) return NULL; count = gf_list_count(ctx->streams); for (i=0; i<count; i++) { GF_StreamContext *tmp = (GF_StreamContext *)gf_list_get(ctx->streams, i); if (tmp->ESID==ES_ID) return tmp; } return NULL;}static void gf_sm_delete_stream(GF_StreamContext *sc){ while (gf_list_count(sc->AUs)) { GF_AUContext *au = (GF_AUContext *)gf_list_last(sc->AUs); gf_list_rem_last(sc->AUs); while (gf_list_count(au->commands)) { void *comptr = gf_list_last(au->commands); gf_list_rem_last(au->commands); switch (sc->streamType) { case GF_STREAM_OD: gf_odf_com_del((GF_ODCom**) & comptr); break; case GF_STREAM_SCENE: gf_sg_command_del((GF_Command *)comptr); break; } } gf_list_del(au->commands); free(au); } gf_list_del(sc->AUs); free(sc);}GF_EXPORTvoid gf_sm_stream_del(GF_SceneManager *ctx, GF_StreamContext *sc){ if (gf_list_del_item(ctx->streams, sc)>=0) { gf_sm_delete_stream(sc); }}GF_EXPORTvoid gf_sm_del(GF_SceneManager *ctx){ u32 count; while ( (count = gf_list_count(ctx->streams)) ) { GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, count-1); gf_list_rem(ctx->streams, count-1); gf_sm_delete_stream(sc); } gf_list_del(ctx->streams); if (ctx->root_od) gf_odf_desc_del((GF_Descriptor *) ctx->root_od); free(ctx);}GF_EXPORTGF_AUContext *gf_sm_stream_au_new(GF_StreamContext *stream, u64 timing, Double time_sec, Bool isRap){ u32 i; GF_AUContext *tmp; /*look for existing AU*/ i=0; while ((tmp = (GF_AUContext *)gf_list_enum(stream->AUs, &i))) { if (timing && (tmp->timing==timing)) return tmp; else if (time_sec && (tmp->timing_sec == time_sec)) return tmp; else if (!time_sec && !timing && !tmp->timing && !tmp->timing_sec) return tmp; /*insert AU*/ else if ((time_sec && time_sec<tmp->timing_sec) || (timing && timing<tmp->timing)) { tmp = (GF_AUContext *)malloc(sizeof(GF_AUContext)); tmp->commands = gf_list_new(); tmp->is_rap = isRap; tmp->timing = timing; tmp->timing_sec = time_sec; tmp->owner = stream; gf_list_insert(stream->AUs, tmp, i); return tmp; } } tmp = (GF_AUContext *)malloc(sizeof(GF_AUContext)); tmp->commands = gf_list_new(); tmp->is_rap = isRap; tmp->timing = timing; tmp->timing_sec = time_sec; tmp->owner = stream; gf_list_add(stream->AUs, tmp); return tmp;}GF_EXPORTGF_Err gf_sm_make_random_access(GF_SceneManager *ctx){ GF_Err e; u32 i, j, stream_count, au_count, com_count; GF_AUContext *au; GF_Command *com; e = GF_OK; stream_count = gf_list_count(ctx->streams); for (i=0; i<stream_count; i++) { GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i); /*FIXME - do this as well for ODs*/ if (sc->streamType == GF_STREAM_SCENE) { /*apply all commands - this will also apply the SceneReplace*/ j=0; while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { e = gf_sg_command_apply_list(ctx->scene_graph, au->commands, 0); if (e) return e; } /* Delete all the commands in the stream */ while ( (au_count = gf_list_count(sc->AUs)) ) { au = (GF_AUContext *)gf_list_get(sc->AUs, au_count-1); gf_list_rem(sc->AUs, au_count-1); while ( (com_count = gf_list_count(au->commands)) ) { com = (GF_Command*)gf_list_get(au->commands, com_count - 1); gf_list_rem(au->commands, com_count - 1); gf_sg_command_del(com); } gf_list_del(au->commands); free(au); } /*and recreate scene replace*/ au = gf_sm_stream_au_new(sc, 0, 0, 1); com = gf_sg_command_new(ctx->scene_graph, GF_SG_SCENE_REPLACE); com->node = ctx->scene_graph->RootNode; ctx->scene_graph->RootNode = NULL; gf_list_del(com->new_proto_list); com->new_proto_list = ctx->scene_graph->protos; ctx->scene_graph->protos = NULL; /*FIXME - check routes & protos*/ gf_list_add(au->commands, com); } } return e;}GF_Err gf_sm_load_init_BT(GF_SceneLoader *load);void gf_sm_load_done_BT(GF_SceneLoader *load);GF_Err gf_sm_load_run_BT(GF_SceneLoader *load);GF_Err gf_sm_load_init_BTString(GF_SceneLoader *load, char *str);GF_Err gf_sm_load_done_BTString(GF_SceneLoader *load);GF_Err gf_sm_load_init_xmt(GF_SceneLoader *load);void gf_sm_load_done_xmt(GF_SceneLoader *load);GF_Err gf_sm_load_run_xmt(GF_SceneLoader *load);GF_Err gf_sm_load_init_xmt_string(GF_SceneLoader *load, char *str);GF_Err gf_sm_load_init_MP4(GF_SceneLoader *load);void gf_sm_load_done_MP4(GF_SceneLoader *load);GF_Err gf_sm_load_run_MP4(GF_SceneLoader *load);#ifndef GPAC_DISABLE_SVG#ifdef GPAC_ENABLE_SVG_SAGF_Err gf_sm_load_init_svg_sa(GF_SceneLoader *load);GF_Err gf_sm_load_done_svg_sa(GF_SceneLoader *load);GF_Err gf_sm_load_run_svg_sa(GF_SceneLoader *load);GF_Err gf_sm_load_init_svg_sa_string(GF_SceneLoader *load, char *str);#endif#ifdef GPAC_ENABLE_SVG_SANIGF_Err gf_sm_load_init_svg_sani(GF_SceneLoader *load);GF_Err gf_sm_load_done_svg_sani(GF_SceneLoader *load);GF_Err gf_sm_load_run_svg_sani(GF_SceneLoader *load);GF_Err gf_sm_load_init_svg_sani_string(GF_SceneLoader *load, char *str);#endifGF_Err gf_sm_load_init_svg(GF_SceneLoader *load);GF_Err gf_sm_load_done_svg(GF_SceneLoader *load);GF_Err gf_sm_load_run_svg(GF_SceneLoader *load);GF_Err gf_sm_load_init_svg_string(GF_SceneLoader *load, char *str);#endif#ifndef GPAC_READ_ONLYGF_Err gf_sm_load_init_SWF(GF_SceneLoader *load);void gf_sm_load_done_SWF(GF_SceneLoader *load);GF_Err gf_sm_load_run_SWF(GF_SceneLoader *load);GF_Err gf_sm_load_init_QT(GF_SceneLoader *load);void gf_sm_load_done_QT(GF_SceneLoader *load);GF_Err gf_sm_load_run_QT(GF_SceneLoader *load);#endifstatic GF_Err gf_sm_load_init_from_string(GF_SceneLoader *load, char *str){ /*we need at least a scene graph*/ if (!load || (!load->ctx && !load->scene_graph)) return GF_BAD_PARAM; if (!load->type) return GF_NOT_SUPPORTED; if (!load->scene_graph) load->scene_graph = load->ctx->scene_graph; switch (load->type) { case GF_SM_LOAD_BT: case GF_SM_LOAD_VRML: case GF_SM_LOAD_X3DV: return gf_sm_load_init_BTString(load, str); case GF_SM_LOAD_XMTA: case GF_SM_LOAD_X3D: return gf_sm_load_init_xmt_string(load, str);#ifndef GPAC_DISABLE_SVG#ifdef GPAC_ENABLE_SVG_SA case GF_SM_LOAD_SVG_SA: return gf_sm_load_init_svg_sa_string(load, str);#endif#ifdef GPAC_ENABLE_SVG_SANI case GF_SM_LOAD_SVG_SANI: return gf_sm_load_init_svg_sani_string(load, str);#endif case GF_SM_LOAD_SVG_DA: case GF_SM_LOAD_XSR: return gf_sm_load_init_svg_string(load, str);#endif case GF_SM_LOAD_SWF: return GF_NOT_SUPPORTED;#ifndef GPAC_READ_ONLY case GF_SM_LOAD_MP4: return GF_NOT_SUPPORTED;#endif } return GF_NOT_SUPPORTED;}static void gf_sm_load_done_string(GF_SceneLoader *load, Bool do_clean){ switch (load->type) { case GF_SM_LOAD_BT: case GF_SM_LOAD_VRML: case GF_SM_LOAD_X3DV: gf_sm_load_done_BTString(load); break; case GF_SM_LOAD_XMTA: case GF_SM_LOAD_X3D: /*we do not reset it here to enable SAX parsing*/ if (do_clean) gf_sm_load_done_xmt(load); break;#ifndef GPAC_DISABLE_SVG /*we do not reset it here to enable SAX parsing*/ case GF_SM_LOAD_SVG_DA: case GF_SM_LOAD_XSR: break;#ifdef GPAC_ENABLE_SVG_SA case GF_SM_LOAD_SVG_SA: break;#endif#ifdef GPAC_ENABLE_SVG_SANI case GF_SM_LOAD_SVG_SANI: break;#endif#endif default: break; }}GF_EXPORTGF_Err gf_sm_load_string(GF_SceneLoader *load, char *str, Bool do_clean){ GF_Err e = gf_sm_load_init_from_string(load, str); if (e) return e; e = gf_sm_load_run(load); gf_sm_load_done_string(load, do_clean); return e;}/*initializes the context loader*/GF_EXPORTGF_Err gf_sm_load_init(GF_SceneLoader *load){ GF_Err e = GF_NOT_SUPPORTED; char *ext, szExt[50]; /*we need at least a scene graph*/ if (!load || (!load->ctx && !load->scene_graph) || (!load->fileName && !load->isom)) return GF_BAD_PARAM; if (!load->type) { if (load->isom) { load->type = GF_SM_LOAD_MP4; } else { ext = strrchr(load->fileName, '.'); if (!ext) return GF_NOT_SUPPORTED; if (!stricmp(ext, ".gz")) { char *anext; ext[0] = 0; anext = strrchr(load->fileName, '.'); ext[0] = '.'; ext = anext; } strcpy(szExt, &ext[1]); strlwr(szExt); if (strstr(szExt, "bt")) load->type = GF_SM_LOAD_BT; else if (strstr(szExt, "wrl")) load->type = GF_SM_LOAD_VRML; else if (strstr(szExt, "x3dv")) load->type = GF_SM_LOAD_X3DV; else if (strstr(szExt, "xmt") || strstr(szExt, "xmta")) load->type = GF_SM_LOAD_XMTA; else if (strstr(szExt, "x3d")) load->type = GF_SM_LOAD_X3D; else if (strstr(szExt, "swf")) load->type = GF_SM_LOAD_SWF; else if (strstr(szExt, "mov")) load->type = GF_SM_LOAD_QT; else if (strstr(szExt, "svg")) load->type = GF_SM_LOAD_SVG_DA; else if (strstr(szExt, "xsr")) load->type = GF_SM_LOAD_XSR; else if (strstr(szExt, "xml")) { char *rtype = gf_xml_get_root_type(load->fileName, &e); if (rtype) { if (!strcmp(rtype, "SAFSession")) load->type = GF_SM_LOAD_XSR; else if (!strcmp(rtype, "XMT-A")) load->type = GF_SM_LOAD_XMTA; else if (!strcmp(rtype, "X3D")) load->type = GF_SM_LOAD_X3D; free(rtype); } } } } if (!load->type) return e; if (!load->scene_graph) load->scene_graph = load->ctx->scene_graph; switch (load->type) { case GF_SM_LOAD_BT: case GF_SM_LOAD_VRML: case GF_SM_LOAD_X3DV: return gf_sm_load_init_BT(load); case GF_SM_LOAD_XMTA: case GF_SM_LOAD_X3D: return gf_sm_load_init_xmt(load);#ifndef GPAC_DISABLE_SVG#ifdef GPAC_ENABLE_SVG_SA case GF_SM_LOAD_SVG_SA: return gf_sm_load_init_svg_sa(load);#endif#ifdef GPAC_ENABLE_SVG_SANI case GF_SM_LOAD_SVG_SANI: return gf_sm_load_init_svg_sani(load);#endif case GF_SM_LOAD_SVG_DA: case GF_SM_LOAD_XSR: return gf_sm_load_init_svg(load);#endif#ifndef GPAC_READ_ONLY case GF_SM_LOAD_SWF: return gf_sm_load_init_SWF(load); case GF_SM_LOAD_QT: return gf_sm_load_init_QT(load); case GF_SM_LOAD_MP4: return gf_sm_load_init_MP4(load);#endif } return GF_NOT_SUPPORTED;}GF_EXPORTvoid gf_sm_load_done(GF_SceneLoader *load){ switch (load->type) { case GF_SM_LOAD_BT: case GF_SM_LOAD_VRML: case GF_SM_LOAD_X3DV: gf_sm_load_done_BT(load); break; case GF_SM_LOAD_XMTA: case GF_SM_LOAD_X3D: gf_sm_load_done_xmt(load); break;#ifndef GPAC_DISABLE_SVG#ifdef GPAC_ENABLE_SVG_SA case GF_SM_LOAD_SVG_SA: gf_sm_load_done_svg_sa(load); break;#endif#ifdef GPAC_ENABLE_SVG_SANI case GF_SM_LOAD_SVG_SANI: gf_sm_load_done_svg_sani(load); break;#endif case GF_SM_LOAD_XSR: case GF_SM_LOAD_SVG_DA: gf_sm_load_done_svg(load); break;#endif#ifndef GPAC_READ_ONLY case GF_SM_LOAD_SWF: gf_sm_load_done_SWF(load); break; case GF_SM_LOAD_QT: gf_sm_load_done_QT(load); break; case GF_SM_LOAD_MP4: gf_sm_load_done_MP4(load); break;#endif }}GF_EXPORTGF_Err gf_sm_load_run(GF_SceneLoader *load){ switch (load->type) { case GF_SM_LOAD_BT: case GF_SM_LOAD_VRML: case GF_SM_LOAD_X3DV: return gf_sm_load_run_BT(load); case GF_SM_LOAD_XMTA: case GF_SM_LOAD_X3D: return gf_sm_load_run_xmt(load);#ifndef GPAC_DISABLE_SVG#ifdef GPAC_ENABLE_SVG_SA case GF_SM_LOAD_SVG_SA: return gf_sm_load_run_svg_sa(load);#endif#ifdef GPAC_ENABLE_SVG_SANI case GF_SM_LOAD_SVG_SANI: return gf_sm_load_run_svg_sani(load);#endif case GF_SM_LOAD_XSR: case GF_SM_LOAD_SVG_DA: return gf_sm_load_run_svg(load);#endif#ifndef GPAC_READ_ONLY case GF_SM_LOAD_SWF: return gf_sm_load_run_SWF(load); case GF_SM_LOAD_QT: return gf_sm_load_run_QT(load); case GF_SM_LOAD_MP4: return gf_sm_load_run_MP4(load);#endif default: return GF_BAD_PARAM; }}#ifdef DANAEvoid *DANAE_NewSceneLoader(char *filename, void *scene_graph){ GF_SceneLoader *scene_loader; GF_SAFEALLOC(scene_loader, GF_SceneLoader); scene_loader->fileName = filename; scene_loader->scene_graph = scene_graph; scene_loader->flags = GF_SM_LOAD_FOR_PLAYBACK; if (gf_sm_load_init(scene_loader) != GF_OK) { free(scene_loader); return NULL; } return scene_loader;}void DANAE_SceneLoader_Parse(void *p){ gf_sm_load_run(p);}void DANAE_SceneLoader_Terminate(void *p){ gf_sm_load_done(p); free(p);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -