This source file includes following definitions.
- CTXLoad_GetCapabilities
- CTXLoad_SetCapabilities
- ODS_SetupOD
- CTXLoad_Reset
- CTXLoad_ExecuteConditional
- CTXLoad_OnActivate
- CTXLoad_OnReverseActivate
- CTXLoad_NodeCallback
- CTXLoad_CheckDownload
- CTXLoad_Setup
- CTXLoad_AttachStream
- CTXLoad_DetachStream
- CTXLoad_AttachScene
- CTXLoad_ReleaseScene
- CTXLoad_StreamInRootOD
- CTXLoad_GetVRMLTime
- CTXLoad_CheckStreams
- CTXLoad_ProcessData
- CTXLoad_GetName
- CTXLoad_CanHandleStream
- DeleteContextLoader
- NewContextLoader
- QueryInterfaces
- LoadInterface
- ShutdownInterface
#include <gpac/internal/terminal_dev.h>
#include <gpac/scene_manager.h>
#include <gpac/constants.h>
#include <gpac/network.h>
#include <gpac/nodes_mpeg4.h>
#if !defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_SCENEGRAPH)
typedef struct
{
GF_Scene *scene;
GF_Terminal *app;
GF_SceneManager *ctx;
GF_SceneLoader load;
char *file_name;
u64 file_size;
u32 load_flags;
u32 nb_streams;
u32 base_stream_id;
u32 last_check_time;
u64 last_check_size;
GF_List *files_to_delete;
FILE *src;
u32 file_pos, sax_max_duration;
Bool progressive_support;
const char *service_url;
} CTXLoadPriv;
static GF_Err CTXLoad_GetCapabilities(GF_BaseDecoder *plug, GF_CodecCapability *cap)
{
cap->cap.valueInt = 0;
return GF_NOT_SUPPORTED;
}
static GF_Err CTXLoad_SetCapabilities(GF_BaseDecoder *plug, const GF_CodecCapability capability)
{
return GF_OK;
}
static void ODS_SetupOD(GF_Scene *scene, GF_ObjectDescriptor *od)
{
GF_ObjectManager *odm;
odm = gf_scene_find_odm(scene, od->objectDescriptorID);
if (odm) gf_odm_disconnect(odm, 1);
odm = gf_odm_new();
odm->OD = od;
odm->term = scene->root_od->term;
odm->parentscene = scene;
gf_mx_p(scene->mx_resources);
gf_list_add(scene->resources, odm);
gf_mx_v(scene->mx_resources);
gf_odm_setup_object(odm, scene->root_od->net_service);
}
static void CTXLoad_Reset(CTXLoadPriv *priv)
{
if (priv->ctx) gf_sm_del(priv->ctx);
priv->ctx = NULL;
gf_sg_reset(priv->scene->graph);
if (priv->load_flags != 3) priv->load_flags = 0;
while (gf_list_count(priv->files_to_delete)) {
char *fileName = (char*)gf_list_get(priv->files_to_delete, 0);
gf_list_rem(priv->files_to_delete, 0);
gf_delete_file(fileName);
gf_free(fileName);
}
}
static void CTXLoad_ExecuteConditional(M_Conditional *c, GF_Scene *scene)
{
GF_List *clist = c->buffer.commandList;
c->buffer.commandList = NULL;
gf_sg_command_apply_list(gf_node_get_graph((GF_Node*)c), clist, gf_scene_get_time(scene));
if (c->buffer.commandList != NULL) {
while (gf_list_count(clist)) {
GF_Command *sub_com = (GF_Command *)gf_list_get(clist, 0);
gf_sg_command_del(sub_com);
gf_list_rem(clist, 0);
}
gf_list_del(clist);
} else {
c->buffer.commandList = clist;
}
}
static void CTXLoad_OnActivate(GF_Node *node, GF_Route *route)
{
GF_Scene *scene = (GF_Scene *) gf_node_get_private(node);
M_Conditional*c = (M_Conditional*)node;
if (c->activate) CTXLoad_ExecuteConditional(c, scene);
}
static void CTXLoad_OnReverseActivate(GF_Node *node, GF_Route *route)
{
GF_Scene *scene = (GF_Scene *) gf_node_get_private(node);
M_Conditional*c = (M_Conditional*)node;
if (!c->reverseActivate)
CTXLoad_ExecuteConditional(c, scene);
}
void CTXLoad_NodeCallback(void *cbk, u32 type, GF_Node *node, void *param)
{
if ((type==GF_SG_CALLBACK_INIT) && (gf_node_get_tag(node) == TAG_MPEG4_Conditional) ) {
M_Conditional*c = (M_Conditional*)node;
c->on_activate = CTXLoad_OnActivate;
c->on_reverseActivate = CTXLoad_OnReverseActivate;
gf_node_set_private(node, cbk);
} else {
gf_term_node_callback(cbk, type, node, param);
}
}
static Bool CTXLoad_CheckDownload(CTXLoadPriv *priv)
{
u64 size;
FILE *f;
u32 now = gf_sys_clock();
if (!priv->file_size && (now - priv->last_check_time < 1000) ) return GF_FALSE;
f = gf_fopen(priv->file_name, "rt");
if (!f) return GF_FALSE;
gf_fseek(f, 0, SEEK_END);
size = gf_ftell(f);
gf_fclose(f);
if (!priv->file_size) {
if (priv->last_check_size == size) return GF_TRUE;
priv->last_check_size = size;
priv->last_check_time = now;
} else {
if (size==priv->file_size) return GF_TRUE;
}
return GF_FALSE;
}
static GF_Err CTXLoad_Setup(GF_BaseDecoder *plug)
{
CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack;
if (!priv->file_name) return GF_BAD_PARAM;
priv->ctx = gf_sm_new(priv->scene->graph);
memset(&priv->load, 0, sizeof(GF_SceneLoader));
priv->load.ctx = priv->ctx;
priv->load.is = priv->scene;
priv->load.scene_graph = priv->scene->graph;
priv->load.fileName = priv->file_name;
priv->load.src_url = priv->service_url;
priv->load.flags = GF_SM_LOAD_FOR_PLAYBACK;
priv->load.localPath = gf_modules_get_option((GF_BaseInterface *)plug, "General", "CacheDirectory");
priv->load.swf_import_flags = GF_SM_SWF_STATIC_DICT | GF_SM_SWF_QUAD_CURVE | GF_SM_SWF_SCALABLE_LINE | GF_SM_SWF_SPLIT_TIMELINE;
return GF_OK;
}
static GF_Err CTXLoad_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd)
{
const char *ext;
GF_BitStream *bs;
u32 size;
CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack;
if (esd->decoderConfig->upstream) return GF_NOT_SUPPORTED;
if (priv->ctx) {
GF_StreamContext *sc;
u32 i = 0;
while ((sc = (GF_StreamContext *)gf_list_enum(priv->ctx->streams, &i))) {
if (esd->ESID == sc->ESID) {
priv->nb_streams++;
return GF_OK;
}
}
return GF_NON_COMPLIANT_BITSTREAM;
}
if (!esd->decoderConfig->decoderSpecificInfo)
return GF_NON_COMPLIANT_BITSTREAM;
bs = gf_bs_new(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_BITSTREAM_READ);
priv->file_size = gf_bs_read_u32(bs);
gf_bs_del(bs);
size = esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32);
priv->file_name = (char *) gf_malloc(sizeof(char)*(1 + size) );
memcpy(priv->file_name, esd->decoderConfig->decoderSpecificInfo->data + sizeof(u32), sizeof(char)*(esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32)) );
priv->file_name[size] = 0;
priv->nb_streams = 1;
priv->load_flags = 0;
priv->base_stream_id = esd->ESID;
priv->service_url = esd->service_url;
CTXLoad_Setup(plug);
priv->progressive_support = GF_FALSE;
priv->sax_max_duration = 0;
ext = strrchr(priv->file_name, '.');
if (!ext) return GF_OK;
ext++;
if (!stricmp(ext, "xmt") || !stricmp(ext, "xmtz") || !stricmp(ext, "xmta")
|| !stricmp(ext, "x3d") || !stricmp(ext, "x3dz")
) {
ext = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "Progressive");
priv->progressive_support = (ext && !stricmp(ext, "yes")) ? GF_TRUE : GF_FALSE;
}
if (priv->progressive_support) {
ext = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "MaxDuration");
if (ext) priv->sax_max_duration = atoi(ext);
}
return GF_OK;
}
static GF_Err CTXLoad_DetachStream(GF_BaseDecoder *plug, u16 ES_ID)
{
CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack;
priv->nb_streams --;
return GF_OK;
}
static GF_Err CTXLoad_AttachScene(GF_SceneDecoder *plug, GF_Scene *scene, Bool is_scene_decoder)
{
CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack;
if (priv->ctx) return GF_BAD_PARAM;
priv->scene = scene;
priv->app = scene->root_od->term;
gf_sg_set_node_callback(scene->graph, CTXLoad_NodeCallback);
return GF_OK;
}
static GF_Err CTXLoad_ReleaseScene(GF_SceneDecoder *plug)
{
CTXLoad_Reset((CTXLoadPriv *) plug->privateStack);
return GF_OK;
}
static Bool CTXLoad_StreamInRootOD(GF_ObjectDescriptor *od, u32 ESID)
{
u32 i, count;
if (!od) return GF_TRUE;
count = gf_list_count(od->ESDescriptors);
if (!count) return GF_TRUE;
for (i=0; i<count; i++) {
GF_ESD *esd = (GF_ESD *)gf_list_get(od->ESDescriptors, i);
if (esd->ESID==ESID) return GF_TRUE;
}
return GF_FALSE;
}
Double CTXLoad_GetVRMLTime(void *cbk)
{
u32 secs, msecs;
Double res;
gf_utc_time_since_1970(&secs, &msecs);
res = msecs;
res /= 1000;
res += secs;
return res;
}
static void CTXLoad_CheckStreams(CTXLoadPriv *priv )
{
u32 i, j, max_dur;
GF_AUContext *au;
GF_StreamContext *sc;
max_dur = 0;
i=0;
while ((sc = (GF_StreamContext *)gf_list_enum(priv->ctx->streams, &i))) {
if (CTXLoad_StreamInRootOD(priv->ctx->root_od, sc->ESID)) sc->in_root_od = GF_TRUE;
if (!sc->timeScale) sc->timeScale = 1000;
j=0;
while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) {
if (!au->timing) au->timing = (u64) (sc->timeScale*au->timing_sec);
}
if (au && sc->in_root_od && (au->timing>max_dur)) max_dur = (u32) (au->timing * 1000 / sc->timeScale);
}
if (max_dur) {
priv->scene->root_od->duration = max_dur;
gf_scene_set_duration(priv->scene);
}
}
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;
if (priv->load_flags==3) return GF_EOS;
assert(ES_ID);
if (!priv->ctx) {
e = CTXLoad_Setup((GF_BaseDecoder *)plug);
if (e) return e;
}
if (stream_time==(u32)-1) {
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;
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))) {
if (!sc->in_root_od && (sc->ESID != ES_ID)) continue;
if (sc->in_root_od && (priv->base_stream_id != ES_ID)) continue;
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);
}
}
else if (!priv->load_flags) {
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);
if ((priv->load.type==GF_SM_LOAD_VRML) || (priv->load.type==GF_SM_LOAD_X3DV) || (priv->load.type==GF_SM_LOAD_X3D)) {
gf_sg_set_scene_time_callback(priv->scene->graph, CTXLoad_GetVRMLTime);
}
}
}
else {
priv->load_flags = 2;
e = gf_sm_load_run(&priv->load);
gf_sm_load_done(&priv->load);
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;
}
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))) {
if (!sc->in_root_od && (sc->ESID != ES_ID)) continue;
if (sc->in_root_od && (priv->base_stream_id != ES_ID)) continue;
if ((sc->streamType == GF_STREAM_OD) && (priv->load_flags==1)) continue;
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;
j=0;
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) {
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;
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;
if (can_delete_com) {
k--;
gf_list_rem(au->commands, k);
gf_sg_command_del(com);
}
}
}
else if (sc->streamType == GF_STREAM_OD) {
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);
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;
}
if (CTXLoad_StreamInRootOD(priv->ctx->root_od, esd->OCRESID)) esd->OCRESID = priv->base_stream_id;
if (od->URLString) {
gf_odf_desc_del((GF_Descriptor *) od);
continue;
}
k=0;
while ((mux = (GF_MuxInfo*)gf_list_enum(esd->extensionDescriptors, &k))) {
if (mux->tag == GF_ODF_MUXINFO_TAG) break;
mux = NULL;
}
if (!mux || !mux->file_name) {
if (!esd->decoderConfig) {
gf_odf_desc_del((GF_Descriptor *) od);
} else if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
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 if (esd->decoderConfig->streamType==GF_STREAM_OCR) {
ODS_SetupOD(priv->scene, od);
} else {
gf_odf_desc_del((GF_Descriptor *) od);
}
continue;
}
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;
}
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;
}
esd->decoderConfig->streamType = GF_STREAM_PRIVATE_SCENE;
esd->dependsOnESID = priv->base_stream_id;
ODS_SetupOD(priv->scene, od);
continue;
#endif
}
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);
}
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 (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;
if (!priv->scene->graph_attached)
gf_scene_attach_to_compositor(priv->scene);
if (e) return e;
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;
}
const char *CTXLoad_GetName(struct _basedecoder *plug)
{
CTXLoadPriv *priv = (CTXLoadPriv *)plug->privateStack;
switch (priv->load.type) {
case GF_SM_LOAD_BT:
return "MPEG-4 BT Parser";
case GF_SM_LOAD_VRML:
return "VRML 97 Parser";
case GF_SM_LOAD_X3DV:
return "X3D (VRML Syntax) Parser";
case GF_SM_LOAD_XMTA:
return "XMT-A Parser";
case GF_SM_LOAD_X3D:
return "X3D (XML Syntax) Parser";
case GF_SM_LOAD_SWF:
return "Flash (SWF) Emulator";
case GF_SM_LOAD_XSR:
return "LASeRML Loader";
case GF_SM_LOAD_MP4:
return "MP4 Memory Loader";
case GF_SM_LOAD_XBL:
return "XBL Parser";
default:
return "Undetermined";
}
}
static u32 CTXLoad_CanHandleStream(GF_BaseDecoder *ifce, u32 StreamType, GF_ESD *esd, u8 PL)
{
if (StreamType==GF_STREAM_PRIVATE_SCENE) {
if (!esd) return GF_CODEC_STREAM_TYPE_SUPPORTED;
switch (esd->decoderConfig->objectTypeIndication) {
case GPAC_OTI_PRIVATE_SCENE_GENERIC:
return GF_CODEC_SUPPORTED;
case GPAC_OTI_PRIVATE_SCENE_LASER:
return GF_CODEC_SUPPORTED;
case GPAC_OTI_PRIVATE_SCENE_XBL:
return GF_CODEC_SUPPORTED;
case GPAC_OTI_PRIVATE_SCENE_SVG:
return GF_CODEC_MAYBE_SUPPORTED;
}
} else if (StreamType==GF_STREAM_SCENE) {
if (!esd) return GF_CODEC_STREAM_TYPE_SUPPORTED;
switch (esd->decoderConfig->objectTypeIndication) {
case GPAC_OTI_SCENE_SVG:
case GPAC_OTI_SCENE_SVG_GZ:
case GPAC_OTI_SCENE_DIMS:
return GF_CODEC_MAYBE_SUPPORTED;
default:
break;
}
}
return GF_CODEC_NOT_SUPPORTED;
}
void DeleteContextLoader(GF_BaseDecoder *plug)
{
CTXLoadPriv *priv;
if (!plug)
return;
priv = (CTXLoadPriv *)plug->privateStack;
if (priv) {
if (priv->file_name)
gf_free(priv->file_name);
priv->file_name = NULL;
assert(!priv->ctx);
if (priv->files_to_delete)
gf_list_del(priv->files_to_delete);
priv->files_to_delete = NULL;
gf_free(priv);
plug->privateStack = NULL;
}
gf_free(plug);
}
GF_BaseDecoder *NewContextLoader()
{
CTXLoadPriv *priv;
GF_SceneDecoder *tmp;
GF_SAFEALLOC(tmp, GF_SceneDecoder);
if (!tmp) return NULL;
GF_SAFEALLOC(priv, CTXLoadPriv);
if (!priv) {
gf_free(tmp);
return NULL;
}
priv->files_to_delete = gf_list_new();
tmp->privateStack = priv;
tmp->AttachStream = CTXLoad_AttachStream;
tmp->DetachStream = CTXLoad_DetachStream;
tmp->GetCapabilities = CTXLoad_GetCapabilities;
tmp->SetCapabilities = CTXLoad_SetCapabilities;
tmp->ProcessData = CTXLoad_ProcessData;
tmp->AttachScene = CTXLoad_AttachScene;
tmp->ReleaseScene = CTXLoad_ReleaseScene;
tmp->GetName = CTXLoad_GetName;
tmp->CanHandleStream = CTXLoad_CanHandleStream;
GF_REGISTER_MODULE_INTERFACE(tmp, GF_SCENE_DECODER_INTERFACE, "GPAC Context Loader", "gpac distribution")
return (GF_BaseDecoder*)tmp;
}
#endif
GPAC_MODULE_EXPORT
const u32 *QueryInterfaces()
{
static u32 si [] = {
#if !defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_SCENEGRAPH)
GF_SCENE_DECODER_INTERFACE,
#endif
0
};
return si;
}
GPAC_MODULE_EXPORT
GF_BaseInterface *LoadInterface(u32 InterfaceType)
{
switch (InterfaceType) {
#if !defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_SCENEGRAPH)
case GF_SCENE_DECODER_INTERFACE:
return (GF_BaseInterface *)NewContextLoader();
#endif
default:
return NULL;
}
}
GPAC_MODULE_EXPORT
void ShutdownInterface(GF_BaseInterface *ifce)
{
switch (ifce->InterfaceType) {
#if !defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_SCENEGRAPH)
case GF_SCENE_DECODER_INTERFACE:
DeleteContextLoader((GF_BaseDecoder *)ifce);
break;
#endif
}
}
GPAC_MODULE_STATIC_DECLARATION( ctx_load )