99
106
CTXLoadPriv *priv = (CTXLoadPriv *) gf_node_get_private(node);
100
107
M_Conditional*c = (M_Conditional*)node;
101
108
/*always apply in parent graph to handle protos correctly*/
102
if (!c->reverseActivate) gf_sg_command_apply_list(gf_node_get_graph(node), c->buffer.commandList, gf_is_get_time(priv->inline_scene));
109
if (!c->reverseActivate)
110
gf_sg_command_apply_list(gf_node_get_graph(node), c->buffer.commandList, gf_is_get_time(priv->inline_scene));
105
113
void CTXLoad_NodeInit(void *cbk, GF_Node *node)
107
115
CTXLoadPriv *priv = (CTXLoadPriv *) cbk;
108
116
if (gf_node_get_tag(node) == TAG_MPEG4_Conditional) {
109
((M_Conditional*)node)->on_activate = CTXLoad_OnActivate;
110
((M_Conditional*)node)->on_reverseActivate = CTXLoad_OnReverseActivate;
117
M_Conditional*c = (M_Conditional*)node;
118
c->on_activate = CTXLoad_OnActivate;
119
c->on_reverseActivate = CTXLoad_OnReverseActivate;
111
120
gf_node_set_private(node, priv);
113
122
gf_term_on_node_init(priv->inline_scene, node);
117
static GF_Err CTXLoad_AttachScene(GF_SceneDecoder *plug, GF_InlineScene *scene, Bool is_scene_decoder)
126
static Bool CTXLoad_CheckDownload(CTXLoadPriv *priv)
130
u32 now = gf_sys_clock();
132
if (!priv->file_size && (now - priv->last_check_time < 1000) ) return 0;
134
f = fopen(priv->file_name, "rt");
135
fseek(f, 0, SEEK_END);
139
/*we MUST have a complete file for now ...*/
140
if (!priv->file_size) {
141
if (priv->last_check_size == size) return 1;
142
priv->last_check_size = size;
143
priv->last_check_time = now;
145
if (size==priv->file_size) return 1;
150
static void CTXLoad_OnMessage(void *cbk, char *szMsg, GF_Err e)
152
CTXLoadPriv *priv = (CTXLoadPriv *)cbk;
153
gf_term_message(priv->inline_scene->root_od->term, priv->inline_scene->root_od->net_service->url, szMsg, e);
156
static void CTXLoad_OnProgress(void *cbk, u32 done, u32 tot)
159
CTXLoadPriv *priv = (CTXLoadPriv *)cbk;
160
evt.type = GF_EVT_PROGRESS;
161
evt.progress.progress_type = 2;
162
evt.progress.done = done;
163
evt.progress.total = tot;
164
evt.progress.service = priv->inline_scene->root_od->net_service->url;
165
GF_USER_SENDEVENT(priv->inline_scene->root_od->term->user, &evt);
169
static GF_Err CTXLoad_Setup(GF_BaseDecoder *plug)
119
171
CTXLoadPriv *priv = plug->privateStack;
120
if (priv->ctx) return GF_BAD_PARAM;
122
priv->inline_scene = scene;
123
priv->app = scene->root_od->term;
125
gf_sg_set_init_callback(scene->graph, CTXLoad_NodeInit, priv);
129
static GF_Err CTXLoad_ReleaseScene(GF_SceneDecoder *plug)
131
CTXLoad_Reset((CTXLoadPriv *) plug->privateStack);
172
if (!priv->file_name) return GF_BAD_PARAM;
174
priv->ctx = gf_sm_new(priv->inline_scene->graph);
175
memset(&priv->load, 0, sizeof(GF_SceneLoader));
176
priv->load.ctx = priv->ctx;
177
priv->load.cbk = priv;
178
priv->load.scene_graph = priv->inline_scene->graph;
179
priv->load.fileName = priv->file_name;
180
priv->load.OnMessage = CTXLoad_OnMessage;
181
priv->load.OnProgress = CTXLoad_OnProgress;
182
priv->load.flags = GF_SM_LOAD_FOR_PLAYBACK;
183
priv->load.localPath = gf_modules_get_option((GF_BaseInterface *)plug, "General", "CacheDirectory");
184
priv->load.swf_import_flags = GF_SM_SWF_STATIC_DICT | GF_SM_SWF_QUAD_CURVE | GF_SM_SWF_SCALABLE_LINE;
156
211
return GF_NON_COMPLIANT_BITSTREAM;
158
213
/*main dummy stream we need a dsi*/
159
if (!decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM;
161
priv->fileName = strdup(decSpecInfo);
215
return GF_NON_COMPLIANT_BITSTREAM;
216
bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ);
217
priv->file_size = gf_bs_read_u32(bs);
219
GF_SAFEALLOC(priv->file_name, sizeof(char)*(1 + decSpecInfoSize - sizeof(u32)) );
220
memcpy(priv->file_name, decSpecInfo + sizeof(u32), sizeof(char)*(decSpecInfoSize - sizeof(u32)) );
162
221
priv->nb_streams = 1;
163
222
priv->load_flags = 0;
164
223
priv->base_stream_id = ES_ID;
228
priv->progressive_support = 0;
229
priv->sax_max_duration = 0;
231
ext = strrchr(priv->file_name, '.');
232
if (!ext) return GF_OK;
235
if (!stricmp(ext, "xmt") || !stricmp(ext, "xmtz") || !stricmp(ext, "xmta")
236
|| !stricmp(ext, "x3d") || !stricmp(ext, "x3dz")
238
ext = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "Progressive");
239
priv->progressive_support = (ext && !stricmp(ext, "yes")) ? 1 : 0;
241
if (priv->progressive_support) {
242
ext = gf_modules_get_option((GF_BaseInterface *)plug, "SAXLoader", "MaxDuration");
243
if (ext) priv->sax_max_duration = atoi(ext);
255
static GF_Err CTXLoad_AttachScene(GF_SceneDecoder *plug, GF_InlineScene *scene, Bool is_scene_decoder)
257
CTXLoadPriv *priv = plug->privateStack;
258
if (priv->ctx) return GF_BAD_PARAM;
260
priv->inline_scene = scene;
261
priv->app = scene->root_od->term;
263
gf_sg_set_init_callback(scene->graph, CTXLoad_NodeInit, priv);
268
static GF_Err CTXLoad_ReleaseScene(GF_SceneDecoder *plug)
270
CTXLoad_Reset((CTXLoadPriv *) plug->privateStack);
175
274
static Bool CTXLoad_StreamInRootOD(GF_ObjectDescriptor *od, u32 ESID)
190
static void CTXLoad_OnMessage(void *cbk, char *szMsg, GF_Err e)
192
CTXLoadPriv *priv = (CTXLoadPriv *)cbk;
193
gf_term_message(priv->inline_scene->root_od->term, priv->inline_scene->root_od->net_service->url, szMsg, e);
196
static void CTXLoad_OnProgress(void *cbk, u32 done, u32 tot)
199
CTXLoadPriv *priv = (CTXLoadPriv *)cbk;
200
evt.type = GF_EVT_PROGRESS;
201
evt.progress.progress_type = 2;
202
evt.progress.done = done;
203
evt.progress.total = tot;
204
evt.progress.service = priv->inline_scene->root_od->net_service->url;
205
GF_USER_SENDEVENT(priv->inline_scene->root_od->term->user, &evt);
208
290
static GF_SceneGraph *CTXLoad_GetProtoLib(void *cbk, MFURL *lib_url)
307
static void CTXLoad_CheckStreams(CTXLoadPriv *priv )
311
GF_StreamContext *sc;
314
while ((sc = gf_list_enum(priv->ctx->streams, &i))) {
315
/*all streams in root OD are handled with ESID 0 to differentiate with any animation streams*/
316
if (CTXLoad_StreamInRootOD(priv->ctx->root_od, sc->ESID)) sc->ESID = 0;
317
if (!sc->timeScale) sc->timeScale = 1000;
320
while ((au = gf_list_enum(sc->AUs, &j))) {
321
if (!au->timing) au->timing = (u64) (sc->timeScale*au->timing_sec);
323
if (au && !sc->ESID && (au->timing>max_dur)) max_dur = (u32) (au->timing * 1000 / sc->timeScale);
326
priv->inline_scene->root_od->duration = max_dur;
327
gf_is_set_duration(priv->inline_scene);
226
331
static GF_Err CTXLoad_ProcessData(GF_SceneDecoder *plug, unsigned char *inBuffer, u32 inBufferLength,
227
332
u16 ES_ID, u32 stream_time, u32 mmlevel)
229
334
GF_Err e = GF_OK;
230
u32 i, j, k, nb_updates, max_dur;
335
u32 i, j, k, nb_updates;
231
336
GF_AUContext *au;
232
337
Bool can_delete_com;
233
338
GF_StreamContext *sc;
239
344
/*this signals main scene deconnection, destroy the context if needed*/
347
e = CTXLoad_Setup((GF_BaseDecoder *)plug);
242
351
if (priv->load_flags != 2) {
353
if (priv->progressive_support) {
355
char file_buf[4096+1];
357
priv->src = fopen(priv->file_name, "rb");
358
if (!priv->src) return GF_URL_ERROR;
361
priv->load.type = GF_SM_LOAD_XMTA;
363
entry_time = gf_sys_clock();
364
fseek(priv->src, priv->file_pos, SEEK_SET);
367
nb_read = fread(file_buf, 1, 4096, priv->src);
368
file_buf[nb_read] = 0;
370
if (priv->file_pos==priv->file_size) {
371
CTXLoad_OnProgress(priv, priv->file_pos, priv->file_size);
374
priv->load_flags = 2;
375
gf_sm_load_done(&priv->load);
381
e = gf_sm_load_string(&priv->load, file_buf, 0);
382
priv->file_pos += nb_read;
384
diff = gf_sys_clock() - entry_time;
385
CTXLoad_OnProgress(priv, priv->file_pos, priv->file_size);
386
if (diff > priv->sax_max_duration) break;
388
if (!priv->inline_scene->graph_attached) {
389
gf_sg_set_scene_size_info(priv->inline_scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics);
390
gf_is_attach_to_renderer(priv->inline_scene);
392
CTXLoad_CheckStreams(priv);
243
395
/*load first frame only*/
244
if (!priv->load_flags) {
396
else if (!priv->load_flags) {
397
/*we need the whole file*/
398
if (!CTXLoad_CheckDownload(priv)) return GF_OK;
245
400
priv->load_flags = 1;
246
priv->ctx = gf_sm_new(priv->inline_scene->graph);
247
memset(&priv->load, 0, sizeof(GF_SceneLoader));
248
priv->load.ctx = priv->ctx;
249
priv->load.cbk = priv;
250
priv->load.scene_graph = priv->inline_scene->graph;
251
priv->load.fileName = priv->fileName;
252
priv->load.OnMessage = CTXLoad_OnMessage;
253
priv->load.OnProgress = CTXLoad_OnProgress;
254
priv->load.flags = GF_SM_LOAD_FOR_PLAYBACK;
255
priv->load.swf_import_flags = GF_SM_SWF_STATIC_DICT | GF_SM_SWF_QUAD_CURVE | GF_SM_SWF_SCALABLE_LINE;
256
401
e = gf_sm_load_init(&priv->load);
258
403
gf_sg_set_scene_size_info(priv->inline_scene->graph, priv->ctx->scene_width, priv->ctx->scene_height, priv->ctx->is_pixel_metrics);
280
425
/*and figure out duration of root scene, and take care of XMT timing*/
282
for (i=0; i<gf_list_count(priv->ctx->streams); i++) {
283
sc = gf_list_get(priv->ctx->streams, i);
284
/*all streams in root OD are handled with ESID 0 to differentiate with any animation streams*/
285
if (CTXLoad_StreamInRootOD(priv->ctx->root_od, sc->ESID)) sc->ESID = 0;
286
if (!sc->timeScale) sc->timeScale = 1000;
289
for (j = 0; j<gf_list_count(sc->AUs); j++) {
290
au = gf_list_get(sc->AUs, j);
291
if (!au->timing) au->timing = (u32) (sc->timeScale*au->timing_sec);
293
if (au && !sc->ESID && (au->timing>max_dur)) max_dur = au->timing * 1000 / sc->timeScale;
295
426
if (priv->load_flags==2) {
297
priv->inline_scene->root_od->duration = max_dur;
298
gf_is_set_duration(priv->inline_scene);
427
CTXLoad_CheckStreams(priv);
428
if (!gf_list_count(priv->ctx->streams)) {
429
gf_is_attach_to_renderer(priv->inline_scene);
305
for (i=0; i<gf_list_count(priv->ctx->streams); i++) {
306
GF_StreamContext *sc = gf_list_get(priv->ctx->streams, i);
437
while ((sc = gf_list_enum(priv->ctx->streams, &i))) {
307
438
/*not our stream*/
308
439
if (sc->ESID && (sc->ESID != ES_ID)) continue;
309
440
/*not the base stream*/
325
456
if (!sc->ESID && (priv->load_flags==2)) can_delete_com = 1;
327
458
/*we're in the right stream, apply update*/
328
for (j=0; j<gf_list_count(sc->AUs); j++) {
329
GF_AUContext *au = gf_list_get(sc->AUs, j);
330
u32 au_time = au->timing*1000/sc->timeScale;
460
while ((au = gf_list_enum(sc->AUs, &j))) {
461
u32 au_time = (u32) (au->timing*1000/sc->timeScale);
331
462
if (au_time + 1 <= sc->last_au_time) {
332
463
/*remove first replace command*/
333
if (!sc->ESID && (sc->streamType==GF_STREAM_SCENE)) {
464
if (can_delete_com && (sc->streamType==GF_STREAM_SCENE)) {
334
465
while (gf_list_count(au->commands)) {
335
466
GF_Command *com = gf_list_get(au->commands, 0);
336
467
gf_list_rem(au->commands, 0);
337
468
gf_sg_command_del(com);
339
471
gf_list_rem(sc->AUs, j);
340
472
gf_list_del(au->commands);
519
651
case GF_SM_LOAD_XMTA: return "XMT-A Parser";
520
652
case GF_SM_LOAD_X3D: return "X3D (XML Syntax) Parser";
521
653
case GF_SM_LOAD_SWF: return "Flash (SWF) Emulator";
654
case GF_SM_LOAD_SVG: return "SVG Loader";
655
case GF_SM_LOAD_XSR: return "LASeRML Loader";
522
656
case GF_SM_LOAD_MP4: return "MP4 Memory Loader";
523
658
default: return "Undetermined";
527
662
Bool CTXLoad_CanHandleStream(GF_BaseDecoder *ifce, u32 StreamType, u32 ObjectType, unsigned char *decSpecInfo, u32 decSpecInfoSize, u32 PL)
529
if ((StreamType==GF_STREAM_PRIVATE_SCENE) && (ObjectType==1)) return 1;
664
if (StreamType==GF_STREAM_PRIVATE_SCENE) {
665
if (ObjectType==1) return 1;
666
/*LASeR ML: we use this plugin since it has command handling*/
667
if (ObjectType==3) return 1;
670
//if ((StreamType==GF_STREAM_PRIVATE_SCENE) && (ObjectType==2)) return 1;
533
674
void DeleteContextLoader(GF_BaseDecoder *plug)
535
676
CTXLoadPriv *priv = plug->privateStack;
536
if (priv->fileName) free(priv->fileName);
677
if (priv->file_name) free(priv->file_name);
537
678
assert(!priv->ctx);
538
679
gf_list_del(priv->files_to_delete);