void V4SceneManager::SaveFile(const char *path) { GF_SMEncodeOptions opts; char rad_name[5000]; /* First dump the scene in a BT file */ strcpy(rad_name, "dump"); m_pSm->scene_graph->RootNode = NULL; gf_sm_dump(m_pSm, rad_name, 0); /* Then reload properly (overriding the current SceneManager)*/ GF_SceneLoader load; memset(&load, 0, sizeof(GF_SceneLoader)); load.fileName = "dump.bt"; load.ctx = m_pSm; gf_sm_load_init(&load); gf_sm_load_run(&load); gf_sm_load_done(&load); /* Finally encode the file */ GF_ISOFile *mp4 = gf_isom_open(path, GF_ISOM_WRITE_EDIT, NULL); m_pSm->max_node_id = gf_sg_get_max_node_id(m_pSm->scene_graph); memset(&opts, 0, sizeof(opts)); opts.flags = GF_SM_LOAD_MPEG4_STRICT; gf_sm_encode_to_file(m_pSm, mp4, &opts); gf_isom_set_brand_info(mp4, GF_ISOM_BRAND_MP42, 1); gf_isom_modify_alternate_brand(mp4, GF_ISOM_BRAND_ISOM, 1); gf_isom_close(mp4); }
GF_EXPORT GF_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; }
GF_EXPORT GF_Err gf_seng_encode_from_file(GF_SceneEngine *seng, u16 ESID, Bool disable_aggregation, char *auFile, gf_seng_callback callback) { GF_Err e; GF_StreamContext *sc; u32 i; Bool dims = 0; seng->loader.fileName = auFile; seng->loader.ctx = seng->ctx; seng->loader.force_es_id = ESID; sc = NULL; i=0; while ((sc = (GF_StreamContext*)gf_list_enum(seng->ctx->streams, &i))) { sc->current_au_count = gf_list_count(sc->AUs); sc->disable_aggregation = disable_aggregation; } /* We need to create an empty AU for the parser to correctly parse a LASeR Command without SceneUnit */ sc = gf_list_get(seng->ctx->streams, 0); if (sc->objectType == GPAC_OTI_SCENE_DIMS) { dims = 1; gf_seng_create_new_au(sc, 0); } seng->loader.flags |= GF_SM_LOAD_CONTEXT_READY; if (dims) { seng->loader.type |= GF_SM_LOAD_DIMS; } else { seng->loader.flags |= GF_SM_LOAD_MPEG4_STRICT; } e = gf_sm_load_run(&seng->loader); if (e<0) { GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[SceneEngine] cannot load AU File %s (error %s)\n", auFile, gf_error_to_string(e))); goto exit; } i = 0; while ((sc = (GF_StreamContext*)gf_list_enum(seng->ctx->streams, &i))) { sc->disable_aggregation = 0; } e = gf_sm_live_encode_scene_au(seng, callback, 0); if (e) goto exit; exit: return e; }
void V4SceneManager::LoadFile(const char *path) { LoadCommon(); GF_Terminal *term = m_gpac_panel->GetMPEG4Terminal(); /* Loading of a file (BT, MP4 ...) and modification of the SceneManager */ GF_SceneLoader load; memset(&load, 0, sizeof(GF_SceneLoader)); load.fileName = path; load.ctx = m_pSm; if (strstr(path, ".mp4") || strstr(path, ".MP4") ) load.isom = gf_isom_open(path, GF_ISOM_OPEN_READ, NULL); gf_sm_load_init(&load); gf_sm_load_run(&load); gf_sm_load_done(&load); if (load.isom) gf_isom_delete(load.isom); /* SceneManager should be initialized and filled correctly */ gf_sg_set_scene_size_info(m_pIs->graph, m_pSm->scene_width, m_pSm->scene_height, m_pSm->is_pixel_metrics); // TODO : replace with GetBifsStream GF_StreamContext *sc = (GF_StreamContext *) gf_list_get(m_pSm->streams,0); if (sc->streamType == 3) { GF_AUContext *au = (GF_AUContext *) gf_list_get(sc->AUs,0); GF_Command *c = (GF_Command *) gf_list_get(au->commands,0); //gf_sg_command_apply(m_pIs->graph, c, 0); /* This is a patch to solve the save pb: When ApplyCommand is made on a Scene Replace Command The command node is set to NULL When we save a BIFS stream whose first command is of this kind, the file saver thinks the bifs commands should come from an NHNT file This is a temporary patch */ if (c->tag == GF_SG_SCENE_REPLACE) { c->node = m_pIs->graph->RootNode; } } gf_sc_set_scene(term->compositor, m_pIs->graph); m_pIs->graph_attached = 1; // TODO : read actual values from file SetLength(50); SetFrameRate(25); // retrieves all the node from the tree and adds them to the node pool GF_Node * root = gf_sg_get_root_node(m_pIs->graph); // CreateDictionnary(); }
GF_Err decode_svg(GF_LoadCompare *lc, char *item_name, char *item_path, char *svg_out_path) { GF_SceneManager *ctx; GF_SceneGraph *sg; GF_SceneLoader load; GF_ISOFile *mp4; GF_Err e = GF_OK; char mp4_path[256]; char *ext; strcpy(mp4_path, item_name); ext = strrchr(mp4_path, '.'); strcpy(ext, ".mp4"); mp4 = gf_isom_open(mp4_path, GF_ISOM_OPEN_READ, NULL); if (!mp4) { if (lc->verbose) fprintf(stdout, "Could not open file %s\n", mp4_path); e = GF_IO_ERR; } else { sg = gf_sg_new(); ctx = gf_sm_new(sg); memset(&load, 0, sizeof(GF_SceneLoader)); load.isom = mp4; load.ctx = ctx; e = gf_sm_load_init(&load); if (e) { fprintf(stderr, "Error loading MP4 file\n"); } else { e = gf_sm_load_run(&load); if (e) { fprintf(stderr, "Error loading MP4 file\n"); } else { gf_sm_load_done(&load); ext = strrchr(svg_out_path, '.'); ext[0] = 0; e = gf_sm_dump(ctx, svg_out_path, GF_SM_DUMP_SVG); if (e) { fprintf(stderr, "Error dumping SVG from MP4 file\n"); } } } gf_sm_del(ctx); gf_sg_del(sg); gf_isom_close(mp4); } return e; }
GF_EXPORT GF_SceneEngine *gf_seng_init(void *calling_object, char * inputContext, u32 load_type, char *dump_path, Bool embed_resources) { GF_SceneEngine *seng; GF_Err e = GF_OK; if (!inputContext) return NULL; GF_SAFEALLOC(seng, GF_SceneEngine) if (!seng) return NULL; seng->calling_object = calling_object; /*Step 1: create context and load input*/ seng->sg = gf_sg_new(); gf_sg_set_node_callback(seng->sg, gf_seng_on_node_modified); gf_sg_set_private(seng->sg, seng); seng->dump_path = dump_path; seng->ctx = gf_sm_new(seng->sg); seng->owns_context = 1; memset(&(seng->loader), 0, sizeof(GF_SceneLoader)); seng->loader.ctx = seng->ctx; seng->loader.type = load_type; /*since we're encoding in BIFS we must get MPEG-4 nodes only*/ seng->loader.flags = GF_SM_LOAD_MPEG4_STRICT; if (embed_resources) seng->loader.flags |= GF_SM_LOAD_EMBEDS_RES; seng->loader.fileName = inputContext; e = gf_sm_load_init(&(seng->loader)); if (!e) e = gf_sm_load_run(&(seng->loader)); if (e<0) { GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[SceneEngine] Cannot load context from %s (error %s)\n", inputContext, gf_error_to_string(e))); goto exit; } e = gf_sm_live_setup(seng); if (e!=GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[SceneEngine] cannot init scene encoder for context (error %s)\n", gf_error_to_string(e))); goto exit; } return seng; exit: gf_seng_terminate(seng); return NULL; }
GF_EXPORT GF_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_Err gpacctx_load_file(GF_LoadCompare *lc, char *item_path, u32 *loadtime) { GF_Err e = GF_OK; GF_SceneLoader load; GF_SceneGraph *sg; u32 i, starttime, endtime; u32 nb; if (lc->spread_repeat) nb = 1; else nb = lc->nbloads ; *loadtime = 0; for (i = 0; i<nb; i++) { memset(&load, 0, sizeof(GF_SceneLoader)); sg = gf_sg_new(); load.ctx = gf_sm_new(sg); load.OnProgress = load_progress; load.fileName = item_path; starttime = gf_sys_clock(); e = gf_sm_load_init(&load); if (e) { fprintf(stderr, "Error loading file %s\n", item_path); } else { e = gf_sm_load_run(&load); if (e) { fprintf(stderr, "Error loading file %s\n", item_path); } else { endtime = gf_sys_clock(); *loadtime += endtime-starttime; } gf_sm_load_done(&load); } gf_sm_del(load.ctx); gf_sg_del(sg); } return e; }
GF_EXPORT GF_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_Err load_mp4(GF_LoadCompare *lc, GF_ISOFile *mp4, u32 *loadtime) { GF_Err e = GF_OK; GF_SceneLoader load; GF_SceneGraph *sg; u32 i, starttime, endtime; u32 nb; if (lc->spread_repeat) nb = 1; else nb = lc->nbloads ; *loadtime = 0; for (i = 0; i< nb; i++) { memset(&load, 0, sizeof(GF_SceneLoader)); sg = gf_sg_new(); load.ctx = gf_sm_new(sg); load.isom = mp4; starttime = gf_sys_clock(); e = gf_sm_load_init(&load); if (e) { fprintf(stderr, "Error loading MP4 file\n"); } else { e = gf_sm_load_run(&load); if (e) { fprintf(stderr, "Error loading MP4 file\n"); } else { endtime = gf_sys_clock(); *loadtime += endtime-starttime; } gf_sm_load_done(&load); } gf_sm_del(load.ctx); gf_sg_del(sg); } return e; }
void V4SceneGraph::LoadFile(const char *path) { GF_SceneLoader load; if (m_pSm) { gf_sr_set_scene(m_pSr, NULL); gf_sm_del(m_pSm); gf_sg_del(m_pSg); } // initializes a new scene // We need an GF_InlineScene, a SceneManager and an GF_ObjectManager m_pIs = gf_is_new(NULL); m_pSg = m_pIs->graph; m_pSm = gf_sm_new(m_pSg); m_pIs->root_od = gf_odm_new(); m_pIs->root_od->parentscene = NULL; m_pIs->root_od->subscene = m_pIs; m_pIs->root_od->term = m_term; m_term->root_scene = m_pIs; // TODO : what's the use of this ? if (m_pOriginal_mp4) gf_free(m_pOriginal_mp4); m_pOriginal_mp4 = NULL; /* Loading of a file (BT, MP4 ...) and modification of the SceneManager */ memset(&load, 0, sizeof(GF_SceneLoader)); load.fileName = path; load.ctx = m_pSm; load.cbk = this; if (strstr(path, ".mp4") || strstr(path, ".MP4") ) load.isom = gf_isom_open(path, GF_ISOM_OPEN_READ, NULL); gf_sm_load_init(&load); gf_sm_load_run(&load); gf_sm_load_done(&load); if (load.isom) gf_isom_delete(load.isom); /* SceneManager should be initialized and filled correctly */ gf_sg_set_scene_size_info(m_pSg, m_pSm->scene_width, m_pSm->scene_height, m_pSm->is_pixel_metrics); // TODO : replace with GetBifsStream GF_StreamContext *sc = (GF_StreamContext *) gf_list_get(m_pSm->streams,0); if (sc->streamType == 3) { GF_AUContext *au = (GF_AUContext *) gf_list_get(sc->AUs,0); GF_Command *c = (GF_Command *) gf_list_get(au->commands,0); gf_sg_command_apply(m_pSg, c, 0); /* This is a patch to solve the save pb: When ApplyCommand is made on a Scene Replace Command The command node is set to NULL When we save a BIFS stream whose first command is of this kind, the file saver thinks the bifs commands should come from an NHNT file This is a temporary patch */ if (c->tag == GF_SG_SCENE_REPLACE) { c->node = m_pSg->RootNode; } } gf_sr_set_scene(m_pSr, m_pSg); // retrieves all the node from the tree and adds them to the node pool GF_Node * root = gf_sg_get_root_node(m_pSg); CreateDictionnary(); }
static GF_Err SVG_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 stream_time, u32 mmlevel) { GF_Err e = GF_OK; SVGIn *svgin = (SVGIn *)plug->privateStack; if (stream_time==(u32)-1) { if (svgin->src) gzclose(svgin->src); svgin->src = NULL; gf_sm_load_done(&svgin->loader); svgin->loader.fileName = NULL; svgin->file_pos = 0; gf_sg_reset(svgin->scene->graph); return GF_OK; } switch (svgin->oti) { /*!OTI for SVG dummy stream (dsi = file name) - GPAC internal*/ case GPAC_OTI_PRIVATE_SCENE_SVG: /*full doc parsing*/ if ((svgin->sax_max_duration==(u32) -1) && svgin->file_size) { /*init step*/ if (!svgin->loader.fileName) { /*not done yet*/ if (!svg_check_download(svgin)) return GF_OK; svgin->loader.fileName = svgin->file_name; e = gf_sm_load_init(&svgin->loader); } else { e = gf_sm_load_run(&svgin->loader); } } /*chunk parsing*/ else { u32 entry_time; char file_buf[SVG_PROGRESSIVE_BUFFER_SIZE+2]; /*initial load*/ if (!svgin->src && !svgin->file_pos) { svgin->src = gzopen(svgin->file_name, "rb"); if (!svgin->src) return GF_URL_ERROR; svgin->loader.fileName = svgin->file_name; gf_sm_load_init(&svgin->loader); } e = GF_OK; entry_time = gf_sys_clock(); while (1) { u32 diff; s32 nb_read; nb_read = gzread(svgin->src, file_buf, SVG_PROGRESSIVE_BUFFER_SIZE); /*we may have read nothing but we still need to call parse in case the parser got suspended*/ if (nb_read<=0) { nb_read = 0; if ((e==GF_EOS) && gzeof(svgin->src)) { gf_set_progress("SVG Parsing", svgin->file_pos, svgin->file_size); gzclose(svgin->src); svgin->src = NULL; gf_sm_load_done(&svgin->loader); } goto exit; } file_buf[nb_read] = file_buf[nb_read+1] = 0; e = gf_sm_load_string(&svgin->loader, file_buf, 0); svgin->file_pos += nb_read; /*handle decompression*/ if (svgin->file_pos > svgin->file_size) svgin->file_size = svgin->file_pos + 1; if (e) break; gf_set_progress("SVG Parsing", svgin->file_pos, svgin->file_size); diff = gf_sys_clock() - entry_time; if (diff > svgin->sax_max_duration) { break; } } } break; /*!OTI for streaming SVG - GPAC internal*/ case GPAC_OTI_SCENE_SVG: e = gf_sm_load_string(&svgin->loader, inBuffer, 0); break; /*!OTI for streaming SVG + gz - GPAC internal*/ case GPAC_OTI_SCENE_SVG_GZ: e = svgin_deflate(svgin, inBuffer, inBufferLength); break; /*!OTI for DIMS (dsi = 3GPP DIMS configuration) - GPAC internal*/ case GPAC_OTI_SCENE_DIMS: { u8 prev, dims_hdr; u32 nb_bytes, size; u64 pos; char * buf2 = gf_malloc(inBufferLength); GF_BitStream *bs = gf_bs_new(inBuffer, inBufferLength, GF_BITSTREAM_READ); memcpy(buf2, inBuffer, inBufferLength); // FILE *f = gf_f64_open("dump.svg", "wb"); // while (gf_bs_available(bs)) { pos = gf_bs_get_position(bs); size = gf_bs_read_u16(bs); nb_bytes = 2; /*GPAC internal hack*/ if (!size) { size = gf_bs_read_u32(bs); nb_bytes = 6; } // gf_fwrite( inBuffer + pos + nb_bytes + 1, 1, size - 1, f ); dims_hdr = gf_bs_read_u8(bs); prev = buf2[pos + nb_bytes + size]; buf2[pos + nb_bytes + size] = 0; if (dims_hdr & GF_DIMS_UNIT_C) { e = svgin_deflate(svgin, buf2 + pos + nb_bytes + 1, size - 1); } else { e = gf_sm_load_string(&svgin->loader, buf2 + pos + nb_bytes + 1, 0); } buf2[pos + nb_bytes + size] = prev; gf_bs_skip_bytes(bs, size-1); } // fclose(f); gf_bs_del(bs); } break; default: return GF_BAD_PARAM; } exit: if ((e>=GF_OK) && (svgin->scene->graph_attached!=1) && (gf_sg_get_root_node(svgin->loader.scene_graph)!=NULL) ) { gf_scene_attach_to_compositor(svgin->scene); } /*prepare for next playback*/ if (e) { gf_sm_load_done(&svgin->loader); svgin->loader.fileName = NULL; e = GF_EOS; } return e; }
static GF_Err CTXLoad_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 stream_time, u32 mmlevel) { GF_Err e = GF_OK; u32 i, j, k, nb_updates, last_rap=0; GF_AUContext *au; Bool can_delete_com; GF_StreamContext *sc; CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack; /*something failed*/ if (priv->load_flags==3) return GF_EOS; /*this signals main scene deconnection, destroy the context if needed*/ assert(ES_ID); if (!priv->ctx) { e = CTXLoad_Setup((GF_BaseDecoder *)plug); if (e) return e; } if (stream_time==(u32)-1) { /*seek on root stream: destroy the context manager and reload it. We cannot seek on the main stream because commands may have changed node attributes/children and we d'ont track the initial value*/ if (priv->load_flags && (priv->base_stream_id == ES_ID)) { if (priv->src) gf_fclose(priv->src); priv->src = NULL; gf_sm_load_done(&priv->load); priv->file_pos = 0; /*queue scene for detach*/ gf_term_lock_media_queue(priv->scene->root_od->term, GF_TRUE); priv->scene->root_od->action_type = GF_ODM_ACTION_SCENE_RECONNECT; gf_list_add(priv->scene->root_od->term->media_queue, priv->scene->root_od); gf_term_lock_media_queue(priv->scene->root_od->term, GF_FALSE); return CTXLoad_Setup((GF_BaseDecoder *)plug); } i=0; while ((sc = (GF_StreamContext *)gf_list_enum(priv->ctx->streams, &i))) { /*not our stream*/ if (!sc->in_root_od && (sc->ESID != ES_ID)) continue; /*not the base stream*/ if (sc->in_root_od && (priv->base_stream_id != ES_ID)) continue; /*handle SWF media extraction*/ if ((sc->streamType == GF_STREAM_OD) && (priv->load_flags==1)) continue; sc->last_au_time = 0; } return GF_OK; } if (priv->load_flags != 2) { if (priv->progressive_support) { u32 entry_time; char file_buf[4096+1]; if (!priv->src) { priv->src = gf_fopen(priv->file_name, "rb"); if (!priv->src) return GF_URL_ERROR; priv->file_pos = 0; } priv->load.type = GF_SM_LOAD_XMTA; e = GF_OK; entry_time = gf_sys_clock(); gf_fseek(priv->src, priv->file_pos, SEEK_SET); while (1) { u32 diff; s32 nb_read = (s32) fread(file_buf, 1, 4096, priv->src); if (nb_read<0) { return GF_IO_ERR; } file_buf[nb_read] = 0; if (!nb_read) { if (priv->file_pos==priv->file_size) { gf_fclose(priv->src); priv->src = NULL; priv->load_flags = 2; gf_sm_load_done(&priv->load); break; } break; } e = gf_sm_load_string(&priv->load, file_buf, GF_FALSE); priv->file_pos += nb_read; if (e) break; diff = gf_sys_clock() - entry_time; if (diff > priv->sax_max_duration) break; } if (!priv->scene->graph_attached) { gf_sg_set_scene_size_info(priv->scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics); gf_scene_attach_to_compositor(priv->scene); CTXLoad_CheckStreams(priv); } } /*load first frame only*/ else if (!priv->load_flags) { /*we need the whole file*/ if (!CTXLoad_CheckDownload(priv)) return GF_OK; priv->load_flags = 1; e = gf_sm_load_init(&priv->load); if (!e) { CTXLoad_CheckStreams(priv); gf_sg_set_scene_size_info(priv->scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics); /*VRML, override base clock*/ if ((priv->load.type==GF_SM_LOAD_VRML) || (priv->load.type==GF_SM_LOAD_X3DV) || (priv->load.type==GF_SM_LOAD_X3D)) { /*override clock callback*/ gf_sg_set_scene_time_callback(priv->scene->graph, CTXLoad_GetVRMLTime); } } } /*load the rest*/ else { priv->load_flags = 2; e = gf_sm_load_run(&priv->load); gf_sm_load_done(&priv->load); /*in case this was not set in the first pass (XMT)*/ gf_sg_set_scene_size_info(priv->scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics); } if (e<0) { gf_sm_load_done(&priv->load); gf_sm_del(priv->ctx); priv->ctx = NULL; priv->load_flags = 3; return e; } /*and figure out duration of root scene, and take care of XMT timing*/ if (priv->load_flags==2) { CTXLoad_CheckStreams(priv); if (!gf_list_count(priv->ctx->streams)) { gf_scene_attach_to_compositor(priv->scene); } } } nb_updates = 0; i=0; while ((sc = (GF_StreamContext *)gf_list_enum(priv->ctx->streams, &i))) { /*not our stream*/ if (!sc->in_root_od && (sc->ESID != ES_ID)) continue; /*not the base stream*/ if (sc->in_root_od && (priv->base_stream_id != ES_ID)) continue; /*handle SWF media extraction*/ if ((sc->streamType == GF_STREAM_OD) && (priv->load_flags==1)) continue; /*check for seek*/ if (sc->last_au_time > 1 + stream_time) { sc->last_au_time = 0; } can_delete_com = GF_FALSE; if (sc->in_root_od && (priv->load_flags==2)) can_delete_com = GF_TRUE; /*we're in the right stream, apply update*/ j=0; /*seek*/ if (!sc->last_au_time) { while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { u32 au_time = (u32) (au->timing*1000/sc->timeScale); if (au_time > stream_time) break; if (au->flags & GF_SM_AU_RAP) last_rap = j-1; } j = last_rap; } while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { u32 au_time = (u32) (au->timing*1000/sc->timeScale); if (au_time + 1 <= sc->last_au_time) { /*remove first replace command*/ if (can_delete_com && (sc->streamType==GF_STREAM_SCENE)) { while (gf_list_count(au->commands)) { GF_Command *com = (GF_Command *)gf_list_get(au->commands, 0); gf_list_rem(au->commands, 0); gf_sg_command_del(com); } j--; gf_list_rem(sc->AUs, j); gf_list_del(au->commands); gf_free(au); } continue; } if (au_time > stream_time) { nb_updates++; break; } if (sc->streamType == GF_STREAM_SCENE) { GF_Command *com; /*apply the commands*/ k=0; while ((com = (GF_Command *)gf_list_enum(au->commands, &k))) { e = gf_sg_command_apply(priv->scene->graph, com, 0); if (e) break; /*remove commands on base layer*/ if (can_delete_com) { k--; gf_list_rem(au->commands, k); gf_sg_command_del(com); } } } else if (sc->streamType == GF_STREAM_OD) { /*apply the commands*/ while (gf_list_count(au->commands)) { Bool keep_com = GF_FALSE; GF_ODCom *com = (GF_ODCom *)gf_list_get(au->commands, 0); gf_list_rem(au->commands, 0); switch (com->tag) { case GF_ODF_OD_UPDATE_TAG: { GF_ODUpdate *odU = (GF_ODUpdate *)com; while (gf_list_count(odU->objectDescriptors)) { GF_ESD *esd; char *remote; GF_MuxInfo *mux = NULL; GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, 0); gf_list_rem(odU->objectDescriptors, 0); /*we can only work with single-stream ods*/ esd = (GF_ESD*)gf_list_get(od->ESDescriptors, 0); if (!esd) { if (od->URLString) { ODS_SetupOD(priv->scene, od); } else { gf_odf_desc_del((GF_Descriptor *) od); } continue; } /*fix OCR dependencies*/ if (CTXLoad_StreamInRootOD(priv->ctx->root_od, esd->OCRESID)) esd->OCRESID = priv->base_stream_id; /*forbidden if ESD*/ if (od->URLString) { gf_odf_desc_del((GF_Descriptor *) od); continue; } /*look for MUX info*/ k=0; while ((mux = (GF_MuxInfo*)gf_list_enum(esd->extensionDescriptors, &k))) { if (mux->tag == GF_ODF_MUXINFO_TAG) break; mux = NULL; } /*we need a mux if not animation stream*/ if (!mux || !mux->file_name) { /*only animation streams are handled*/ if (!esd->decoderConfig) { gf_odf_desc_del((GF_Descriptor *) od); } else if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { /*set ST to private scene to get sure the stream will be redirected to us*/ esd->decoderConfig->streamType = GF_STREAM_PRIVATE_SCENE; esd->dependsOnESID = priv->base_stream_id; ODS_SetupOD(priv->scene, od); } else if (esd->decoderConfig->streamType==GF_STREAM_INTERACT) { GF_UIConfig *cfg = (GF_UIConfig *) esd->decoderConfig->decoderSpecificInfo; gf_odf_encode_ui_config(cfg, &esd->decoderConfig->decoderSpecificInfo); gf_odf_desc_del((GF_Descriptor *) cfg); ODS_SetupOD(priv->scene, od); } else { gf_odf_desc_del((GF_Descriptor *) od); } continue; } //solve url before import if (mux->src_url) { char *res_url = gf_url_concatenate(mux->src_url, mux->file_name); if (res_url) { gf_free(mux->file_name); mux->file_name = res_url; } gf_free(mux->src_url); mux->src_url = NULL; } /*text import*/ if (mux->textNode) { #ifdef GPAC_DISABLE_MEDIA_IMPORT gf_odf_desc_del((GF_Descriptor *) od); continue; #else e = gf_sm_import_bifs_subtitle(priv->ctx, esd, mux); if (e) { e = GF_OK; gf_odf_desc_del((GF_Descriptor *) od); continue; } /*set ST to private scene and dependency to base to get sure the stream will be redirected to us*/ esd->decoderConfig->streamType = GF_STREAM_PRIVATE_SCENE; esd->dependsOnESID = priv->base_stream_id; ODS_SetupOD(priv->scene, od); continue; #endif } /*soundstreams are a bit of a pain, they may be declared before any data gets written*/ if (mux->delete_file) { FILE *t = gf_fopen(mux->file_name, "rb"); if (!t) { keep_com = GF_TRUE; gf_list_insert(odU->objectDescriptors, od, 0); break; } gf_fclose(t); } /*remap to remote URL - warning, the URL has already been resolved according to the parent path*/ remote = (char*)gf_malloc(sizeof(char) * (strlen("gpac://")+strlen(mux->file_name)+1) ); strcpy(remote, "gpac://"); strcat(remote, mux->file_name); k = od->objectDescriptorID; /*if files were created we'll have to clean up (swf import)*/ if (mux->delete_file) gf_list_add(priv->files_to_delete, gf_strdup(remote)); gf_odf_desc_del((GF_Descriptor *) od); od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->URLString = remote; od->objectDescriptorID = k; ODS_SetupOD(priv->scene, od); } if (keep_com) break; } break; case GF_ODF_OD_REMOVE_TAG: { GF_ODRemove *odR = (GF_ODRemove*)com; for (k=0; k<odR->NbODs; k++) { GF_ObjectManager *odm = gf_scene_find_odm(priv->scene, odR->OD_ID[k]); if (odm) gf_odm_disconnect(odm, 1); } } break; default: break; } if (keep_com) { gf_list_insert(au->commands, com, 0); break; } else { gf_odf_com_del(&com); } if (e) break; } } sc->last_au_time = au_time + 1; /*attach graph to renderer*/ if (!priv->scene->graph_attached) gf_scene_attach_to_compositor(priv->scene); if (e) return e; /*for root streams remove completed AUs (no longer needed)*/ if (sc->in_root_od && !gf_list_count(au->commands) ) { j--; gf_list_rem(sc->AUs, j); gf_list_del(au->commands); gf_free(au); } } } if (e) return e; if ((priv->load_flags==2) && !nb_updates) return GF_EOS; return GF_OK; }
GF_Err encode_laser(GF_LoadCompare *lc, char *item_path, GF_ISOFile *mp4, GF_SMEncodeOptions *opts) { GF_Err e = GF_OK; GF_SceneLoader load; GF_SceneManager *ctx; GF_SceneGraph *sg; GF_StatManager *statsman = NULL; memset(&load, 0, sizeof(GF_SceneLoader)); sg = gf_sg_new(); ctx = gf_sm_new(sg); load.ctx = ctx; load.fileName = item_path; e = gf_sm_load_init(&load); if (e) { fprintf(stderr, "Error loading file %s\n", item_path); } else { e = gf_sm_load_run(&load); if (e) { fprintf(stderr, "Error loading file %s\n", item_path); } else { if (opts->auto_qant) { if (lc->verbose) fprintf(stdout, "Analysing Scene for Automatic Quantization\n"); statsman = gf_sm_stats_new(); e = gf_sm_stats_for_scene(statsman, ctx); if (!e) { GF_SceneStatistics *stats = gf_sm_stats_get(statsman); if (opts->resolution > (s32)stats->frac_res_2d) { if (lc->verbose) fprintf(stdout, " Given resolution %d is (unnecessarily) too high, using %d instead.\n", opts->resolution, stats->frac_res_2d); opts->resolution = stats->frac_res_2d; } else if (stats->int_res_2d + opts->resolution <= 0) { if (lc->verbose) fprintf(stdout, " Given resolution %d is too low, using %d instead.\n", opts->resolution, stats->int_res_2d - 1); opts->resolution = 1 - stats->int_res_2d; } opts->coord_bits = stats->int_res_2d + opts->resolution; if (lc->verbose) fprintf(stdout, " Coordinates & Lengths encoded using "); if (opts->resolution < 0) { if (lc->verbose) fprintf(stdout, "only the %d most significant bits (of %d).\n", opts->coord_bits, stats->int_res_2d); } else { if (lc->verbose) fprintf(stdout, "a %d.%d representation\n", stats->int_res_2d, opts->resolution); } if (lc->verbose) fprintf(stdout, " Matrix Scale & Skew Coefficients "); if (opts->coord_bits < stats->scale_int_res_2d) { opts->scale_bits = stats->scale_int_res_2d - opts->coord_bits; if (lc->verbose) fprintf(stdout, "encoded using a %d.8 representation\n", stats->scale_int_res_2d); } else { opts->scale_bits = 0; if (lc->verbose) fprintf(stdout, "not encoded.\n"); } } gf_sm_stats_del(statsman); } e = gf_sm_encode_to_file(ctx, mp4, opts); if (e) { fprintf(stderr, "Error while encoding mp4 file\n"); } else { e = gf_isom_set_brand_info(mp4, GF_ISOM_BRAND_MP42, 1); if (!e) e = gf_isom_modify_alternate_brand(mp4, GF_ISOM_BRAND_ISOM, 1); } gf_sm_load_done(&load); } } gf_sm_del(ctx); gf_sg_del(sg); return e; }
void DANAE_SceneLoader_Parse(void *p) { gf_sm_load_run(p); }