Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Management sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/scene_manager.h>
27 : #include <gpac/constants.h>
28 : #include <gpac/utf.h>
29 : #include <gpac/network.h>
30 : #include <gpac/xml.h>
31 : #include <gpac/internal/bifs_dev.h>
32 : #include <gpac/internal/scenegraph_dev.h>
33 : #include <gpac/nodes_x3d.h>
34 :
35 : #ifndef GPAC_DISABLE_LOADER_XMT
36 :
37 : void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName);
38 :
39 : /*for QP types*/
40 : #include "../bifs/quant.h"
41 :
42 : typedef struct
43 : {
44 : GF_Node *node;
45 : GF_FieldInfo container_field;
46 : GF_ChildNodeItem *last;
47 : } XMTNodeStack;
48 :
49 :
50 : /**/
51 : enum
52 : {
53 : /*document is not yet initialized*/
54 : XMT_STATE_INIT = 0,
55 : /*document head is being parsed*/
56 : XMT_STATE_HEAD = 1,
57 : /*document body being parsed*/
58 : XMT_STATE_BODY = 2,
59 : /*commands are being parsed*/
60 : XMT_STATE_COMMANDS = 3,
61 : /*elements are being parsed*/
62 : XMT_STATE_ELEMENTS = 4,
63 : /*end of body parsing*/
64 : XMT_STATE_BODY_END = 5,
65 : /*end of parsing*/
66 : XMT_STATE_END = 6,
67 : };
68 :
69 :
70 : typedef struct
71 : {
72 : /*1: XMT-A, 2: X3D, 3: XMT-O (not supported yet) */
73 : u32 doc_type;
74 : /*0: not init, 1: header, 2: body*/
75 : u32 state;
76 : u32 current_node_tag;
77 :
78 : GF_SceneLoader *load;
79 : GF_Err last_error;
80 : GF_SAXParser *sax_parser;
81 : XMTNodeStack *x3d_root;
82 :
83 : /* stack of nodes for SAX parsing*/
84 : GF_List *nodes;
85 : /* stack of descriptors for SAX parsing*/
86 : GF_List *descriptors;
87 :
88 : GF_List *peeked_nodes;
89 : GF_List *def_nodes;
90 : GF_List *inserted_routes, *unresolved_routes;
91 :
92 : /* OD and ESD links*/
93 : GF_List *od_links, *esd_links;
94 : /*set when parsing proto*/
95 : GF_Proto *parsing_proto;
96 : GF_ProtoFieldInterface *proto_field;
97 :
98 : GF_StreamContext *scene_es;
99 : GF_AUContext *scene_au;
100 : u32 base_scene_id;
101 : /*current scene command*/
102 : GF_Command *command;
103 : SFCommandBuffer *command_buffer;
104 :
105 : GF_StreamContext *od_es;
106 : GF_AUContext *od_au;
107 : u32 base_od_id;
108 : /*current od command*/
109 : GF_ODCom *od_command;
110 :
111 :
112 : /*current stream ID, AU time and RAP flag*/
113 : u32 stream_id;
114 : Double au_time;
115 : Bool au_is_rap;
116 : Bool in_com;
117 : GF_List *script_to_load;
118 : } GF_XMTParser;
119 :
120 :
121 : typedef struct
122 : {
123 : char *desc_name;
124 : u32 ID;
125 : /*store nodes referring to this URL*/
126 : GF_List *mf_urls;
127 : GF_ObjectDescriptor *od;
128 : } XMT_ODLink;
129 :
130 : typedef struct
131 : {
132 : char *desc_name;
133 : u32 ESID;
134 : GF_ESD *esd;
135 : char *OCR_Name;
136 : char *Depends_Name;
137 : } XMT_ESDLink;
138 :
139 :
140 5 : static GF_Err xmt_report(GF_XMTParser *parser, GF_Err e, char *format, ...)
141 : {
142 : #ifndef GPAC_DISABLE_LOG
143 5 : if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
144 : char szMsg[2048];
145 : va_list args;
146 5 : va_start(args, format);
147 : vsnprintf(szMsg, 2048, format, args);
148 5 : va_end(args);
149 5 : GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[XMT Parsing] %s (line %d)\n", szMsg, gf_xml_sax_get_line(parser->sax_parser)) );
150 : }
151 : #endif
152 5 : if (e) parser->last_error = e;
153 5 : return e;
154 : }
155 45 : static void xmt_progress(void *cbk, u64 done, u64 total)
156 : {
157 45 : gf_set_progress("XMT Parsing", done, total);
158 45 : }
159 : static Bool xmt_esid_available(GF_XMTParser *parser, u16 ESID)
160 : {
161 : u32 i;
162 : XMT_ESDLink *esdl;
163 0 : i=0;
164 0 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
165 0 : if (esdl->ESID == ESID) return 0;
166 : }
167 : return 1;
168 : }
169 :
170 20 : static char *xmt_get_es_name(GF_XMTParser *parser, u16 ESID)
171 : {
172 : u32 i;
173 : XMT_ESDLink *esdl;
174 20 : i=0;
175 50 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
176 30 : if (esdl->ESID == ESID) return esdl->desc_name;
177 : }
178 : return NULL;
179 : }
180 :
181 25 : static void xmt_new_od_link(GF_XMTParser *parser, GF_ObjectDescriptor *od, char *name, u32 ID)
182 : {
183 : u32 i, j, count;
184 : XMT_ODLink *odl;
185 :
186 25 : if (!ID) {
187 0 : if (!strnicmp(name, "od", 2)) ID = atoi(name + 2);
188 0 : else if (!strnicmp(name, "iod", 3)) ID = atoi(name+ 3);
189 : /*be careful, an url like "11-regression-test.mp4" will return 1 on sscanf :)*/
190 0 : else if (sscanf(name, "%u", &ID) == 1) {
191 : char szURL[20];
192 0 : sprintf(szURL, "%u", ID);
193 0 : if (strcmp(szURL, name)) {
194 0 : ID = 0;
195 : } else {
196 : name = NULL;
197 : }
198 : }
199 : }
200 :
201 25 : count = gf_list_count(parser->od_links);
202 60 : for (i=0; i<count; i++) {
203 40 : odl = (XMT_ODLink*)gf_list_get(parser->od_links, i);
204 40 : if ( (ID && (odl->ID == ID))
205 40 : || (odl->od == od)
206 40 : || (odl->desc_name && name && !strcmp(odl->desc_name, name))
207 : ) {
208 5 : if (!odl->od) odl->od = od;
209 5 : if (!odl->desc_name && name) odl->desc_name = gf_strdup(name);
210 5 : if (!od->objectDescriptorID) {
211 5 : od->objectDescriptorID = ID;
212 0 : } else if (ID && (od->objectDescriptorID != ID)) {
213 0 : xmt_report(parser, GF_BAD_PARAM, "Conflicting OD IDs %d vs %d\n", ID, od->objectDescriptorID);
214 : }
215 :
216 25 : for (j=i+1; j<count; j++) {
217 20 : XMT_ODLink *l2 = (XMT_ODLink*)gf_list_get(parser->od_links, j);
218 20 : if (l2->od == od) {
219 0 : odl->ID = od->objectDescriptorID = odl->od->objectDescriptorID;
220 0 : gf_list_rem(parser->od_links, j);
221 0 : if (l2->desc_name) gf_free(l2->desc_name);
222 0 : gf_list_del(l2->mf_urls);
223 0 : gf_free(l2);
224 0 : break;
225 : }
226 : }
227 : return;
228 : }
229 : }
230 20 : GF_SAFEALLOC(odl, XMT_ODLink);
231 20 : if (!odl) return;
232 :
233 20 : odl->mf_urls = gf_list_new();
234 20 : odl->od = od;
235 20 : if (ID) od->objectDescriptorID = ID;
236 20 : if (name) odl->desc_name = gf_strdup(name);
237 20 : gf_list_add(parser->od_links, odl);
238 : }
239 :
240 30 : static void xmt_new_od_link_from_node(GF_XMTParser *parser, char *name, MFURL *url)
241 : {
242 : u32 i, ID;
243 : XMT_ODLink *odl;
244 :
245 : /*find OD_ID*/
246 30 : ID = 0;
247 50 : if (!strnicmp(name, "od", 2)) ID = atoi(name + 2);
248 10 : else if (!strnicmp(name, "iod", 3)) ID = atoi(name + 3);
249 : /*be careful, an url like "11-regression-test.mp4" will return 1 on sscanf :)*/
250 10 : else if (sscanf(name, "%u", &ID) == 1) {
251 : char szURL[20];
252 0 : sprintf(szURL, "%u", ID);
253 0 : if (strcmp(szURL, name)) {
254 0 : ID = 0;
255 : } else {
256 : name = NULL;
257 : }
258 : }
259 10 : else ID = 0;
260 :
261 : /*write OD_ID*/
262 : assert(url->count);
263 30 : i = url->count - 1;
264 30 : url->vals[i].OD_ID = 0;
265 30 : url->vals->OD_ID = ID;
266 :
267 30 : i=0;
268 110 : while ((odl = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
269 100 : if ( (name && odl->desc_name && !strcmp(odl->desc_name, name))
270 80 : || (ID && odl->od && odl->od->objectDescriptorID==ID)
271 80 : || (ID && (odl->ID==ID))
272 : ) {
273 20 : if (url && (gf_list_find(odl->mf_urls, url)<0) ) gf_list_add(odl->mf_urls, url);
274 20 : return;
275 : }
276 : }
277 10 : GF_SAFEALLOC(odl, XMT_ODLink);
278 10 : if (!odl) return;
279 :
280 10 : odl->mf_urls = gf_list_new();
281 10 : if (url) gf_list_add(odl->mf_urls, url);
282 10 : if (ID) odl->ID = ID;
283 10 : else odl->desc_name = gf_strdup(name);
284 10 : gf_list_add(parser->od_links, odl);
285 : }
286 30 : static void xmt_new_esd_link(GF_XMTParser *parser, GF_ESD *esd, char *desc_name, u32 binID)
287 : {
288 : u32 i, j;
289 : XMT_ESDLink *esdl;
290 :
291 30 : i=0;
292 105 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
293 75 : if (esdl->esd && (esd!=esdl->esd)) continue;
294 0 : if (!esdl->esd) {
295 0 : if (!esdl->ESID || !desc_name || strcmp(esdl->desc_name, desc_name)) continue;
296 0 : esdl->esd = esd;
297 : }
298 0 : if (binID) {
299 : /*remove temp links*/
300 0 : if (esdl->ESID == (u16) ( ( (PTR_TO_U_CAST esdl) >> 16) | ( (PTR_TO_U_CAST esdl) & 0x0000FFFF) ) ) {
301 : GF_StreamContext *sc;
302 0 : j=0;
303 0 : while ((sc = (GF_StreamContext *)gf_list_enum(parser->load->ctx->streams, &j))) {
304 0 : if (sc->ESID!=esdl->ESID) continue;
305 : /*reassign*/
306 0 : sc->ESID = binID;
307 : break;
308 : }
309 : }
310 0 : esdl->ESID = esdl->esd->ESID = binID;
311 : }
312 0 : if (desc_name && !esdl->desc_name) {
313 0 : esdl->desc_name = gf_strdup(desc_name);
314 0 : if (!esdl->ESID && !strnicmp(desc_name, "es", 2)) esdl->ESID = atoi(&desc_name[2]);
315 : }
316 0 : return;
317 : }
318 30 : GF_SAFEALLOC(esdl, XMT_ESDLink);
319 30 : if (!esdl) return;
320 :
321 30 : esdl->esd = esd;
322 30 : esd->ESID = esdl->ESID = binID;
323 30 : if (desc_name) {
324 30 : if (!esdl->ESID && !strnicmp(desc_name, "es", 2)) esdl->ESID = atoi(&desc_name[2]);
325 30 : esdl->desc_name = gf_strdup(desc_name);
326 : }
327 30 : if (!esd->ESID) {
328 0 : esd->ESID = 1;
329 0 : while (!xmt_esid_available(parser, esd->ESID)) esd->ESID++;
330 0 : esdl->ESID = esd->ESID;
331 : }
332 :
333 30 : gf_list_add(parser->esd_links, esdl);
334 : }
335 0 : static Bool xmt_set_depend_id(GF_XMTParser *parser, GF_ESD *desc, char *es_name, Bool is_ocr_dep)
336 : {
337 : u32 i;
338 : XMT_ESDLink *esdl;
339 0 : if (!desc || !es_name) return 0;
340 :
341 0 : i=0;
342 0 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
343 0 : if (esdl->esd == desc) {
344 0 : if (is_ocr_dep)
345 0 : esdl->OCR_Name = gf_strdup(es_name);
346 : else
347 0 : esdl->Depends_Name = gf_strdup(es_name);
348 : return 1;
349 : }
350 : }
351 : return 0;
352 : }
353 :
354 10 : static u32 xmt_get_od_id(GF_XMTParser *parser, char *od_name)
355 : {
356 : u32 i, ID;
357 : XMT_ODLink *l;
358 10 : if (sscanf(od_name, "%u", &ID)==1) return ID;
359 :
360 10 : i=0;
361 20 : while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
362 20 : if (!l->od) continue;
363 20 : if (l->desc_name && !strcmp(l->desc_name, od_name)) return l->od->objectDescriptorID;
364 : }
365 : return 0;
366 : }
367 :
368 5 : static u32 xmt_get_esd_id(GF_XMTParser *parser, char *esd_name)
369 : {
370 : u32 i, ID;
371 : XMT_ESDLink *l;
372 5 : if (sscanf(esd_name, "%u", &ID)==1) return ID;
373 :
374 5 : i=0;
375 15 : while ((l = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
376 15 : if (!l->esd) continue;
377 15 : if (l->desc_name && !strcmp(l->desc_name, esd_name)) return l->esd->ESID;
378 : }
379 : return 0;
380 : }
381 0 : static u32 xmt_locate_stream(GF_XMTParser *parser, char *stream_name)
382 : {
383 : XMT_ESDLink *esdl;
384 : u32 i;
385 : char szN[200];
386 :
387 0 : i=0;
388 0 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
389 0 : if (esdl->desc_name && !strcmp(esdl->desc_name, stream_name)) return esdl->ESID;
390 0 : if (esdl->ESID) {
391 : sprintf(szN, "es%d", esdl->ESID);
392 0 : if (!strcmp(szN, stream_name)) return esdl->ESID;
393 0 : sprintf(szN, "%d", esdl->ESID);
394 0 : if (!strcmp(szN, stream_name)) return esdl->ESID;
395 : }
396 : }
397 0 : if (parser->load->ctx) {
398 : GF_StreamContext *sc;
399 0 : i=0;
400 0 : while ((sc = gf_list_enum(parser->load->ctx->streams, &i))) {
401 0 : if (sc->name && !strcmp(sc->name, stream_name)) return sc->ESID;
402 0 : sprintf(szN, "%d", sc->ESID);
403 0 : if (!strcmp(szN, stream_name)) return sc->ESID;
404 : }
405 : }
406 : /*create a temp one*/
407 0 : esdl = (XMT_ESDLink *)gf_malloc(sizeof(XMT_ESDLink));
408 : memset(esdl, 0, sizeof(XMT_ESDLink));
409 0 : esdl->ESID = (u16) ( (PTR_TO_U_CAST esdl) >> 16) | ( (PTR_TO_U_CAST esdl) & 0x0000FFFF);
410 0 : if (!strnicmp(stream_name, "es", 2)) esdl->ESID = atoi(&stream_name[2]);
411 0 : esdl->desc_name = gf_strdup(stream_name);
412 0 : gf_list_add(parser->esd_links, esdl);
413 0 : return esdl->ESID;
414 : }
415 0 : static Bool xmt_odid_available(GF_XMTParser *parser, u16 ODID)
416 : {
417 : u32 i;
418 : XMT_ODLink *l;
419 0 : i=0;
420 0 : while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
421 0 : if (l->ID == ODID) return 0;
422 0 : if (l->od && l->od->objectDescriptorID == ODID) return 0;
423 : }
424 : return 1;
425 : }
426 :
427 5 : static void xmt_resolve_od_links(GF_XMTParser *parser)
428 : {
429 : u32 i, j;
430 : XMT_ESDLink *esdl, *esdl2;
431 : XMT_ODLink *l;
432 : char szURL[5000];
433 :
434 : /*fix ESD IDs*/
435 5 : i=0;
436 40 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
437 30 : if (!esdl->esd) {
438 0 : xmt_report(parser, GF_BAD_PARAM, "Stream %s ID %d has no associated ES descriptor\n", esdl->desc_name ? esdl->desc_name : "", esdl->ESID);
439 0 : i--;
440 0 : gf_list_rem(parser->esd_links, i);
441 0 : if (esdl->desc_name) gf_free(esdl->desc_name);
442 0 : gf_free(esdl);
443 0 : continue;
444 : }
445 30 : if (esdl->ESID) esdl->esd->ESID = esdl->ESID;
446 0 : else if (!esdl->esd->ESID) {
447 : u16 ESID = 1;
448 0 : while (!xmt_esid_available(parser, ESID)) ESID++;
449 0 : esdl->esd->ESID = ESID;
450 : }
451 : }
452 :
453 : /*set OCR es ids*/
454 5 : i=0;
455 40 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
456 : Bool use_old_fmt;
457 : u16 ocr_id;
458 : char szTest[50];
459 :
460 30 : esdl->esd->OCRESID = 0;
461 30 : if (!esdl->OCR_Name) continue;
462 :
463 : use_old_fmt = 0;
464 0 : ocr_id = atoi(esdl->OCR_Name);
465 0 : sprintf(szTest, "%d", ocr_id);
466 0 : if (!stricmp(szTest, esdl->OCR_Name)) use_old_fmt = 1;
467 :
468 0 : j=0;
469 0 : while ((esdl2 = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &j))) {
470 0 : if (esdl2->desc_name && !strcmp(esdl2->desc_name, esdl->OCR_Name)) {
471 0 : esdl->esd->OCRESID = esdl2->esd->ESID;
472 0 : break;
473 : }
474 0 : if (use_old_fmt && (esdl2->esd->ESID==ocr_id)) {
475 0 : esdl->esd->OCRESID = ocr_id;
476 0 : break;
477 : }
478 : }
479 0 : if (!esdl->esd->OCRESID) {
480 0 : xmt_report(parser, GF_OK, "WARNING: Could not find clock reference %s for ES %s - forcing self-synchronization", esdl->OCR_Name, esdl->desc_name);
481 : }
482 0 : gf_free(esdl->OCR_Name);
483 0 : esdl->OCR_Name = NULL;
484 : }
485 :
486 : /*set dependsOn es ids*/
487 5 : i=0;
488 40 : while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
489 : Bool use_old_fmt;
490 : u16 dep_id;
491 : char szTest[50];
492 :
493 30 : esdl->esd->dependsOnESID = 0;
494 30 : if (!esdl->Depends_Name) continue;
495 :
496 : use_old_fmt = 0;
497 0 : dep_id = atoi(esdl->Depends_Name);
498 0 : sprintf(szTest, "%d", dep_id);
499 0 : if (!stricmp(szTest, esdl->Depends_Name)) use_old_fmt = 1;
500 :
501 0 : j=0;
502 0 : while ((esdl2 = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &j))) {
503 0 : if (esdl2->desc_name && !strcmp(esdl2->desc_name, esdl->Depends_Name)) {
504 0 : esdl->esd->dependsOnESID = esdl2->esd->ESID;
505 0 : break;
506 : }
507 0 : if (use_old_fmt && (esdl2->esd->ESID==dep_id)) {
508 0 : esdl->esd->dependsOnESID = dep_id;
509 0 : break;
510 : }
511 : }
512 0 : if (!esdl->esd->dependsOnESID) {
513 0 : xmt_report(parser, GF_OK, "WARNING: Could not find stream dependence %s for ES %s - forcing self-synchronization", esdl->Depends_Name, esdl->desc_name);
514 : }
515 0 : gf_free(esdl->Depends_Name);
516 0 : esdl->Depends_Name = NULL;
517 : }
518 :
519 35 : while (gf_list_count(parser->esd_links)) {
520 30 : esdl = (XMT_ESDLink *)gf_list_get(parser->esd_links, 0);
521 30 : gf_list_rem(parser->esd_links, 0);
522 30 : if (esdl->desc_name) gf_free(esdl->desc_name);
523 30 : gf_free(esdl);
524 : }
525 :
526 5 : i=0;
527 40 : while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
528 30 : if (l->od && !l->od->objectDescriptorID) {
529 : u16 ODID = 1;
530 0 : while (!xmt_odid_available(parser, ODID)) ODID++;
531 0 : l->od->objectDescriptorID = ODID;
532 : }
533 30 : if (l->od) {
534 20 : if (!l->ID) l->ID = l->od->objectDescriptorID;
535 : assert(l->ID == l->od->objectDescriptorID);
536 : }
537 : }
538 :
539 : /*unroll dep in case some URLs reference ODs by their binary IDs not their string ones*/
540 5 : i=0;
541 40 : while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
542 : XMT_ODLink *l2;
543 : /*not OD URL*/
544 30 : if (!l->ID) continue;
545 20 : j=i+1;
546 90 : while ((l2 = (XMT_ODLink*)gf_list_enum(parser->od_links, &j))) {
547 : /*not OD URL*/
548 50 : if (!l2->ID) continue;
549 15 : if (l->ID == l2->ID) {
550 0 : while (gf_list_count(l2->mf_urls)) {
551 0 : MFURL *url = (MFURL *)gf_list_get(l2->mf_urls, 0);
552 0 : gf_list_rem(l2->mf_urls, 0);
553 0 : gf_list_add(l->mf_urls, url);
554 : }
555 0 : j--;
556 0 : gf_list_rem(parser->od_links, j);
557 0 : if (l2->desc_name) gf_free(l2->desc_name);
558 0 : gf_list_del(l2->mf_urls);
559 0 : gf_free(l2);
560 : }
561 : }
562 : }
563 :
564 35 : while (gf_list_count(parser->od_links) ) {
565 30 : l = (XMT_ODLink*)gf_list_get(parser->od_links, 0);
566 30 : if (!l->od) {
567 : /*if no ID found this is not an OD URL*/
568 10 : if (l->ID) {
569 0 : if (l->desc_name) {
570 0 : xmt_report(parser, GF_OK, "WARNING: OD \"%s\" (ID %d) not assigned", l->desc_name, l->ID);
571 : } else {
572 0 : xmt_report(parser, GF_OK, "WARNING: OD ID %d not assigned", l->ID);
573 : }
574 : }
575 : } else {
576 : MFURL *the_url;
577 20 : j=0;
578 60 : while ((the_url = (MFURL *)gf_list_enum(l->mf_urls, &j))) {
579 : u32 k;
580 : char *seg = NULL;
581 20 : for (k=0; k<the_url->count; k++) {
582 20 : SFURL *url = &the_url->vals[k];
583 20 : if (url->url) seg = strstr(url->url, "#");
584 20 : if (seg) {
585 0 : sprintf(szURL, "od:%d#%s", l->od->objectDescriptorID, seg+1);
586 0 : gf_free(url->url);
587 0 : url->url = gf_strdup(szURL);
588 : } else {
589 20 : if (url->url) gf_free(url->url);
590 20 : url->url = NULL;
591 20 : url->OD_ID = l->od->objectDescriptorID;
592 : }
593 : }
594 : }
595 : }
596 :
597 30 : if (l->desc_name) gf_free(l->desc_name);
598 30 : gf_list_del(l->mf_urls);
599 30 : gf_free(l);
600 30 : gf_list_rem(parser->od_links, 0);
601 : }
602 5 : }
603 :
604 :
605 235 : static u32 xmt_get_next_node_id(GF_XMTParser *parser)
606 : {
607 : u32 ID;
608 235 : GF_SceneGraph *sc = parser->load->scene_graph;
609 235 : if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
610 235 : ID = gf_sg_get_next_available_node_id(sc);
611 235 : if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
612 205 : parser->load->ctx->max_node_id = ID;
613 235 : return ID;
614 : }
615 260 : static u32 xmt_get_node_id(GF_XMTParser *parser, char *name)
616 : {
617 : GF_Node *n = NULL;
618 260 : u32 ID = 0;
619 260 : if (sscanf(name, "N%u", &ID) == 1) {
620 : u32 k=1;
621 175 : ID++;
622 635 : while (name && name[k]) {
623 285 : if (strchr("0123456789", name[k])==0) {
624 0 : ID = 0;
625 0 : break;
626 : }
627 285 : k++;
628 : }
629 175 : if (ID) {
630 175 : n = gf_sg_find_node(parser->load->scene_graph, ID);
631 175 : if (!n) {
632 25 : if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
633 25 : return ID;
634 : }
635 : }
636 : }
637 235 : ID = xmt_get_next_node_id(parser);
638 235 : if (n) {
639 150 : GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[XMT Parsing] (line %d) Binary ID %s already assigned to %s - keeping internal ID %d\n", gf_xml_sax_get_line(parser->sax_parser), name, gf_node_get_name(n), ID));
640 : }
641 235 : return ID;
642 : }
643 :
644 3530 : static u32 xmt_get_node_tag(GF_XMTParser *parser, const char *node_name)
645 : {
646 : u32 tag;
647 : /*if VRML and allowing non MPEG4 nodes, use X3D*/
648 3530 : if ((parser->doc_type==2) && !(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) {
649 : #ifndef GPAC_DISABLE_X3D
650 0 : tag = gf_node_x3d_type_by_class_name(node_name);
651 0 : if (!tag)
652 : #endif
653 0 : tag = gf_node_mpeg4_type_by_class_name(node_name);
654 : } else {
655 3530 : tag = gf_node_mpeg4_type_by_class_name(node_name);
656 : /*if allowing non MPEG4 nodes, try X3D*/
657 : #ifndef GPAC_DISABLE_X3D
658 3530 : if (!tag && !(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) tag = gf_node_x3d_type_by_class_name(node_name);
659 : #endif
660 : }
661 3530 : return tag;
662 : }
663 :
664 295 : static GF_Node *xmt_find_node(GF_XMTParser *parser, char *ID)
665 : {
666 : u32 i, count, tag;
667 : Bool is_proto;
668 : char *node_class;
669 : GF_Node *n;
670 295 : if (!ID) return NULL;
671 295 : n = gf_sg_find_node_by_name(parser->load->scene_graph, ID);
672 295 : if (n) return n;
673 :
674 5 : count = gf_list_count(parser->peeked_nodes);
675 5 : for (i=0; i<count; i++) {
676 0 : n = (GF_Node*)gf_list_get(parser->peeked_nodes, i);
677 0 : if (!strcmp(gf_node_get_name(n), ID)) return n;
678 : }
679 5 : node_class = gf_xml_sax_peek_node(parser->sax_parser, "DEF", ID, "ProtoInstance", "name", "<par", &is_proto);
680 5 : if (!node_class) return NULL;
681 :
682 : n = NULL;
683 5 : if (is_proto) {
684 : GF_Proto *p;
685 0 : GF_SceneGraph *sg = parser->load->scene_graph;
686 : while (1) {
687 0 : p = gf_sg_find_proto(sg, 0, node_class);
688 0 : if (p) break;
689 0 : sg = sg->parent_scene;
690 0 : if (!sg) break;
691 : }
692 0 : if (!p) {
693 0 : xmt_report(parser, GF_BAD_PARAM, "%s: not a valid/supported proto", node_class);
694 0 : gf_free(node_class);
695 0 : return NULL;
696 : }
697 0 : n = gf_sg_proto_create_instance(parser->load->scene_graph, p);
698 : } else {
699 5 : tag = xmt_get_node_tag(parser, node_class);
700 5 : n = gf_node_new(parser->load->scene_graph, tag);
701 : }
702 5 : gf_free(node_class);
703 5 : if (n) {
704 5 : u32 nID = xmt_get_node_id(parser, ID);
705 5 : gf_node_set_id(n, nID, ID);
706 5 : if (!parser->parsing_proto) gf_node_init(n);
707 5 : gf_list_add(parser->peeked_nodes, n);
708 : }
709 : return n;
710 : }
711 :
712 : #define XMT_GET_ONE_VAL \
713 : char value[100]; \
714 : u32 i; \
715 : char *str = a_value; \
716 : if (!str) { \
717 : xmt_report(parser, GF_BAD_PARAM, "%s: Number expected", name); \
718 : return 0; \
719 : } \
720 : while (str[0] == ' ') str += 1; \
721 : i = 0; \
722 : while ((str[i] != ' ') && str[i]) { \
723 : value[i] = str[i]; \
724 : i++; \
725 : } \
726 : value[i] = 0; \
727 : while ((str[i] == ' ') && str[i]) i++;
728 :
729 560 : static u32 xmt_parse_int(GF_XMTParser *parser, const char *name, SFInt32 *val, char *a_value)
730 : {
731 560 : XMT_GET_ONE_VAL
732 560 : *val = atoi(value);
733 560 : return i;
734 : }
735 3625 : static u32 xmt_parse_float(GF_XMTParser *parser, const char *name, SFFloat *val, char *a_value)
736 : {
737 3625 : XMT_GET_ONE_VAL
738 3625 : *val = FLT2FIX(atof(value));
739 3625 : return i;
740 : }
741 5 : static u32 xmt_parse_time(GF_XMTParser *parser, const char *name, SFTime *val, char *a_value)
742 : {
743 5 : XMT_GET_ONE_VAL
744 5 : *val = atof(value);
745 5 : return i;
746 : }
747 160 : static u32 xmt_parse_bool(GF_XMTParser *parser, const char *name, SFBool *val, char *a_value)
748 : {
749 160 : XMT_GET_ONE_VAL
750 160 : if (!stricmp(value, "1") || !stricmp(value, "true"))
751 115 : *val = 1;
752 : else
753 45 : *val = 0;
754 : return i;
755 : }
756 :
757 150 : static u32 xmt_parse_string(GF_XMTParser *parser, const char *name, SFString *val, Bool is_mf, char *a_value)
758 : {
759 : char *value;
760 : char sep[10];
761 : u32 len;
762 : u32 i=0;
763 : u32 k=0;
764 : char *str = a_value;
765 150 : if (!str) return 0;
766 :
767 : /*SF string, no inspection*/
768 150 : if (!is_mf) {
769 25 : len = (u32) strlen(str);
770 25 : if (val->buffer) gf_free(val->buffer);
771 25 : val->buffer = NULL;
772 25 : if (len) val->buffer = gf_strdup(str);
773 25 : return len+1;
774 : }
775 :
776 : /*now this is the REAL pain:
777 : X3D allows '"String1" "String2"' and therefore '"String "test""'
778 : XMT allows '"String1" "String2"' and therefore '"String \"test\""'
779 : thus translating the string from xml to UTF may screw up the separators !! We need to identify them
780 : */
781 :
782 : i = 0;
783 0 : while ((str[i]==' ') || (str[i]=='\t')) i++;
784 125 : if (!strncmp(&str[i], """, 6)) strcpy(sep, """);
785 125 : else if (!strncmp(&str[i], "'", 6)) strcpy(sep, "'");
786 125 : else if (str[i]=='\'') strcpy(sep, "\'");
787 125 : else if (str[i]=='\"') strcpy(sep, "\"");
788 : /*handle as a single field (old GPAC XMT & any unknown cases...*/
789 : else {
790 10 : len = (u32) strlen(str);
791 10 : if (val->buffer) gf_free(val->buffer);
792 10 : val->buffer = NULL;
793 10 : if (len) val->buffer = gf_strdup(str);
794 : return len;
795 : }
796 : k = 0;
797 115 : i += (u32) strlen(sep);
798 :
799 115 : value = gf_strdup(str);
800 :
801 115 : if (strncmp(&str[i], sep, strlen(sep))) {
802 :
803 2215 : while (str[i]) {
804 2215 : if ((str[i] == '\\') && !strncmp(&str[i+1], sep, strlen(sep))) {
805 : i++;
806 0 : continue;
807 : }
808 2215 : value[k] = str[i];
809 2215 : i++;
810 2215 : k++;
811 2215 : if (!strncmp(&str[i], sep, strlen(sep)) && (str[i-1] != '\\')) break;
812 : }
813 : }
814 115 : value[k] = 0;
815 115 : len = (u32) strlen(sep) + i;
816 :
817 115 : if (val->buffer) gf_free(val->buffer);
818 115 : val->buffer = NULL;
819 115 : if (strlen(value)) val->buffer = gf_strdup(value);
820 115 : gf_free(value);
821 : return len;
822 : }
823 :
824 30 : static u32 xmt_parse_url(GF_XMTParser *parser, const char *name, MFURL *val, GF_Node *owner, Bool is_mf, char *a_value)
825 : {
826 : SFString sfstr;
827 : u32 res, idx;
828 : char value[5000], *tmp;
829 :
830 : /*parse as a string*/
831 30 : sfstr.buffer = NULL;
832 30 : res = xmt_parse_string(parser, name, &sfstr, is_mf, a_value);
833 30 : if (parser->last_error) return res;
834 :
835 : assert(val->count);
836 30 : idx = val->count - 1;
837 30 : if (val->vals[idx].url) gf_free(val->vals[idx].url);
838 30 : val->vals[idx].url = sfstr.buffer;
839 30 : val->vals[idx].OD_ID = 0;
840 : /*empty*/
841 30 : if (!val->vals[idx].url) return res;
842 :
843 : /*remove segments & viewpoints info to create OD link*/
844 : strcpy(value, val->vals[idx].url);
845 30 : tmp = strstr(value, "#");
846 30 : if (tmp) tmp[0] = 0;
847 :
848 : /*according to XMT-A spec, both 'od:' and 'od://' are tolerated in XMT-A*/
849 30 : if (!strnicmp(value, "od://", 5))
850 20 : xmt_new_od_link_from_node(parser, value+5, val);
851 10 : else if (!strnicmp(value, "od:", 3))
852 0 : xmt_new_od_link_from_node(parser, value+3, val);
853 : else
854 10 : xmt_new_od_link_from_node(parser, value, val);
855 : return res;
856 : }
857 :
858 :
859 5 : static u32 xmt_parse_script(GF_XMTParser *parser, const char *name, SFScript *val, Bool is_mf, char *a_value)
860 : {
861 : SFString sfstr;
862 : u32 res;
863 :
864 : /*parse as a string*/
865 5 : sfstr.buffer = NULL;
866 5 : res = xmt_parse_string(parser, name, &sfstr, is_mf, a_value);
867 5 : if (parser->last_error) return res;
868 :
869 5 : if (val->script_text) gf_free(val->script_text);
870 5 : val->script_text = (char*)sfstr.buffer;
871 : return res;
872 : }
873 :
874 : static void xmt_offset_time(GF_XMTParser *parser, Double *time)
875 : {
876 13 : if (time && parser)
877 13 : *time += parser->au_time;
878 : }
879 5 : static void xmt_check_time_offset(GF_XMTParser *parser, GF_Node *n, GF_FieldInfo *info)
880 : {
881 5 : if (!(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
882 1 : if (gf_node_get_tag(n) != TAG_ProtoNode) {
883 1 : if (!stricmp(info->name, "startTime") || !stricmp(info->name, "stopTime"))
884 1 : xmt_offset_time(parser, (Double *)info->far_ptr);
885 0 : } else if (gf_sg_proto_field_is_sftime_offset(n, info)) {
886 0 : xmt_offset_time(parser, (Double *)info->far_ptr);
887 : }
888 : }
889 :
890 2805 : static u32 xmt_parse_sf_field(GF_XMTParser *parser, GF_FieldInfo *info, GF_Node *n, char *a_value)
891 : {
892 : u32 res = 0;
893 2805 : switch (info->fieldType) {
894 545 : case GF_SG_VRML_SFINT32:
895 545 : res = xmt_parse_int(parser, info->name, (SFInt32 *)info->far_ptr, a_value);
896 545 : break;
897 160 : case GF_SG_VRML_SFBOOL:
898 160 : res = xmt_parse_bool(parser, info->name, (SFBool *)info->far_ptr, a_value);
899 160 : break;
900 1000 : case GF_SG_VRML_SFFLOAT:
901 1000 : res = xmt_parse_float(parser, info->name, (SFFloat *)info->far_ptr, a_value);
902 1000 : break;
903 5 : case GF_SG_VRML_SFTIME:
904 5 : res = xmt_parse_time(parser, info->name, (SFTime *)info->far_ptr, a_value);
905 5 : if (n) xmt_check_time_offset(parser, n, info);
906 : break;
907 255 : case GF_SG_VRML_SFCOLOR:
908 255 : res = xmt_parse_float(parser, info->name, & ((SFColor *)info->far_ptr)->red, a_value);
909 255 : res += xmt_parse_float(parser, info->name, & ((SFColor *)info->far_ptr)->green, a_value + res);
910 255 : res += xmt_parse_float(parser, info->name, & ((SFColor *)info->far_ptr)->blue, a_value + res);
911 255 : break;
912 580 : case GF_SG_VRML_SFVEC2F:
913 580 : res = xmt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->x, a_value);
914 580 : res += xmt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->y, a_value + res);
915 580 : break;
916 220 : case GF_SG_VRML_SFVEC3F:
917 220 : res = xmt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->x, a_value);
918 220 : res += xmt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->y, a_value + res);
919 220 : res += xmt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->z, a_value + res);
920 220 : break;
921 10 : case GF_SG_VRML_SFROTATION:
922 10 : res = xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->x, a_value);
923 10 : res += xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->y, a_value + res);
924 10 : res += xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->z, a_value + res);
925 10 : res += xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->q, a_value + res);
926 10 : break;
927 25 : case GF_SG_VRML_SFSTRING:
928 25 : res = xmt_parse_string(parser, info->name, (SFString*)info->far_ptr, 0, a_value);
929 25 : if (n && (n->sgprivate->tag==TAG_MPEG4_BitWrapper)) {
930 0 : gf_sm_update_bitwrapper_buffer(n, parser->load->fileName);
931 : }
932 : break;
933 0 : case GF_SG_VRML_SFSCRIPT:
934 0 : res = xmt_parse_script(parser, info->name, (SFScript *)info->far_ptr, 0, a_value);
935 0 : break;
936 0 : case GF_SG_VRML_SFCOMMANDBUFFER:
937 : {
938 0 : SFCommandBuffer *cb = (SFCommandBuffer *)info->far_ptr;
939 0 : if (parser->command_buffer) {
940 0 : cb->buffer = (unsigned char*)parser->command_buffer;
941 : } else {
942 0 : cb->buffer = (unsigned char*)parser->command;
943 : }
944 0 : parser->command_buffer = cb;
945 : }
946 0 : break;
947 :
948 5 : case GF_SG_VRML_SFIMAGE:
949 : {
950 : u32 k, size, v;
951 5 : SFImage *img = (SFImage *)info->far_ptr;
952 5 : res = xmt_parse_int(parser, "width", (SFInt32*)&img->width, a_value);
953 5 : if (parser->last_error) return res;
954 5 : res += xmt_parse_int(parser, "height", (SFInt32*)&img->height, a_value + res);
955 5 : if (parser->last_error) return res;
956 5 : res += xmt_parse_int(parser, "nbComp", (SFInt32*)&v, a_value + res);
957 5 : if (parser->last_error) return res;
958 5 : img->numComponents = v;
959 5 : size = img->width * img->height * img->numComponents;
960 5 : if (img->pixels) gf_free(img->pixels);
961 5 : img->pixels = (unsigned char*)gf_malloc(sizeof(char) * size);
962 5 : a_value += res;
963 : res = 0;
964 85 : for (k=0; k<size; k++) {
965 : char *name = "pixels";
966 80 : XMT_GET_ONE_VAL
967 80 : if (strstr(value, "0x")) sscanf(value, "%x", &v);
968 0 : else sscanf(value, "%u", &v);
969 80 : switch (img->numComponents) {
970 80 : case 1:
971 80 : img->pixels[k] = (char) v;
972 80 : break;
973 0 : case 2:
974 0 : img->pixels[k] = (char) (v>>8)&0xFF;
975 0 : img->pixels[k+1] = (char) (v)&0xFF;
976 : k++;
977 0 : break;
978 0 : case 3:
979 0 : img->pixels[k] = (char) (v>>16)&0xFF;
980 0 : img->pixels[k+1] = (char) (v>>8)&0xFF;
981 0 : img->pixels[k+2] = (char) (v)&0xFF;
982 : k+=2;
983 0 : break;
984 0 : case 4:
985 0 : img->pixels[k] = (char) (v>>24)&0xFF;
986 0 : img->pixels[k+1] = (char) (v>>16)&0xFF;
987 0 : img->pixels[k+2] = (char) (v>>8)&0xFF;
988 0 : img->pixels[k+3] = (char) (v)&0xFF;
989 : k+=3;
990 0 : break;
991 : }
992 80 : res += i;
993 80 : a_value += i;
994 : }
995 : }
996 5 : break;
997 :
998 0 : default:
999 0 : parser->last_error = GF_NOT_SUPPORTED;
1000 0 : break;
1001 : }
1002 : return res;
1003 : }
1004 :
1005 250 : static void xmt_parse_mf_field(GF_XMTParser *parser, GF_FieldInfo *info, GF_Node *n, char *value)
1006 : {
1007 : u32 res;
1008 : GF_FieldInfo sfInfo;
1009 250 : sfInfo.fieldType = gf_sg_vrml_get_sf_type(info->fieldType);
1010 250 : sfInfo.name = info->name;
1011 250 : gf_sg_vrml_mf_reset(info->far_ptr, info->fieldType);
1012 :
1013 250 : if (!value || !strlen(value)) return;
1014 :
1015 2305 : while (value[0] && !parser->last_error) {
1016 :
1017 2115 : while (value[0] == ' ')
1018 60 : value++;
1019 2055 : if (!value[0]) break;
1020 :
1021 2055 : gf_sg_vrml_mf_append(info->far_ptr, info->fieldType, &sfInfo.far_ptr);
1022 :
1023 : /*special case for MF type based on string (MFString, MFURL and MFScript), we need to take care
1024 : of all possible forms of XML multi string encoding*/
1025 2055 : if (sfInfo.fieldType == GF_SG_VRML_SFSTRING) {
1026 90 : res = xmt_parse_string(parser, info->name, (SFString*)sfInfo.far_ptr, 1, value);
1027 1965 : } else if (sfInfo.fieldType == GF_SG_VRML_SFURL) {
1028 30 : res = xmt_parse_url(parser, info->name, (MFURL *)info->far_ptr, n, 1, value);
1029 1935 : } else if (sfInfo.fieldType == GF_SG_VRML_SFSCRIPT) {
1030 5 : res = xmt_parse_script(parser, info->name, (SFScript*)sfInfo.far_ptr, 1, value);
1031 : } else {
1032 1930 : res = xmt_parse_sf_field(parser, &sfInfo, n, value);
1033 : }
1034 2055 : if (res) {
1035 2055 : value += res;
1036 : } else {
1037 : break;
1038 : }
1039 : }
1040 : }
1041 :
1042 10 : static Bool xmt_has_been_def(GF_XMTParser *parser, char *node_name)
1043 : {
1044 : u32 i, count;
1045 10 : count = gf_list_count(parser->def_nodes);
1046 170 : for (i=0; i<count; i++) {
1047 175 : GF_Node *n = (GF_Node *)gf_list_get(parser->def_nodes, i);
1048 175 : if (!strcmp(gf_node_get_name(n), node_name)) return 1;
1049 : }
1050 : return 0;
1051 : }
1052 :
1053 15 : static u32 xmt_get_route(GF_XMTParser *parser, char *name, Bool del_com)
1054 : {
1055 : u32 i;
1056 : GF_Command *com;
1057 15 : GF_Route *r = gf_sg_route_find_by_name(parser->load->scene_graph, name);
1058 15 : if (r) return r->ID;
1059 15 : i=0;
1060 15 : while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
1061 10 : if (com->def_name && !strcmp(com->def_name, name)) {
1062 10 : if (del_com) gf_list_rem(parser->inserted_routes, i);
1063 10 : return com->RouteID;
1064 : }
1065 : }
1066 : return 0;
1067 : }
1068 :
1069 5 : static Bool xmt_route_id_used(GF_XMTParser *parser, u32 ID)
1070 : {
1071 : u32 i;
1072 : GF_Command *com;
1073 5 : GF_Route *r = gf_sg_route_find(parser->load->scene_graph, ID);
1074 5 : if (r) return 1;
1075 5 : i=0;
1076 5 : while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
1077 0 : if (com->RouteID == ID) return 1;
1078 : }
1079 : return 0;
1080 : }
1081 0 : static u32 xmt_get_next_route_id(GF_XMTParser *parser)
1082 : {
1083 : u32 ID;
1084 0 : GF_SceneGraph *sc = parser->load->scene_graph;
1085 0 : if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
1086 :
1087 0 : ID = gf_sg_get_next_available_route_id(sc);
1088 0 : if (parser->load->ctx && (ID>parser->load->ctx->max_route_id))
1089 0 : parser->load->ctx->max_route_id = ID;
1090 0 : return ID;
1091 : }
1092 :
1093 20 : static void xmt_resolve_routes(GF_XMTParser *parser)
1094 : {
1095 : /*resolve all commands*/
1096 : while (1) {
1097 20 : GF_Command *com = (GF_Command *)gf_list_last(parser->unresolved_routes);
1098 20 : if (!com) break;
1099 0 : gf_list_rem_last(parser->unresolved_routes);
1100 0 : switch (com->tag) {
1101 0 : case GF_SG_ROUTE_DELETE:
1102 : case GF_SG_ROUTE_REPLACE:
1103 0 : com->RouteID = xmt_get_route(parser, com->unres_name, 0);
1104 0 : if (!com->RouteID) {
1105 0 : xmt_report(parser, GF_BAD_PARAM, "Cannot resolve GF_Route DEF %s", com->unres_name);
1106 : } else {
1107 0 : com->unresolved = 0;
1108 : }
1109 0 : gf_free(com->unres_name);
1110 0 : com->unres_name = NULL;
1111 0 : break;
1112 : }
1113 : }
1114 10 : while (gf_list_count(parser->inserted_routes)) gf_list_rem(parser->inserted_routes, 0);
1115 20 : }
1116 40 : static void xmt_parse_route(GF_XMTParser *parser, const GF_XMLAttribute *attributes, u32 nb_attributes, Bool is_insert, GF_Command *com)
1117 : {
1118 : GF_Route *r;
1119 : char *toN, *toNF, *fromN, *fromNF, *ID;
1120 : GF_Node *orig, *dest;
1121 : GF_Err e;
1122 : u32 rID, i;
1123 : GF_FieldInfo orig_field, dest_field;
1124 :
1125 : toN = toNF = fromN = fromNF = ID = NULL;
1126 :
1127 165 : for (i=0; i<nb_attributes; i++) {
1128 165 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
1129 165 : if (!att->value || !strlen(att->value)) continue;
1130 165 : if (!strcmp(att->name, "fromNode")) fromN = att->value;
1131 125 : else if (!strcmp(att->name, "fromField")) fromNF = att->value;
1132 85 : else if (!strcmp(att->name, "toNode")) toN = att->value;
1133 45 : else if (!strcmp(att->name, "toField")) toNF = att->value;
1134 5 : else if (!strcmp(att->name, "DEF")) ID = att->value;
1135 : }
1136 :
1137 40 : orig = xmt_find_node(parser, fromN);
1138 40 : if (!orig) {
1139 0 : xmt_report(parser, GF_BAD_PARAM, "ROUTE: Cannot find origin node %s", fromN);
1140 40 : return;
1141 : }
1142 40 : if (fromNF) {
1143 40 : e = gf_node_get_field_by_name(orig, fromNF, &orig_field);
1144 40 : if (e != GF_OK) {
1145 0 : char *sz = strstr(fromNF, "_changed");
1146 0 : if (sz) {
1147 0 : sz[0] = 0;
1148 0 : e = gf_node_get_field_by_name(orig, fromNF, &orig_field);
1149 : }
1150 : }
1151 : } else {
1152 : e = GF_BAD_PARAM;
1153 : }
1154 40 : if (e!=GF_OK) {
1155 0 : xmt_report(parser, GF_BAD_PARAM, "%s is not an attribute of node %s", fromNF, fromN);
1156 : return;
1157 : }
1158 :
1159 40 : dest = xmt_find_node(parser, toN);
1160 40 : if (!dest) {
1161 0 : xmt_report(parser, GF_BAD_PARAM, "ROUTE: Cannot find destination node %s", toN);
1162 : return;
1163 : }
1164 40 : if (toNF) {
1165 40 : e = gf_node_get_field_by_name(dest, toNF, &dest_field);
1166 40 : if ((e != GF_OK) && !strnicmp(toNF, "set_", 4))
1167 0 : e = gf_node_get_field_by_name(dest, &toNF[4], &dest_field);
1168 : } else {
1169 : e = GF_BAD_PARAM;
1170 : }
1171 40 : if (e != GF_OK) {
1172 0 : xmt_report(parser, GF_BAD_PARAM, "%s is not an attribute of node %s", toNF, toN);
1173 : return;
1174 : }
1175 :
1176 : rID = 0;
1177 40 : if (ID && strlen(ID)) {
1178 5 : rID = xmt_get_route(parser, ID, 0);
1179 5 : if (!rID && (ID[0]=='R') ) {
1180 10 : rID = atoi(&ID[1]);
1181 5 : if (rID) {
1182 5 : rID++;
1183 5 : if (xmt_route_id_used(parser, rID)) rID = 0;
1184 : }
1185 : }
1186 5 : if (!rID) rID = xmt_get_next_route_id(parser);
1187 : }
1188 40 : if (com) {
1189 : /*for insert command*/
1190 40 : if (rID) {
1191 5 : com->RouteID = rID;
1192 5 : com->def_name = gf_strdup(ID);
1193 : /*whenever not inserting in graph, keep track of max defined ID*/
1194 5 : gf_sg_set_max_defined_route_id(parser->load->scene_graph, rID);
1195 5 : if (rID>parser->load->ctx->max_route_id) parser->load->ctx->max_route_id = rID;
1196 :
1197 : }
1198 40 : com->fromNodeID = gf_node_get_id(orig);
1199 40 : com->fromFieldIndex = orig_field.fieldIndex;
1200 40 : com->toNodeID = gf_node_get_id(dest);
1201 40 : com->toFieldIndex = dest_field.fieldIndex;
1202 : return;
1203 : }
1204 0 : r = gf_sg_route_new(parser->load->scene_graph, orig, orig_field.fieldIndex, dest, dest_field.fieldIndex);
1205 0 : if (rID) {
1206 0 : gf_sg_route_set_id(r, rID);
1207 0 : gf_sg_route_set_name(r, ID);
1208 : }
1209 : }
1210 :
1211 :
1212 965 : static void xmt_update_timenode(GF_XMTParser *parser, GF_Node *node)
1213 : {
1214 965 : if (!(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
1215 :
1216 193 : switch (gf_node_get_tag(node)) {
1217 1 : case TAG_MPEG4_AnimationStream:
1218 1 : xmt_offset_time(parser, & ((M_AnimationStream*)node)->startTime);
1219 1 : xmt_offset_time(parser, & ((M_AnimationStream*)node)->stopTime);
1220 : break;
1221 1 : case TAG_MPEG4_AudioBuffer:
1222 1 : xmt_offset_time(parser, & ((M_AudioBuffer*)node)->startTime);
1223 1 : xmt_offset_time(parser, & ((M_AudioBuffer*)node)->stopTime);
1224 : break;
1225 1 : case TAG_MPEG4_AudioClip:
1226 1 : xmt_offset_time(parser, & ((M_AudioClip*)node)->startTime);
1227 1 : xmt_offset_time(parser, & ((M_AudioClip*)node)->stopTime);
1228 : break;
1229 1 : case TAG_MPEG4_AudioSource:
1230 1 : xmt_offset_time(parser, & ((M_AudioSource*)node)->startTime);
1231 1 : xmt_offset_time(parser, & ((M_AudioSource*)node)->stopTime);
1232 : break;
1233 1 : case TAG_MPEG4_MovieTexture:
1234 1 : xmt_offset_time(parser, & ((M_MovieTexture*)node)->startTime);
1235 1 : xmt_offset_time(parser, & ((M_MovieTexture*)node)->stopTime);
1236 : break;
1237 1 : case TAG_MPEG4_TimeSensor:
1238 1 : xmt_offset_time(parser, & ((M_TimeSensor*)node)->startTime);
1239 1 : xmt_offset_time(parser, & ((M_TimeSensor*)node)->stopTime);
1240 : break;
1241 4 : case TAG_ProtoNode:
1242 : {
1243 : u32 i, nbFields;
1244 : GF_FieldInfo inf;
1245 4 : nbFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL);
1246 34 : for (i=0; i<nbFields; i++) {
1247 30 : gf_node_get_field(node, i, &inf);
1248 30 : if (inf.fieldType != GF_SG_VRML_SFTIME) continue;
1249 0 : xmt_check_time_offset(parser, node, &inf);
1250 : }
1251 : }
1252 4 : break;
1253 : }
1254 : }
1255 :
1256 220 : static void xmt_strip_name(const char *in, char *out)
1257 : {
1258 220 : while (in[0]==' ') in++;
1259 : strcpy(out, in);
1260 0 : while (out[strlen(out)-1] == ' ') out[strlen(out)-1] = 0;
1261 220 : }
1262 :
1263 110 : static u32 xmt_get_ft_by_name(const char *_name)
1264 : {
1265 : char name[1024];
1266 110 : xmt_strip_name(_name, name);
1267 :
1268 110 : if (!strcmp(name, "Boolean") || !strcmp(name, "SFBool")) return GF_SG_VRML_SFBOOL;
1269 90 : else if (!strcmp(name, "Integer") || !strcmp(name, "SFInt32")) return GF_SG_VRML_SFINT32;
1270 90 : else if (!strcmp(name, "Color") || !strcmp(name, "SFColor")) return GF_SG_VRML_SFCOLOR;
1271 70 : else if (!strcmp(name, "Vector2") || !strcmp(name, "SFVec2f")) return GF_SG_VRML_SFVEC2F;
1272 50 : else if (!strcmp(name, "Image") || !strcmp(name, "SFImage")) return GF_SG_VRML_SFIMAGE;
1273 50 : else if (!strcmp(name, "Time") || !strcmp(name, "SFTime")) return GF_SG_VRML_SFTIME;
1274 45 : else if (!strcmp(name, "Float") || !strcmp(name, "SFFloat")) return GF_SG_VRML_SFFLOAT;
1275 15 : else if (!strcmp(name, "Vector3") || !strcmp(name, "SFVec3f")) return GF_SG_VRML_SFVEC3F;
1276 15 : else if (!strcmp(name, "Rotation") || !strcmp(name, "SFRotation")) return GF_SG_VRML_SFROTATION;
1277 15 : else if (!strcmp(name, "String") || !strcmp(name, "SFString")) return GF_SG_VRML_SFSTRING;
1278 15 : else if (!strcmp(name, "Node") || !strcmp(name, "SFNode")) return GF_SG_VRML_SFNODE;
1279 0 : else if (!strcmp(name, "Booleans") || !strcmp(name, "MFBool")) return GF_SG_VRML_MFBOOL;
1280 0 : else if (!strcmp(name, "Integers") || !strcmp(name, "MFInt32")) return GF_SG_VRML_MFINT32;
1281 0 : else if (!strcmp(name, "Colors") || !strcmp(name, "MFColor")) return GF_SG_VRML_MFCOLOR;
1282 0 : else if (!strcmp(name, "Vector2s") || !strcmp(name, "Vector2Array") || !strcmp(name, "MFVec2f")) return GF_SG_VRML_MFVEC2F;
1283 0 : else if (!strcmp(name, "Images") || !strcmp(name, "MFImage")) return GF_SG_VRML_MFIMAGE;
1284 0 : else if (!strcmp(name, "Times") || !strcmp(name, "MFTime")) return GF_SG_VRML_MFTIME;
1285 0 : else if (!strcmp(name, "Floats") || !strcmp(name, "MFFloat")) return GF_SG_VRML_MFFLOAT;
1286 0 : else if (!strcmp(name, "Vector3s") || !strcmp(name, "Vector3Array") || !strcmp(name, "MFVec3f")) return GF_SG_VRML_MFVEC3F;
1287 0 : else if (!strcmp(name, "Rotations") || !strcmp(name, "MFRotation")) return GF_SG_VRML_MFROTATION;
1288 0 : else if (!strcmp(name, "Strings") || !strcmp(name, "MFString")) return GF_SG_VRML_MFSTRING;
1289 0 : else if (!strcmp(name, "Nodes") || !strcmp(name, "MFNode")) return GF_SG_VRML_MFNODE;
1290 :
1291 0 : else if (!strcmp(name, "SFColorRGBA")) return GF_SG_VRML_SFCOLORRGBA;
1292 0 : else if (!strcmp(name, "MFColorRGBA")) return GF_SG_VRML_MFCOLORRGBA;
1293 0 : else if (!strcmp(name, "SFDouble")) return GF_SG_VRML_SFDOUBLE;
1294 0 : else if (!strcmp(name, "MFDouble")) return GF_SG_VRML_MFDOUBLE;
1295 0 : else if (!strcmp(name, "SFVec3d")) return GF_SG_VRML_SFVEC3D;
1296 0 : else if (!strcmp(name, "MFVec3d")) return GF_SG_VRML_MFVEC3D;
1297 0 : else if (!strcmp(name, "SFVec2d")) return GF_SG_VRML_SFVEC2D;
1298 0 : else if (!strcmp(name, "MFVec2d")) return GF_SG_VRML_MFVEC2D;
1299 0 : else return GF_SG_VRML_UNKNOWN;
1300 : }
1301 10 : static u32 xmt_get_script_et_by_name(const char *_name)
1302 : {
1303 : char name[1024];
1304 10 : xmt_strip_name((char *)_name, name);
1305 :
1306 10 : if (!strcmp(name, "eventIn") || !strcmp(name, "inputOnly") ) return GF_SG_SCRIPT_TYPE_EVENT_IN;
1307 5 : else if (!strcmp(name, "eventOut") || !strcmp(name, "outputOnly")) return GF_SG_SCRIPT_TYPE_EVENT_OUT;
1308 5 : else if (!strcmp(name, "field") || !strcmp(name, "initializeOnly") ) return GF_SG_SCRIPT_TYPE_FIELD;
1309 0 : else return GF_SG_EVENT_UNKNOWN;
1310 : }
1311 100 : static u32 xmt_get_et_by_name(const char *_name)
1312 : {
1313 : char name[1024];
1314 100 : xmt_strip_name((char *)_name, name);
1315 :
1316 100 : if (!strcmp(name, "eventIn") || !strcmp(name, "inputOnly") ) return GF_SG_EVENT_IN;
1317 90 : else if (!strcmp(name, "eventOut") || !strcmp(name, "outputOnly")) return GF_SG_EVENT_OUT;
1318 90 : else if (!strcmp(name, "field") || !strcmp(name, "initializeOnly") ) return GF_SG_EVENT_FIELD;
1319 90 : else if (!strcmp(name, "exposedField") || !strcmp(name, "inputOutput")) return GF_SG_EVENT_EXPOSED_FIELD;
1320 0 : else return GF_SG_EVENT_UNKNOWN;
1321 : }
1322 :
1323 10 : static void xmt_parse_script_field(GF_XMTParser *parser, GF_Node *node, const GF_XMLAttribute *attributes, u32 nb_attributes)
1324 : {
1325 : GF_ScriptField *scfield;
1326 : GF_FieldInfo field;
1327 : u32 fieldType, eventType, i;
1328 : char *val = NULL;
1329 : char *fieldName = NULL;
1330 : fieldType = eventType = 0;
1331 :
1332 40 : for (i=0; i<nb_attributes; i++) {
1333 30 : GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
1334 30 : if (!att->value || !strlen(att->value)) continue;
1335 30 : if (!strcmp(att->name, "name")) fieldName = att->value;
1336 20 : else if (!strcmp(att->name, "type")) fieldType = xmt_get_ft_by_name(att->value);
1337 10 : else if (!strcmp(att->name, "vrml97Hint") || !strcmp(att->name, "accessType")) eventType = xmt_get_script_et_by_name(att->value);
1338 0 : else if (strstr(att->name, "value") || strstr(att->name, "Value")) val = att->value;
1339 : }
1340 10 : scfield = gf_sg_script_field_new(node, eventType, fieldType, fieldName);
1341 :
1342 10 : if (!scfield) {
1343 0 : xmt_report(parser, GF_BAD_PARAM, "Cannot create script field - please check syntax");
1344 0 : return;
1345 : }
1346 10 : if (val) {
1347 0 : gf_node_get_field_by_name(node, fieldName, &field);
1348 0 : if (gf_sg_vrml_is_sf_field(fieldType)) {
1349 0 : xmt_parse_sf_field(parser, &field, node, val);
1350 : } else {
1351 0 : xmt_parse_mf_field(parser, &field, node, val);
1352 : }
1353 : }
1354 : }
1355 :
1356 15 : static u32 xmt_get_next_proto_id(GF_XMTParser *parser)
1357 : {
1358 : u32 ID;
1359 15 : GF_SceneGraph *sc = parser->load->scene_graph;
1360 15 : if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
1361 15 : ID = gf_sg_get_next_available_proto_id(sc);
1362 15 : if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
1363 10 : parser->load->ctx->max_proto_id = ID;
1364 15 : return ID;
1365 : }
1366 :
1367 15 : static void xmt_parse_proto(GF_XMTParser *parser, const GF_XMLAttribute *attributes, u32 nb_attributes, GF_List *proto_list)
1368 : {
1369 : GF_FieldInfo info;
1370 : GF_Proto *proto;
1371 : char *szName, *extURL;
1372 : u32 ID, i;
1373 :
1374 : szName = extURL = NULL;
1375 50 : for (i=0; i<nb_attributes; i++) {
1376 35 : GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
1377 35 : if (!att->value || !strlen(att->value)) continue;
1378 35 : if (!strcmp(att->name, "name")) szName = att->value;
1379 : // else if (!strcmp(att->name, "protoID")) ID = atoi(att->value);
1380 20 : else if (!strcmp(att->name, "locations")) extURL = att->value;
1381 15 : else if (!strcmp(att->name, "url")) extURL = att->value;
1382 : }
1383 :
1384 15 : ID = xmt_get_next_proto_id(parser);
1385 15 : proto = gf_sg_proto_new(parser->load->scene_graph, ID, szName, proto_list ? 1 : 0);
1386 15 : if (proto_list) gf_list_add(proto_list, proto);
1387 15 : if (parser->load->ctx && (parser->load->ctx->max_proto_id<ID)) parser->load->ctx->max_proto_id=ID;
1388 :
1389 : /*store previous proto*/
1390 15 : proto->userpriv = parser->parsing_proto;
1391 15 : parser->parsing_proto = proto;
1392 15 : parser->load->scene_graph = gf_sg_proto_get_graph(proto);
1393 :
1394 15 : if (extURL) {
1395 5 : info.fieldType = GF_SG_VRML_MFURL;
1396 5 : info.far_ptr = &proto->ExternProto;
1397 5 : info.name = "ExternURL";
1398 5 : xmt_parse_mf_field(parser, &info, NULL, extURL);
1399 : }
1400 15 : }
1401 0 : static u32 xmt_get_protofield_qp_type(const char *QP_Type)
1402 : {
1403 : #ifndef GPAC_DISABLE_BIFS
1404 0 : if (!strcmp(QP_Type, "position3D")) return QC_3DPOS;
1405 0 : else if (!strcmp(QP_Type, "position2D")) return QC_2DPOS;
1406 0 : else if (!strcmp(QP_Type, "drawingOrder")) return QC_ORDER;
1407 0 : else if (!strcmp(QP_Type, "color")) return QC_COLOR;
1408 0 : else if (!strcmp(QP_Type, "textureCoordinate")) return QC_TEXTURE_COORD;
1409 0 : else if (!strcmp(QP_Type, "angle")) return QC_ANGLE;
1410 0 : else if (!strcmp(QP_Type, "scale")) return QC_SCALE;
1411 0 : else if (!strcmp(QP_Type, "keys")) return QC_INTERPOL_KEYS;
1412 0 : else if (!strcmp(QP_Type, "normals")) return QC_NORMALS;
1413 0 : else if (!strcmp(QP_Type, "rotations")) return QC_ROTATION;
1414 0 : else if (!strcmp(QP_Type, "size3D")) return QC_SIZE_3D;
1415 0 : else if (!strcmp(QP_Type, "size2D")) return QC_SIZE_2D;
1416 0 : else if (!strcmp(QP_Type, "linear")) return QC_LINEAR_SCALAR;
1417 0 : else if (!strcmp(QP_Type, "coordIndex")) return QC_COORD_INDEX;
1418 : #endif
1419 0 : return 0;
1420 : }
1421 :
1422 0 : static GF_Err x3d_get_default_container(GF_Node *par, GF_Node *n, GF_FieldInfo *info)
1423 : {
1424 : u32 i, count;
1425 0 : count = gf_node_get_field_count(par);
1426 : /*get the first field/exposedField accepting this child*/
1427 0 : for (i=0; i<count; i++) {
1428 0 : gf_node_get_field(par, i, info);
1429 0 : if ((info->fieldType!=GF_SG_VRML_SFNODE) && (info->fieldType!=GF_SG_VRML_MFNODE)) continue;
1430 0 : if ((info->eventType==GF_SG_EVENT_OUT) || (info->eventType==GF_SG_EVENT_IN)) continue;
1431 0 : if (gf_node_in_table(n, info->NDTtype)) return GF_OK;
1432 : }
1433 : return GF_BAD_PARAM;
1434 : }
1435 :
1436 :
1437 2020 : static GF_Node *xmt_parse_element(GF_XMTParser *parser, char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes, XMTNodeStack *parent)
1438 : {
1439 : GF_Err e;
1440 : GF_FieldInfo info;
1441 : u32 tag, i, ID;
1442 : Bool register_def = 0;
1443 : Bool is_script = 0;
1444 : GF_Node *node;
1445 : GF_FieldInfo container;
1446 : char *def_name;
1447 : GF_Proto *proto = NULL;
1448 :
1449 : node = NULL;
1450 2020 : if (!strcmp(name, "NULL")) return NULL;
1451 2020 : if (!strcmp(name, "ROUTE")) {
1452 30 : if (!parser->parsing_proto && (parser->doc_type==1) ) {
1453 30 : GF_Command *sgcom = gf_sg_command_new(parser->load->scene_graph, GF_SG_ROUTE_INSERT);
1454 30 : gf_list_add(parser->scene_au->commands, sgcom);
1455 30 : xmt_parse_route(parser, attributes, nb_attributes, 0, sgcom);
1456 30 : if (sgcom->RouteID) gf_list_add(parser->inserted_routes, sgcom);
1457 : } else {
1458 0 : xmt_parse_route(parser, attributes, nb_attributes, 0, NULL);
1459 : }
1460 : return NULL;
1461 : }
1462 3770 : if (parent && parent->node && ((parent->node->sgprivate->tag==TAG_MPEG4_Script)
1463 : #ifndef GPAC_DISABLE_X3D
1464 1780 : || (parent->node->sgprivate->tag==TAG_X3D_Script)
1465 : #endif
1466 : ) ) {
1467 : is_script = 1;
1468 20 : if (!strcmp(name, "field")) {
1469 10 : xmt_parse_script_field(parser, parent->node, attributes, nb_attributes);
1470 : return NULL;
1471 : }
1472 10 : else if (!strcmp(name, "node") || !strcmp(name, "nodes") ) return NULL;
1473 : }
1474 :
1475 : /*proto declaration*/
1476 1975 : if (!strcmp(name, "ProtoDeclare") || !strcmp(name, "ExternProtoDeclare")) {
1477 15 : if (!parser->parsing_proto && parser->command && !parser->command->new_proto_list) parser->command->new_proto_list = gf_list_new();
1478 15 : xmt_parse_proto(parser, attributes, nb_attributes, (!parser->parsing_proto && parser->command) ? parser->command->new_proto_list : NULL);
1479 : return NULL;
1480 : }
1481 : /*proto parsing*/
1482 1960 : if (parser->parsing_proto) {
1483 315 : if (!strcmp(name, "IS"))
1484 : return NULL;
1485 :
1486 275 : if (!strcmp(name, "field")) {
1487 : char *fieldName = NULL;
1488 : char *value = NULL;
1489 : u32 fType, eType;
1490 : fType = eType = 0;
1491 :
1492 380 : for (i=0; i<nb_attributes; i++) {
1493 380 : GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
1494 380 : if (!att->value || !strlen(att->value)) continue;
1495 :
1496 380 : if (!strcmp(att->name, "name")) fieldName = att->value;
1497 280 : else if (!strcmp(att->name, "type")) fType = xmt_get_ft_by_name(att->value);
1498 180 : else if (!strcmp(att->name, "vrml97Hint") || !strcmp(att->name, "accessType") ) eType = xmt_get_et_by_name(att->value);
1499 80 : else if (strstr(att->name, "value") || strstr(att->name, "Value")) value = att->value;
1500 : }
1501 100 : parser->proto_field = gf_sg_proto_field_new(parser->parsing_proto, fType, eType, fieldName);
1502 100 : if (value && strlen(value)) {
1503 80 : gf_sg_proto_field_get_field(parser->proto_field, &info);
1504 80 : if (gf_sg_vrml_is_sf_field(fType)) {
1505 80 : xmt_parse_sf_field(parser, &info, NULL, value);
1506 : } else {
1507 0 : xmt_parse_mf_field(parser, &info, NULL, value);
1508 : }
1509 20 : } else if (gf_sg_vrml_get_sf_type(fType) != GF_SG_VRML_SFNODE) {
1510 : /*value not specified for exter proto*/
1511 : }
1512 : /*SF/MFNode proto field: push node stack with container info but no parent*/
1513 : else {
1514 : XMTNodeStack *pf_stack;
1515 10 : GF_SAFEALLOC(pf_stack, XMTNodeStack);
1516 10 : if (pf_stack) {
1517 10 : gf_sg_proto_field_get_field(parser->proto_field, &pf_stack->container_field);
1518 10 : gf_list_add(parser->nodes, pf_stack);
1519 : }
1520 : }
1521 : return NULL;
1522 : }
1523 :
1524 : /*X3D style*/
1525 175 : if (!strcmp(name, "ProtoInterface") || !strcmp(name, "ProtoBody"))
1526 : return NULL;
1527 : /*XMT1 decl for SFNode proto fields*/
1528 175 : if (parser->proto_field && (!strcmp(name, "node") || !strcmp(name, "nodes")) )
1529 : return NULL;
1530 : /*anim & QP info */
1531 165 : if (parser->proto_field && !strcmp(name, "InterfaceCodingParameters")) {
1532 : u32 qp_type, nbBits, hasMinMax, qp_sftype;
1533 : Fixed ftMin, ftMax;
1534 0 : ftMin = ftMax = 0;
1535 : qp_type = hasMinMax = nbBits = 0;
1536 0 : for (i=0; i<nb_attributes; i++) {
1537 0 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
1538 0 : if (!att->value || !strlen(att->value)) continue;
1539 0 : if (!strcmp(att->name, "quantCategory")) qp_type = xmt_get_protofield_qp_type(att->value);
1540 0 : else if (!strcmp(att->name, "nbBits")) nbBits = atoi(att->value);
1541 0 : else if (!strncmp(att->name, "position3DM", 11) || !strncmp(att->name, "position2DM", 11)
1542 0 : || !strncmp(att->name, "drawOrderM", 10) || !strncmp(att->name, "colorM", 6)
1543 0 : || !strncmp(att->name, "textureCoordinateM", 18) || !strncmp(att->name, "angleM", 6)
1544 0 : || !strncmp(att->name, "scaleM", 6) || !strncmp(att->name, "keyM", 4) || !strncmp(att->name, "sizeM", 5)
1545 : ) {
1546 : hasMinMax = 1;
1547 0 : if (strstr(att->name, "Min")) xmt_parse_float(parser, att->name, &ftMin, att->value);
1548 0 : else xmt_parse_float(parser, att->name, &ftMax, att->value);
1549 : }
1550 : }
1551 0 : if (gf_sg_vrml_get_sf_type(parser->proto_field->FieldType) == GF_SG_VRML_SFINT32) {
1552 : qp_sftype = GF_SG_VRML_SFINT32;
1553 : } else {
1554 : qp_sftype = GF_SG_VRML_SFFLOAT;
1555 : }
1556 0 : gf_bifs_proto_field_set_aq_info(parser->proto_field, qp_type, hasMinMax, qp_sftype, &ftMin, &ftMax, nbBits);
1557 : return NULL;
1558 : }
1559 : /*connect */
1560 165 : if (!strcmp(name, "connect")) {
1561 : GF_ProtoFieldInterface *pf;
1562 : GF_FieldInfo pfield, nfield;
1563 : char *atField, *atProtoField;
1564 55 : XMTNodeStack *last = (XMTNodeStack*)gf_list_last(parser->nodes);
1565 : is_script = 0;
1566 55 : if (!last) {
1567 0 : xmt_report(parser, GF_OK, "connect: no parent node specified - skipping");
1568 : return NULL;
1569 : }
1570 : atField = atProtoField = NULL;
1571 110 : for (i=0; i<nb_attributes; i++) {
1572 110 : GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
1573 110 : if (!att->value || !strlen(att->value)) continue;
1574 110 : if (!strcmp(att->name, "nodeField")) atField = att->value;
1575 55 : else if (!strcmp(att->name, "protoField")) atProtoField = att->value;
1576 : }
1577 55 : if (!atField) {
1578 0 : xmt_report(parser, GF_OK, "connect: Missing node field - skipping");
1579 : return NULL;
1580 : }
1581 55 : if (!atProtoField) {
1582 0 : xmt_report(parser, GF_OK, "connect: Missing proto field - skipping");
1583 : return NULL;
1584 : }
1585 55 : if ( (e = gf_node_get_field_by_name(last->node, atField, &nfield)) != GF_OK) {
1586 0 : u32 l_tag = gf_node_get_tag(last->node);
1587 0 : if ((l_tag!=TAG_MPEG4_Script)
1588 : #ifndef GPAC_DISABLE_X3D
1589 0 : && (l_tag!=TAG_X3D_Script)
1590 : #endif
1591 : ) {
1592 0 : xmt_report(parser, e, "connect: %s not an field of node %s", atField, gf_node_get_class_name(last->node) );
1593 : return NULL;
1594 : }
1595 : is_script = 1;
1596 : }
1597 55 : pf = gf_sg_proto_field_find_by_name(parser->parsing_proto, atProtoField);
1598 55 : if (!pf) {
1599 0 : xmt_report(parser, GF_BAD_PARAM, "connect: Proto field %s is not defined", atProtoField);
1600 : return NULL;
1601 : }
1602 55 : gf_sg_proto_field_get_field(pf, &pfield);
1603 55 : if (is_script) {
1604 0 : gf_sg_script_field_new(last->node, pfield.eventType, pfield.fieldType, atField);
1605 0 : gf_node_get_field_by_name(last->node, atField, &nfield);
1606 : }
1607 55 : e = gf_sg_proto_field_set_ised(parser->parsing_proto, pfield.fieldIndex, last->node, nfield.fieldIndex);
1608 55 : if (e) xmt_report(parser, GF_BAD_PARAM, "connect: %s", gf_error_to_string(e));
1609 : return NULL;
1610 : }
1611 : }
1612 : /*proto instance field*/
1613 1755 : if (!strcmp(name, "fieldValue")) {
1614 : char *field, *value;
1615 130 : if (!parent || !parent->node || (parent->node->sgprivate->tag != TAG_ProtoNode)) {
1616 0 : xmt_report(parser, GF_OK, "Warning: fieldValue not a valid node");
1617 : return NULL;
1618 : }
1619 : field = value = NULL;
1620 245 : for (i=0; i<nb_attributes; i++) {
1621 245 : GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
1622 245 : if (!att->value || !strlen(att->value)) continue;
1623 245 : if (!strcmp(att->name, "name")) field = att->value;
1624 115 : else if (!strstr(att->name, "Value") || !strstr(att->name, "value")) value = att->value;
1625 : }
1626 130 : if (!field) {
1627 0 : xmt_report(parser, GF_OK, "Warning: unspecified proto field name - skipping");
1628 : return NULL;
1629 : }
1630 130 : e = gf_node_get_field_by_name(parent->node, field, &info);
1631 130 : if (e) {
1632 0 : xmt_report(parser, GF_OK, "Warning: Unknown proto field %s - skipping", field);
1633 : return NULL;
1634 : }
1635 130 : if (value) {
1636 115 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
1637 115 : xmt_parse_sf_field(parser, &info, parent->node, value);
1638 : } else {
1639 0 : xmt_parse_mf_field(parser, &info, parent->node, value);
1640 : }
1641 115 : gf_sg_proto_mark_field_loaded(parent->node, &info);
1642 15 : } else if (gf_sg_vrml_get_sf_type(info.fieldType) == GF_SG_VRML_SFNODE) {
1643 15 : parent->container_field = info;
1644 15 : parent->last = NULL;
1645 : }
1646 : return NULL;
1647 : }
1648 1625 : if (parent && parent->node && (parent->node->sgprivate->tag == TAG_ProtoNode) && (!strcmp(name, "node") || !strcmp(name, "nodes")) ) {
1649 : return NULL;
1650 : }
1651 :
1652 : ID = 0;
1653 : def_name = NULL;
1654 : tag = 0;
1655 :
1656 1610 : if (!strcmp(name, "ProtoInstance")) {
1657 : char *proto_name = NULL;
1658 : char *proto_use = NULL;
1659 : node = NULL;
1660 25 : for (i=0; i<nb_attributes; i++) {
1661 25 : GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
1662 25 : if (!att->value || !strlen(att->value)) continue;
1663 25 : if (!strcmp(att->name, "name")) {
1664 : proto_name = att->value;
1665 20 : att->value = NULL;
1666 5 : } else if (!strcmp(att->name, "USE")) {
1667 : proto_use = att->value;
1668 : }
1669 : }
1670 20 : if (proto_use) {
1671 0 : node = xmt_find_node(parser, proto_use);
1672 : e = GF_OK;
1673 0 : if (!node)
1674 0 : e = xmt_report(parser, GF_BAD_PARAM, "Warning: Cannot find node %s referenced in USE - skipping", proto_use);
1675 :
1676 0 : if (e) return NULL;
1677 : ID = 0;
1678 : register_def = 0;
1679 : tag = 0;
1680 20 : } else if (proto_name) {
1681 20 : GF_SceneGraph *sg = parser->load->scene_graph;
1682 : while (1) {
1683 20 : proto = gf_sg_find_proto(sg, 0, proto_name);
1684 20 : if (proto) break;
1685 0 : sg = sg->parent_scene;
1686 0 : if (!sg) break;
1687 : }
1688 20 : if (!proto) {
1689 0 : xmt_report(parser, GF_BAD_PARAM, "%s: not a valid/supported proto", proto_name);
1690 : return NULL;
1691 : }
1692 20 : node = gf_sg_proto_create_instance(parser->load->scene_graph, proto);
1693 : }
1694 : } else {
1695 1590 : tag = xmt_get_node_tag(parser, name);
1696 :
1697 1590 : if (!tag) {
1698 : /*XMT-A weird syntax*/
1699 585 : if (parent) {
1700 580 : if (gf_node_get_field_by_name(parent->node, name, &parent->container_field)==GF_OK) {
1701 580 : parent->last = NULL;
1702 580 : if (parent->container_field.fieldType==GF_SG_VRML_SFCOMMANDBUFFER) {
1703 35 : parser->command_buffer = (SFCommandBuffer*)parent->container_field.far_ptr;
1704 : /*store command*/
1705 35 : parser->command_buffer->buffer = (unsigned char *)parser->command;
1706 35 : parser->state = XMT_STATE_COMMANDS;
1707 : }
1708 : return NULL;
1709 : }
1710 0 : if (!strcmp(name, "store") && (parent->container_field.fieldType==GF_SG_VRML_MFATTRREF)) {
1711 : GF_FieldInfo pinfo;
1712 : GF_Node *atNode = NULL;
1713 : char *fieldName = NULL;
1714 0 : for (i=0; i<nb_attributes; i++) {
1715 0 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
1716 0 : if (!att->value || !strlen(att->value)) continue;
1717 0 : if (!strcmp(att->name, "node")) {
1718 0 : atNode = xmt_find_node(parser, att->value);
1719 0 : if (!atNode) xmt_report(parser, GF_BAD_PARAM, "Cannot locate node %s", att->value);
1720 : }
1721 0 : if (!strcmp(att->name, "field")) fieldName = att->value;
1722 : }
1723 0 : if (!fieldName || !atNode) {
1724 0 : xmt_report(parser, GF_BAD_PARAM, "Node or field name missing in <store>");
1725 0 : } else if (gf_node_get_field_by_name(atNode, fieldName, &pinfo) != GF_OK) {
1726 0 : xmt_report(parser, GF_BAD_PARAM, "Field %s not a member of node %s", fieldName, gf_node_get_class_name(node) );
1727 : } else {
1728 : SFAttrRef *ptr;
1729 0 : gf_sg_vrml_mf_append(parent->container_field.far_ptr , GF_SG_VRML_MFATTRREF, (void **) &ptr);
1730 0 : ptr->node = atNode;
1731 0 : ptr->fieldIndex = pinfo.fieldIndex;
1732 : }
1733 : return NULL;
1734 : }
1735 0 : parent->container_field.far_ptr = NULL;
1736 : }
1737 5 : else if (parser->command && (parser->command->tag == GF_SG_MULTIPLE_REPLACE)) {
1738 5 : if (gf_node_get_field_by_name(parser->command->node, name, &container)==GF_OK) {
1739 5 : GF_CommandField *field = gf_sg_command_field_new(parser->command);
1740 5 : field->fieldIndex = container.fieldIndex;
1741 5 : field->fieldType = container.fieldType;
1742 : return NULL;
1743 : }
1744 : }
1745 0 : xmt_report(parser, GF_NON_COMPLIANT_BITSTREAM, "Warning: %s is not a valid node - skipping", name);
1746 : return NULL;
1747 : }
1748 1005 : node = gf_node_new(parser->load->scene_graph, tag);
1749 1005 : if (!node) {
1750 0 : xmt_report(parser, GF_SG_UNKNOWN_NODE, "Warning: %s is not a supported node - skipping", name);
1751 : return NULL;
1752 : }
1753 : }
1754 :
1755 1025 : parser->current_node_tag = tag;
1756 :
1757 1025 : if (parent) container = parent->container_field;
1758 : else {
1759 80 : container.far_ptr = NULL;
1760 80 : container.fieldIndex = 0;
1761 80 : container.fieldType = 0;
1762 : }
1763 :
1764 1095 : for (i=0; i<nb_attributes; i++) {
1765 1125 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
1766 1125 : if (!att->value || !strlen(att->value)) continue;
1767 :
1768 1105 : if (!strcmp(att->name, "DEF")) {
1769 260 : GF_Node *undef_node = gf_sg_find_node_by_name(parser->load->scene_graph, att->value);
1770 : register_def = 1;
1771 260 : if (undef_node) {
1772 10 : gf_list_del_item(parser->peeked_nodes, undef_node);
1773 : /*if we see twice a DEF N1 then force creation of a new node*/
1774 10 : if (xmt_has_been_def(parser, att->value)) {
1775 5 : ID = xmt_get_node_id(parser, att->value);
1776 5 : xmt_report(parser, GF_OK, "Warning: Node %s has been defined several times - IDs may get corrupted", att->value);
1777 : } else {
1778 5 : gf_node_register(node, NULL);
1779 5 : gf_node_unregister(node, NULL);
1780 : node = undef_node;
1781 : ID = 0;
1782 : }
1783 : } else {
1784 250 : ID = xmt_get_node_id(parser, att->value);
1785 :
1786 : }
1787 260 : def_name = att->value;
1788 : }
1789 : /*USE node*/
1790 845 : else if (!strcmp(att->name, "USE")) {
1791 : GF_Node *def_node;
1792 :
1793 30 : def_node = xmt_find_node(parser, att->value);
1794 :
1795 : e = GF_OK;
1796 30 : if (!def_node)
1797 0 : e = xmt_report(parser, GF_BAD_PARAM, "Warning: Cannot find node %s referenced in USE - skipping", att->value);
1798 30 : else if (tag != gf_node_get_tag(def_node)) {
1799 0 : xmt_report(parser, GF_OK, "Warning: Node type %s doesn't match type %s of node %s", gf_node_get_class_name(node), gf_node_get_class_name(def_node), att->value);
1800 : }
1801 :
1802 : /*DESTROY NODE*/
1803 30 : gf_node_register(node, NULL);
1804 30 : gf_node_unregister(node, NULL);
1805 :
1806 30 : if (e) return NULL;
1807 :
1808 : node = def_node;
1809 : ID = 0;
1810 : register_def = 0;
1811 : tag = 0;
1812 : break;
1813 : }
1814 : /*X3D stuff*/
1815 815 : else if (!strcmp(att->name, "containerField")) {
1816 0 : if (parent) {
1817 0 : if (gf_node_get_field_by_name(parent->node, att->value, &container) != GF_OK) {
1818 0 : xmt_report(parser, GF_BAD_PARAM, "Warning: Container field %s not member of node %s", att->value, name);
1819 0 : container.far_ptr = NULL;
1820 : }
1821 : }
1822 : }
1823 : /*ignored ones*/
1824 815 : else if (!strcmp(att->name, "bboxCenter") || !strcmp(att->name, "bboxSize")) {
1825 : }
1826 : /*all other fields*/
1827 : else {
1828 815 : e = gf_node_get_field_by_name(node, att->name, &info);
1829 815 : if (e) xmt_report(parser, GF_OK, "Warning: Unknown field \"%s\" for node %s - skipping", att->name, name);
1830 815 : else if (gf_sg_vrml_is_sf_field(info.fieldType)) {
1831 570 : xmt_parse_sf_field(parser, &info, node, att->value);
1832 : } else {
1833 245 : xmt_parse_mf_field(parser, &info, node, att->value);
1834 : }
1835 : }
1836 : }
1837 :
1838 1025 : if (!parser->parsing_proto) xmt_update_timenode(parser, node);
1839 :
1840 1025 : if (register_def) {
1841 260 : gf_node_register(node, NULL);
1842 260 : gf_list_add(parser->def_nodes, node);
1843 : }
1844 1025 : if (ID) gf_node_set_id(node, ID, def_name);
1845 :
1846 1025 : if (is_script) {
1847 5 : u32 last_field = gf_node_get_field_count(parent->node);
1848 5 : gf_node_get_field(parent->node, last_field-1, &container);
1849 : }
1850 :
1851 1025 : if (parent) {
1852 945 : if (!container.far_ptr) {
1853 0 : if (parser->doc_type==2) {
1854 0 : x3d_get_default_container(parent->node, node, &container);
1855 0 : parent->last = NULL;
1856 : }
1857 0 : if (!container.far_ptr) {
1858 0 : gf_node_get_field_by_name(parent->node, "children", &container);
1859 0 : parent->last = NULL;
1860 : }
1861 :
1862 : }
1863 945 : if (container.fieldType == GF_SG_VRML_SFNODE) {
1864 465 : if (* ((GF_Node **)container.far_ptr) ) gf_node_unregister(* ((GF_Node **)container.far_ptr) , parent->node);
1865 465 : * ((GF_Node **)container.far_ptr) = node;
1866 465 : gf_node_register(node, parent->node);
1867 465 : parent->container_field.far_ptr = NULL;
1868 465 : parent->last = NULL;
1869 480 : } else if (container.fieldType == GF_SG_VRML_MFNODE) {
1870 480 : gf_node_list_add_child_last( (GF_ChildNodeItem **)container.far_ptr, node, &parent->last);
1871 480 : gf_node_register(node, parent->node);
1872 : }
1873 : assert(parent->node);
1874 945 : gf_node_changed(parent->node, NULL);
1875 : }
1876 :
1877 1025 : if (!parser->parsing_proto && (tag || proto) )
1878 935 : gf_node_init(node);
1879 :
1880 : /*For Ivica: load proto as soon as found when in playback mode*/
1881 1025 : if ( (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) && proto && !parser->parsing_proto) {
1882 4 : parser->last_error = gf_sg_proto_load_code(node);
1883 : }
1884 : return node;
1885 : }
1886 :
1887 :
1888 260 : GF_Descriptor *xmt_parse_descriptor(GF_XMTParser *parser, char *name, const GF_XMLAttribute *attributes, u32 nb_attributes, GF_Descriptor *parent)
1889 : {
1890 : GF_Err e;
1891 : u32 i;
1892 : u32 fake_desc = 0;
1893 : GF_Descriptor *desc;
1894 : char *xmt_desc_name = NULL, *ocr_ref = NULL, *dep_ref = NULL;
1895 : u32 binaryID = 0;
1896 260 : u8 tag = gf_odf_get_tag_by_name(name);
1897 :
1898 260 : if (!tag) {
1899 140 : if (!parent) return NULL;
1900 130 : switch (parent->tag) {
1901 55 : case GF_ODF_IOD_TAG:
1902 : case GF_ODF_OD_TAG:
1903 55 : if (!strcmp(name, "Profiles")) fake_desc = 1;
1904 50 : else if (!strcmp(name, "Descr")) fake_desc = 1;
1905 25 : else if (!strcmp(name, "esDescr")) fake_desc = 1;
1906 0 : else if (!strcmp(name, "URL")) fake_desc = 1;
1907 : else return NULL;
1908 : break;
1909 40 : case GF_ODF_ESD_TAG:
1910 40 : if (!strcmp(name, "decConfigDescr")) fake_desc = 1;
1911 20 : else if (!strcmp(name, "slConfigDescr")) fake_desc = 1;
1912 : else return NULL;
1913 : break;
1914 15 : case GF_ODF_DCD_TAG:
1915 15 : if (!strcmp(name, "decSpecificInfo")) fake_desc = 1;
1916 : else return NULL;
1917 : break;
1918 0 : case GF_ODF_SLC_TAG:
1919 0 : if (!strcmp(name, "custom")) fake_desc = 1;
1920 : else return NULL;
1921 : break;
1922 10 : case GF_ODF_MUXINFO_TAG:
1923 10 : if (!strcmp(name, "MP4MuxHints")) fake_desc = 1;
1924 : else return NULL;
1925 : break;
1926 10 : case GF_ODF_BIFS_CFG_TAG:
1927 10 : if (!strcmp(name, "commandStream")) fake_desc = 1;
1928 5 : else if (!strcmp(name, "size")) fake_desc = 2;
1929 : else return NULL;
1930 : break;
1931 : default:
1932 : return NULL;
1933 : }
1934 120 : }
1935 : if (fake_desc) {
1936 : tag = parent->tag;
1937 : desc = parent;
1938 : } else {
1939 120 : desc = gf_odf_desc_new(tag);
1940 120 : if (!desc) return NULL;
1941 : }
1942 :
1943 460 : for (i=0; i<nb_attributes; i++) {
1944 210 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
1945 210 : if (!att->value || !strlen(att->value)) continue;
1946 265 : if (!strcmp(att->name, "binaryID")) binaryID = atoi(att->value);
1947 155 : else if (!stricmp(att->name, "objectDescriptorID")) xmt_desc_name = att->value;
1948 130 : else if (!strcmp(att->name, "ES_ID")) xmt_desc_name = att->value;
1949 100 : else if (!strcmp(att->name, "OCR_ES_ID")) ocr_ref = att->value;
1950 100 : else if (!strcmp(att->name, "dependsOn_ES_ID")) dep_ref = att->value;
1951 : else {
1952 100 : e = gf_odf_set_field(desc, att->name, att->value);
1953 100 : if (e) xmt_report(parser, e, "Warning: %s not a valid attribute for descriptor %s", att->name, name);
1954 : //store src path but do not concatenate, othewise we break BT<->XMT conversion ...
1955 100 : if ((desc->tag==GF_ODF_MUXINFO_TAG) && (!stricmp(att->name, "fileName") || !stricmp(att->name, "url"))) {
1956 : GF_MuxInfo *mux = (GF_MuxInfo *) desc;
1957 10 : if (!mux->src_url)
1958 10 : mux->src_url = gf_strdup(parser->load->src_url ? parser->load->src_url : parser->load->fileName);
1959 : }
1960 : }
1961 : }
1962 250 : if (binaryID || xmt_desc_name) {
1963 55 : if ((tag == GF_ODF_IOD_TAG) || (tag == GF_ODF_OD_TAG))
1964 25 : xmt_new_od_link(parser, (GF_ObjectDescriptor *)desc, xmt_desc_name, binaryID);
1965 30 : else if (tag == GF_ODF_ESD_TAG) {
1966 30 : xmt_new_esd_link(parser, (GF_ESD *) desc, xmt_desc_name, binaryID);
1967 :
1968 : /*set references once the esd link has been established*/
1969 30 : if (ocr_ref) xmt_set_depend_id(parser, (GF_ESD *) desc, ocr_ref, 1);
1970 30 : if (dep_ref) xmt_set_depend_id(parser, (GF_ESD *) desc, dep_ref, 0);
1971 : }
1972 : }
1973 :
1974 250 : if (fake_desc) {
1975 130 : if (fake_desc==2) {
1976 : GF_BIFSConfig *bcfg = (GF_BIFSConfig *)desc;
1977 5 : parser->load->ctx->scene_width = bcfg->pixelWidth;
1978 5 : parser->load->ctx->scene_height = bcfg->pixelHeight;
1979 5 : parser->load->ctx->is_pixel_metrics = bcfg->pixelMetrics;
1980 : }
1981 : return NULL;
1982 : }
1983 120 : if (parent) {
1984 95 : e = gf_odf_desc_add_desc(parent, desc);
1985 95 : if (e) {
1986 0 : xmt_report(parser, GF_OK, "Invalid child descriptor");
1987 0 : gf_odf_desc_del(desc);
1988 0 : return NULL;
1989 : }
1990 : /*finally check for scene manager streams (scene description, OD, ...)*/
1991 95 : if (parent->tag == GF_ODF_ESD_TAG) {
1992 : GF_ESD *esd = (GF_ESD *)parent;
1993 50 : if (esd->decoderConfig) {
1994 40 : switch (esd->decoderConfig->streamType) {
1995 20 : case GF_STREAM_SCENE:
1996 : case GF_STREAM_OD:
1997 20 : if (!esd->decoderConfig->objectTypeIndication) esd->decoderConfig->objectTypeIndication = 1;
1998 : /*watchout for default BIFS stream*/
1999 20 : if (parser->scene_es && !parser->base_scene_id && (esd->decoderConfig->streamType==GF_STREAM_SCENE)) {
2000 0 : parser->scene_es->ESID = parser->base_scene_id = esd->ESID;
2001 0 : parser->scene_es->timeScale = (esd->slConfig && esd->slConfig->timestampResolution) ? esd->slConfig->timestampResolution : 1000;
2002 : } else {
2003 : char *s_name;
2004 20 : GF_StreamContext *sc = gf_sm_stream_new(parser->load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication);
2005 : /*set default timescale for systems tracks (ignored for other)*/
2006 20 : if (sc) sc->timeScale = (esd->slConfig && esd->slConfig->timestampResolution) ? esd->slConfig->timestampResolution : 1000;
2007 20 : if (!parser->base_scene_id && (esd->decoderConfig->streamType==GF_STREAM_SCENE)) parser->base_scene_id = esd->ESID;
2008 15 : else if (!parser->base_od_id && (esd->decoderConfig->streamType==GF_STREAM_OD)) parser->base_od_id = esd->ESID;
2009 :
2010 20 : s_name = xmt_get_es_name(parser, esd->ESID);
2011 20 : if (sc && s_name && !sc->name) sc->name = gf_strdup(s_name);
2012 : }
2013 : break;
2014 : }
2015 : }
2016 : }
2017 : }
2018 : return desc;
2019 : }
2020 :
2021 390 : static void xmt_parse_command(GF_XMTParser *parser, const char *name, const GF_XMLAttribute *attributes, u32 nb_attributes)
2022 : {
2023 : GF_Err e;
2024 : GF_FieldInfo info;
2025 : GF_CommandField *field;
2026 : u32 i;
2027 390 : if (!strcmp(name, "Scene")) {
2028 15 : parser->state = XMT_STATE_ELEMENTS;
2029 385 : return;
2030 : }
2031 375 : if (!parser->in_com)
2032 5 : parser->stream_id = parser->load->force_es_id;
2033 :
2034 375 : if (!strcmp(name, "par")) {
2035 90 : parser->in_com = 1;
2036 180 : for (i=0; i<nb_attributes; i++) {
2037 90 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
2038 90 : if (!att->value || !strlen(att->value)) continue;
2039 180 : if (!strcmp(att->name, "begin")) parser->au_time = atof(att->value);
2040 0 : else if (!strcmp(att->name, "isRAP")) parser->au_is_rap = !strcmp(att->value, "yes") ? 1 : 0;
2041 0 : else if (!strcmp(att->name, "atES_ID")) {
2042 0 : parser->stream_id = xmt_locate_stream(parser, att->value);
2043 0 : if (!parser->stream_id) xmt_report(parser, GF_OK, "Warning: Cannot locate command's target stream %s", att->value);
2044 : }
2045 : }
2046 : return;
2047 : }
2048 : /*ROUTE insert/replace*/
2049 285 : if (!strcmp(name, "ROUTE")) {
2050 10 : if (!parser->command || ((parser->command->tag!=GF_SG_ROUTE_REPLACE) && (parser->command->tag!=GF_SG_ROUTE_INSERT))) {
2051 0 : xmt_report(parser, GF_BAD_PARAM, "ROUTE declared outside command scope");
2052 0 : return;
2053 : }
2054 10 : if (parser->command->tag==GF_SG_ROUTE_INSERT) {
2055 5 : xmt_parse_route(parser, attributes, nb_attributes, 1, parser->command);
2056 5 : gf_list_add(parser->inserted_routes, parser->command);
2057 : } else {
2058 5 : xmt_parse_route(parser, attributes, nb_attributes, 0, parser->command);
2059 5 : if (!parser->command->RouteID) {
2060 0 : parser->command->unresolved = 1;
2061 0 : if (gf_list_find(parser->unresolved_routes, parser->command)<0)
2062 0 : gf_list_add(parser->unresolved_routes, parser->command);
2063 : }
2064 : }
2065 : return;
2066 : }
2067 : /*multiple replace*/
2068 275 : if (!strcmp(name, "repField")) {
2069 : char *fieldName = NULL;
2070 : char *fieldValue = NULL;
2071 : assert(parser->command);
2072 15 : if (!parser->command->node) return;
2073 20 : for (i=0; i<nb_attributes; i++) {
2074 20 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
2075 20 : if (!att->value || !strlen(att->value)) continue;
2076 20 : if (!strcmp(att->name, "atField")) fieldName = att->value;
2077 10 : else if (!strcmp(att->name, "value")) fieldValue = att->value;
2078 : }
2079 15 : if (!fieldName) {
2080 5 : parser->state = XMT_STATE_ELEMENTS;
2081 5 : return;
2082 : }
2083 10 : e = gf_node_get_field_by_name(parser->command->node, fieldName, &info);
2084 10 : if (e) {
2085 0 : xmt_report(parser, GF_BAD_PARAM, "Warning: Field %s not a member of node %s ", fieldName, gf_node_get_class_name(parser->command->node) );
2086 0 : return;
2087 : }
2088 10 : if (gf_sg_vrml_get_sf_type(info.fieldType) == GF_SG_VRML_SFNODE) {
2089 0 : parser->state = XMT_STATE_ELEMENTS;
2090 0 : return;
2091 : }
2092 10 : if (!fieldValue) return;
2093 :
2094 10 : field = gf_sg_command_field_new(parser->command);
2095 10 : field->fieldIndex = info.fieldIndex;
2096 10 : field->fieldType = info.fieldType;
2097 10 : field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
2098 10 : info.far_ptr = field->field_ptr;
2099 10 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2100 10 : xmt_parse_sf_field(parser, &info, parser->command->node, fieldValue);
2101 : } else {
2102 0 : xmt_parse_mf_field(parser, &info, parser->command->node, fieldValue);
2103 : }
2104 : return;
2105 : }
2106 : /*multiple index replace*/
2107 260 : if (!strcmp(name, "repValue")) {
2108 : s32 position = -1;
2109 : char *fieldValue = NULL;
2110 : assert(parser->command);
2111 15 : if (!parser->command->node) return;
2112 30 : for (i=0; i<nb_attributes; i++) {
2113 30 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
2114 30 : if (!att->value || !strlen(att->value)) continue;
2115 30 : if (!strcmp(att->name, "position")) {
2116 15 : if (!strcmp(att->value, "BEGIN")) position = 0;
2117 15 : else if (!strcmp(att->value, "END")) position = -1;
2118 : else position = atoi(att->value);
2119 : }
2120 15 : else if (!strcmp(att->name, "value")) fieldValue = att->value;
2121 : }
2122 15 : gf_node_get_field(parser->command->node, parser->command->fromFieldIndex, &info);
2123 15 : if (info.fieldType == GF_SG_VRML_MFNODE) {
2124 0 : field = gf_sg_command_field_new(parser->command);
2125 0 : field->fieldIndex = info.fieldIndex;
2126 0 : field->fieldType = GF_SG_VRML_SFNODE;
2127 0 : field->pos = position;
2128 0 : parser->state = XMT_STATE_ELEMENTS;
2129 15 : } else if (fieldValue) {
2130 15 : field = gf_sg_command_field_new(parser->command);
2131 15 : field->fieldIndex = info.fieldIndex;
2132 15 : field->fieldType = info.fieldType = gf_sg_vrml_get_sf_type(info.fieldType);
2133 15 : field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
2134 15 : field->pos = position;
2135 15 : info.far_ptr = field->field_ptr;
2136 15 : xmt_parse_sf_field(parser, &info, parser->command->node, fieldValue);
2137 : }
2138 : return;
2139 : }
2140 :
2141 :
2142 : /*BIFS command*/
2143 245 : if (!strcmp(name, "Replace") || !strcmp(name, "Insert") || !strcmp(name, "Delete")) {
2144 : GF_Node *atNode;
2145 : u8 tag = GF_SG_UNDEFINED;
2146 : u32 stream_id;
2147 225 : Double au_time = parser->au_time;
2148 225 : Bool au_is_rap = parser->au_is_rap;
2149 : char *nodeName = NULL;
2150 : char *fieldName = NULL;
2151 : char *fieldValue = NULL;
2152 : char *routeName = NULL;
2153 : char *extended = NULL;
2154 : char *idxNode = NULL;
2155 : char *idxField = NULL;
2156 : char *childField = NULL;
2157 : char *fromNode = NULL;
2158 : char *fromField = NULL;
2159 :
2160 : s32 position = -2;
2161 :
2162 225 : if (!parser->stream_id) parser->stream_id = parser->base_scene_id;
2163 225 : stream_id = parser->stream_id;
2164 :
2165 720 : for (i=0; i<nb_attributes; i++) {
2166 495 : GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
2167 495 : if (!att->value || !strlen(att->value)) continue;
2168 495 : if (!strcmp(att->name, "begin")) au_time = atoi(att->value);
2169 495 : else if (!strcmp(att->name, "isRAP")) au_is_rap = !strcmp(att->value, "yes") ? 1 : 0;
2170 495 : else if (!strcmp(att->name, "atES_ID")) {
2171 0 : stream_id = xmt_locate_stream(parser, att->value);
2172 0 : if (!stream_id) {
2173 0 : xmt_report(parser, GF_OK, "Warning: Cannot locate command's target stream %s", att->value);
2174 0 : stream_id = parser->stream_id;
2175 : }
2176 : }
2177 495 : else if (!strcmp(att->name, "atNode")) nodeName = att->value;
2178 320 : else if (!strcmp(att->name, "atField")) fieldName = att->value;
2179 210 : else if (!strcmp(att->name, "value")) fieldValue = att->value;
2180 120 : else if (!strcmp(att->name, "atRoute")) routeName = att->value;
2181 110 : else if (!strcmp(att->name, "extended")) extended = att->value;
2182 75 : else if (!strcmp(att->name, "atIndexNode")) idxNode = att->value;
2183 70 : else if (!strcmp(att->name, "atIndexField")) idxField = att->value;
2184 65 : else if (!strcmp(att->name, "atChildField")) childField = att->value;
2185 60 : else if (!strcmp(att->name, "fromNode")) fromNode = att->value;
2186 55 : else if (!strcmp(att->name, "fromField")) fromField = att->value;
2187 50 : else if (!strcmp(att->name, "position")) {
2188 50 : if (!strcmp(att->value, "BEGIN")) position = 0;
2189 20 : else if (!strcmp(att->value, "END")) position = -1;
2190 : else position = atoi(att->value);
2191 : }
2192 : }
2193 :
2194 : /*if we are parsing in an already loaded context and no time is given, force a time != 0 to create a new command*/
2195 225 : if (!au_time && (parser->load->flags&GF_SM_LOAD_CONTEXT_READY))
2196 : au_time = 0.001;
2197 :
2198 : atNode = NULL;
2199 225 : if (nodeName) {
2200 175 : if (fieldName) {
2201 110 : if (position>-2) {
2202 25 : if (!strcmp(name, "Replace")) tag = GF_SG_INDEXED_REPLACE;
2203 10 : else if (!strcmp(name, "Insert")) tag = GF_SG_INDEXED_INSERT;
2204 5 : else if (!strcmp(name, "Delete")) tag = GF_SG_INDEXED_DELETE;
2205 : } else {
2206 85 : if (!strcmp(name, "Replace")) {
2207 85 : if ((idxNode && idxField) || childField || (fromNode && fromField)) {
2208 : tag = GF_SG_XREPLACE;
2209 : } else {
2210 : tag = GF_SG_FIELD_REPLACE;
2211 : }
2212 : }
2213 : }
2214 : } else {
2215 65 : if (!strcmp(name, "Replace")) {
2216 : tag = GF_SG_NODE_REPLACE;
2217 30 : parser->state = XMT_STATE_ELEMENTS;
2218 : }
2219 35 : else if (!strcmp(name, "Insert")) {
2220 : tag = GF_SG_NODE_INSERT;
2221 25 : parser->state = XMT_STATE_ELEMENTS;
2222 : }
2223 10 : else if (!strcmp(name, "Delete")) tag = GF_SG_NODE_DELETE;
2224 : }
2225 :
2226 175 : atNode = xmt_find_node(parser, nodeName);
2227 175 : if (!atNode) {
2228 0 : xmt_report(parser, GF_BAD_PARAM, "Warning: Cannot locate node %s for command %s", nodeName, name);
2229 0 : return;
2230 : }
2231 175 : if (fieldName) {
2232 110 : e = gf_node_get_field_by_name(atNode, fieldName, &info);
2233 110 : if (e) {
2234 0 : xmt_report(parser, GF_BAD_PARAM, "Warning: Field %s not a member of node %s ", fieldName, nodeName);
2235 0 : return;
2236 : }
2237 : }
2238 : }
2239 50 : else if (routeName) {
2240 10 : if (!strcmp(name, "Replace")) tag = GF_SG_ROUTE_REPLACE;
2241 5 : else if (!strcmp(name, "Delete")) tag = GF_SG_ROUTE_DELETE;
2242 : }
2243 40 : else if (!strcmp(name, "Replace")) {
2244 : tag = GF_SG_SCENE_REPLACE;
2245 : au_is_rap = 1;
2246 280 : while (gf_list_count(parser->def_nodes)) {
2247 260 : GF_Node *anode = gf_list_pop_back(parser->def_nodes);
2248 260 : gf_node_unregister(anode, NULL);
2249 : }
2250 : }
2251 20 : else if (!strcmp(name, "Insert"))
2252 : tag = GF_SG_ROUTE_INSERT;
2253 :
2254 225 : if (extended) {
2255 35 : if (!strcmp(extended, "globalQuant")) {
2256 : tag = GF_SG_GLOBAL_QUANTIZER;
2257 5 : parser->state = XMT_STATE_ELEMENTS;
2258 : }
2259 30 : else if (!strcmp(extended, "fields")) {
2260 : tag = GF_SG_MULTIPLE_REPLACE;
2261 5 : parser->state = XMT_STATE_COMMANDS;
2262 : }
2263 25 : else if (!strcmp(extended, "indices")) {
2264 : tag = GF_SG_MULTIPLE_INDEXED_REPLACE;
2265 5 : parser->state = XMT_STATE_COMMANDS;
2266 : }
2267 20 : else if (!strcmp(extended, "deleteOrder")) tag = GF_SG_NODE_DELETE_EX;
2268 15 : else if (!strcmp(extended, "allProtos")) tag = GF_SG_PROTO_DELETE_ALL;
2269 10 : else if (!strcmp(extended, "proto") || !strcmp(extended, "protos")) {
2270 10 : if (!strcmp(name, "Insert")) {
2271 5 : parser->state = XMT_STATE_ELEMENTS;
2272 : tag = GF_SG_PROTO_INSERT;
2273 : }
2274 5 : else if (!strcmp(name, "Delete")) tag = GF_SG_PROTO_DELETE;
2275 : }
2276 : else {
2277 0 : xmt_report(parser, GF_BAD_PARAM, "Warning: Unknown extended command %s", extended);
2278 0 : return;
2279 : }
2280 :
2281 : }
2282 :
2283 190 : if (tag == GF_SG_UNDEFINED) {
2284 0 : xmt_report(parser, GF_BAD_PARAM, "Warning: Unknown scene command %s", name);
2285 0 : return;
2286 : }
2287 :
2288 225 : parser->command = gf_sg_command_new(parser->load->scene_graph, tag);
2289 225 : if (parser->command_buffer) {
2290 65 : gf_list_add(parser->command_buffer->commandList, parser->command);
2291 65 : parser->command_buffer->bufferSize++;
2292 : } else {
2293 160 : GF_StreamContext *stream = gf_sm_stream_find(parser->load->ctx, (u16) stream_id);
2294 160 : if (!stream || (stream->streamType!=GF_STREAM_SCENE)) stream_id = parser->base_scene_id;
2295 :
2296 160 : parser->scene_es = gf_sm_stream_new(parser->load->ctx, (u16) stream_id, GF_STREAM_SCENE, GF_CODECID_BIFS);
2297 160 : parser->scene_au = gf_sm_stream_au_new(parser->scene_es, 0, au_time, au_is_rap);
2298 160 : gf_list_add(parser->scene_au->commands, parser->command);
2299 : }
2300 :
2301 225 : if (atNode) {
2302 175 : parser->command->node = atNode;
2303 175 : gf_node_register(atNode, NULL);
2304 175 : if (tag == GF_SG_MULTIPLE_INDEXED_REPLACE) {
2305 5 : parser->command->fromFieldIndex = info.fieldIndex;
2306 5 : return;
2307 : }
2308 170 : if (fieldName) {
2309 105 : field = gf_sg_command_field_new(parser->command);
2310 105 : field->fieldIndex = info.fieldIndex;
2311 :
2312 105 : if (idxNode && idxField) {
2313 5 : GF_Node *iNode = xmt_find_node(parser, idxNode);
2314 5 : if (iNode) {
2315 : GF_FieldInfo idxF;
2316 5 : parser->command->toNodeID = gf_node_get_id(iNode);
2317 5 : gf_node_get_field_by_name(iNode, idxField, &idxF);
2318 5 : parser->command->toFieldIndex = idxF.fieldIndex;
2319 : position = 0;
2320 5 : switch (idxF.fieldType) {
2321 0 : case GF_SG_VRML_SFBOOL:
2322 0 : if (*(SFBool*)idxF.far_ptr) position = 1;
2323 : break;
2324 5 : case GF_SG_VRML_SFINT32:
2325 5 : if (*(SFInt32*)idxF.far_ptr >=0) position = *(SFInt32*)idxF.far_ptr;
2326 : break;
2327 0 : case GF_SG_VRML_SFFLOAT:
2328 0 : if ( (*(SFFloat *)idxF.far_ptr) >=0) position = (s32) floor( FIX2FLT(*(SFFloat*)idxF.far_ptr) );
2329 : break;
2330 0 : case GF_SG_VRML_SFTIME:
2331 0 : if ( (*(SFTime *)idxF.far_ptr) >=0) position = (s32) floor( (*(SFTime *)idxF.far_ptr) );
2332 : break;
2333 : }
2334 : }
2335 : }
2336 105 : if (childField) {
2337 5 : GF_Node *child = gf_node_list_get_child( ((GF_ParentNode*)atNode)->children, position);
2338 5 : if (child) {
2339 5 : parser->command->ChildNodeTag = gf_node_get_tag(child);
2340 5 : if (parser->command->ChildNodeTag == TAG_ProtoNode) {
2341 0 : s32 p_id = gf_sg_proto_get_id(gf_node_get_proto(child));
2342 0 : parser->command->ChildNodeTag = -p_id;
2343 : }
2344 : /*get field in the info struct for later parsing*/
2345 5 : gf_node_get_field_by_name(child, childField, &info);
2346 5 : parser->command->child_field = info.fieldIndex;
2347 : }
2348 : }
2349 : /*do not keep position info if index node is used*/
2350 105 : if (idxNode && idxField) position = -2;
2351 :
2352 105 : if (fromNode && fromField) {
2353 5 : GF_Node *fNode = xmt_find_node(parser, fromNode);
2354 5 : if (fNode) {
2355 : GF_FieldInfo fField;
2356 5 : parser->command->fromNodeID = gf_node_get_id(fNode);
2357 5 : gf_node_get_field_by_name(fNode, fromField, &fField);
2358 5 : parser->command->fromFieldIndex = fField.fieldIndex;
2359 : }
2360 : }
2361 105 : if (!fromNode && !fromField) {
2362 100 : if (gf_sg_vrml_get_sf_type(info.fieldType) != GF_SG_VRML_SFNODE) {
2363 90 : if (position==-2) {
2364 75 : field->fieldType = info.fieldType;
2365 75 : field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
2366 75 : info.far_ptr = field->field_ptr;
2367 75 : if (gf_sg_vrml_is_sf_field(info.fieldType)) {
2368 75 : xmt_parse_sf_field(parser, &info, atNode, fieldValue);
2369 : } else {
2370 0 : xmt_parse_mf_field(parser, &info, atNode, fieldValue);
2371 : }
2372 : } else {
2373 15 : field->fieldType = info.fieldType = gf_sg_vrml_get_sf_type(info.fieldType);
2374 15 : field->pos = position;
2375 15 : if (tag != GF_SG_INDEXED_DELETE) {
2376 10 : field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
2377 10 : info.far_ptr = field->field_ptr;
2378 10 : xmt_parse_sf_field(parser, &info, atNode, fieldValue);
2379 : }
2380 : }
2381 : } else {
2382 10 : field->pos = position;
2383 10 : if ((position==-2) && (info.fieldType==GF_SG_VRML_MFNODE)) {
2384 0 : field->fieldType = GF_SG_VRML_MFNODE;
2385 : } else {
2386 10 : field->fieldType = GF_SG_VRML_SFNODE;
2387 : }
2388 10 : parser->state = XMT_STATE_ELEMENTS;
2389 : }
2390 : }
2391 65 : } else if (tag==GF_SG_NODE_INSERT) {
2392 25 : field = gf_sg_command_field_new(parser->command);
2393 25 : field->fieldType = GF_SG_VRML_SFNODE;
2394 25 : field->pos = position;
2395 25 : parser->state = XMT_STATE_ELEMENTS;
2396 : }
2397 : }
2398 50 : else if (routeName) {
2399 10 : u32 rID = xmt_get_route(parser, routeName, 0);
2400 10 : if (!rID) {
2401 0 : parser->command->unres_name = gf_strdup(routeName);
2402 0 : parser->command->unresolved = 1;
2403 0 : gf_list_add(parser->unresolved_routes, parser->command);
2404 : } else {
2405 10 : parser->command->RouteID = rID;
2406 : /*for bt<->xmt conversions*/
2407 10 : parser->command->def_name = gf_strdup(routeName);
2408 : }
2409 : }
2410 40 : else if (tag == GF_SG_PROTO_DELETE) {
2411 : char *sep;
2412 5 : while (fieldValue) {
2413 : GF_Proto *p;
2414 5 : sep = strchr(fieldValue, ' ');
2415 5 : if (sep) sep[0] = 0;
2416 5 : p = gf_sg_find_proto(parser->load->scene_graph, 0, fieldValue);
2417 10 : if (!p) p = gf_sg_find_proto(parser->load->scene_graph, atoi(fieldValue), NULL);
2418 :
2419 5 : if (!p) xmt_report(parser, GF_OK, "Warning: Cannot locate proto %s - skipping", fieldValue);
2420 : else {
2421 5 : parser->command->del_proto_list = (u32*)gf_realloc(parser->command->del_proto_list, sizeof(u32) * (parser->command->del_proto_list_size+1));
2422 5 : parser->command->del_proto_list[parser->command->del_proto_list_size] = p->ID;
2423 5 : parser->command->del_proto_list_size++;
2424 : }
2425 5 : if (!sep) break;
2426 0 : sep[0] = ' ';
2427 0 : fieldValue = sep+1;
2428 : }
2429 : }
2430 :
2431 : return;
2432 : }
2433 :
2434 : /*OD commands*/
2435 20 : if (!strcmp(name, "ObjectDescriptorUpdate") || !strcmp(name, "ObjectDescriptorRemove")
2436 5 : || !strcmp(name, "ES_DescriptorUpdate") || !strcmp(name, "ES_DescriptorRemove")
2437 0 : || !strcmp(name, "IPMP_DescriptorUpdate") || !strcmp(name, "IPMP_DescriptorRemove") ) {
2438 : u32 stream_id;
2439 : u8 tag = 0;
2440 : GF_StreamContext *stream;
2441 : char *od_ids = NULL;
2442 : char *es_ids = NULL;
2443 20 : Double au_time = parser->au_time;
2444 20 : Bool au_is_rap = parser->au_is_rap;
2445 :
2446 20 : if (!parser->stream_id) parser->stream_id = parser->base_od_id;
2447 20 : stream_id = parser->stream_id;
2448 :
2449 35 : for (i=0; i<nb_attributes; i++) {
2450 15 : GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
2451 15 : if (!att->value || !strlen(att->value)) continue;
2452 15 : if (!strcmp(att->name, "begin")) au_time = atoi(att->value);
2453 15 : else if (!strcmp(att->name, "isRAP")) au_is_rap = !strcmp(att->value, "yes") ? 1 : 0;
2454 15 : else if (!stricmp(att->name, "objectDescriptorId")) od_ids = att->value;
2455 5 : else if (!strcmp(att->name, "ES_ID")) es_ids = att->value;
2456 : }
2457 :
2458 : /*if we are parsing in an already loaded context and no time is given, force a time != 0 to create a new command*/
2459 20 : if (!au_time && (parser->load->flags&GF_SM_LOAD_CONTEXT_READY))
2460 : au_time = 0.001;
2461 :
2462 20 : if (!strcmp(name, "ObjectDescriptorUpdate")) tag = GF_ODF_OD_UPDATE_TAG;
2463 10 : else if (!strcmp(name, "ES_DescriptorUpdate")) tag = GF_ODF_ESD_UPDATE_TAG;
2464 10 : else if (!strcmp(name, "IPMP_DescriptorUpdate")) tag = GF_ODF_IPMP_UPDATE_TAG;
2465 10 : else if (!strcmp(name, "ObjectDescriptorRemove")) {
2466 5 : if (!od_ids) return;
2467 : tag = GF_ODF_OD_REMOVE_TAG;
2468 : }
2469 5 : else if (!strcmp(name, "ES_DescriptorRemove")) {
2470 5 : if (!od_ids || !es_ids) return;
2471 : tag = GF_ODF_ESD_REMOVE_TAG;
2472 : }
2473 0 : else if (!strcmp(name, "IPMP_DescriptorRemove")) tag = GF_ODF_IPMP_REMOVE_TAG;
2474 :
2475 20 : stream = gf_sm_stream_find(parser->load->ctx, (u16) stream_id);
2476 20 : if (stream && (stream->streamType!=GF_STREAM_OD)) stream_id = parser->base_od_id;
2477 20 : parser->od_es = gf_sm_stream_new(parser->load->ctx, (u16) stream_id, GF_STREAM_OD, GF_CODECID_OD_V1);
2478 20 : parser->od_au = gf_sm_stream_au_new(parser->od_es, 0, au_time, au_is_rap);
2479 20 : parser->od_command = gf_odf_com_new(tag);
2480 20 : gf_list_add(parser->od_au->commands, parser->od_command);
2481 :
2482 20 : if (tag == GF_ODF_ESD_REMOVE_TAG) {
2483 : char *sep;
2484 5 : GF_ESDRemove *esdR = (GF_ESDRemove *) parser->od_command ;
2485 5 : esdR->ODID = xmt_get_od_id(parser, od_ids);
2486 10 : while (es_ids) {
2487 : u32 es_id;
2488 5 : sep = strchr(es_ids, ' ');
2489 5 : if (sep) sep[0] = 0;
2490 5 : es_id = xmt_get_esd_id(parser, es_ids);
2491 5 : if (!es_id) xmt_report(parser, GF_OK, "Warning: Cannot find ES Descriptor %s - skipping", es_ids);
2492 : else {
2493 5 : esdR->ES_ID = (u16*)gf_realloc(esdR->ES_ID, sizeof(u16) * (esdR->NbESDs+1));
2494 5 : esdR->ES_ID[esdR->NbESDs] = es_id;
2495 5 : esdR->NbESDs++;
2496 : }
2497 5 : if (!sep) break;
2498 0 : sep[0] = ' ';
2499 0 : es_ids = sep+1;
2500 : }
2501 : }
2502 15 : else if (tag == GF_ODF_OD_REMOVE_TAG) {
2503 : char *sep;
2504 5 : GF_ODRemove *odR = (GF_ODRemove *) parser->od_command ;
2505 10 : while (od_ids) {
2506 : u32 od_id;
2507 5 : sep = strchr(od_ids, ' ');
2508 5 : if (sep) sep[0] = 0;
2509 5 : od_id = xmt_get_od_id(parser, od_ids);
2510 5 : if (!od_id) xmt_report(parser, GF_OK, "Warning: Cannot find Object Descriptor %s - skipping", od_ids);
2511 : else {
2512 5 : odR->OD_ID = (u16*)gf_realloc(odR->OD_ID, sizeof(u16) * (odR->NbODs+1));
2513 5 : odR->OD_ID[odR->NbODs] = od_id;
2514 5 : odR->NbODs++;
2515 : }
2516 5 : if (!sep) break;
2517 0 : sep[0] = ' ';
2518 0 : od_ids = sep+1;
2519 : }
2520 : }
2521 : }
2522 : }
2523 :
2524 2685 : static void xmt_node_start(void *sax_cbck, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes)
2525 : {
2526 : GF_Node *elt;
2527 : XMTNodeStack *top, *new_top;
2528 : GF_XMTParser *parser = (GF_XMTParser *)sax_cbck;
2529 :
2530 2685 : if (parser->last_error) {
2531 0 : gf_xml_sax_suspend(parser->sax_parser, 1);
2532 0 : if (parser->command_buffer)
2533 0 : parser->command_buffer->buffer = NULL;
2534 : return;
2535 : }
2536 :
2537 : /*init doc type*/
2538 2685 : if (!parser->doc_type) {
2539 5 : if (!strcmp(name, "XMT-A")) parser->doc_type = 1;
2540 0 : else if (!strcmp(name, "X3D")) {
2541 0 : parser->doc_type = 2;
2542 0 : parser->script_to_load = gf_list_new();
2543 : }
2544 0 : else if (!strcmp(name, "XMT-O")) parser->doc_type = 3;
2545 : return;
2546 : }
2547 :
2548 : /*init doc state with already loaded context (for chunk encoding)*/
2549 2680 : if ((parser->state == XMT_STATE_INIT) && (parser->load->flags & GF_SM_LOAD_CONTEXT_READY) && (parser->doc_type == 1)) {
2550 0 : parser->state = XMT_STATE_COMMANDS;
2551 : }
2552 : /*init doc state for regular parsing*/
2553 2680 : else if (parser->state == XMT_STATE_INIT) {
2554 : /*XMT-A header*/
2555 5 : if ((parser->doc_type == 1) && !strcmp(name, "Header")) parser->state = XMT_STATE_HEAD;
2556 : /*X3D header*/
2557 0 : else if ((parser->doc_type == 2) && !strcmp(name, "head")) parser->state = XMT_STATE_HEAD;
2558 : /*XMT-O header*/
2559 0 : else if ((parser->doc_type == 3) && !strcmp(name, "head")) parser->state = XMT_STATE_HEAD;
2560 :
2561 : return;
2562 : }
2563 :
2564 : /*XMT-A header: parse OD/IOD*/
2565 2675 : if ((parser->doc_type == 1) && (parser->state == XMT_STATE_HEAD)) {
2566 : GF_Descriptor *desc, *par;
2567 90 : par = (GF_Descriptor *)gf_list_last(parser->descriptors);
2568 90 : desc = xmt_parse_descriptor(parser, (char *) name, attributes, nb_attributes, par);
2569 90 : if (desc) gf_list_add(parser->descriptors, desc);
2570 : return;
2571 : }
2572 2585 : if (parser->state==XMT_STATE_END) {
2573 0 : if (!strcmp(name, "head")) {
2574 0 : parser->state = XMT_STATE_HEAD;
2575 : } else {
2576 0 : parser->state = XMT_STATE_COMMANDS;
2577 : }
2578 : }
2579 :
2580 : /*scene content*/
2581 2585 : if (parser->state==XMT_STATE_BODY) {
2582 : /*XMT-A body*/
2583 5 : if ((parser->doc_type == 1) && !strcmp(name, "Body")) parser->state = XMT_STATE_COMMANDS;
2584 : /*X3D scene*/
2585 0 : else if ((parser->doc_type == 2) && !strcmp(name, "Scene")) {
2586 0 : parser->state = XMT_STATE_ELEMENTS;
2587 0 : if (parser->load->ctx) {
2588 0 : parser->load->ctx->is_pixel_metrics = 0;
2589 0 : parser->load->ctx->scene_width = parser->load->ctx->scene_height = 0;
2590 : }
2591 0 : gf_sg_set_scene_size_info(parser->load->scene_graph, 0, 0, 0);
2592 : }
2593 : /*XMT-O body*/
2594 0 : else if ((parser->doc_type == 3) && !strcmp(name, "body")) parser->state = XMT_STATE_COMMANDS;
2595 : return;
2596 : }
2597 : /*XMT-A command*/
2598 2580 : if ((parser->doc_type == 1) && (parser->state == XMT_STATE_COMMANDS)) {
2599 : /*OD command*/
2600 560 : if (parser->od_command) {
2601 : GF_Descriptor *desc, *par;
2602 170 : par = (GF_Descriptor *)gf_list_last(parser->descriptors);
2603 170 : desc = xmt_parse_descriptor(parser, (char *) name, attributes, nb_attributes, par);
2604 170 : if (desc) gf_list_add(parser->descriptors, desc);
2605 : } else {
2606 390 : xmt_parse_command(parser, name, attributes, nb_attributes);
2607 : }
2608 : return;
2609 : }
2610 :
2611 :
2612 : /*node*/
2613 2020 : if (parser->state != XMT_STATE_ELEMENTS) return;
2614 :
2615 2020 : top = (XMTNodeStack*)gf_list_last(parser->nodes);
2616 2020 : if (!top) top = parser->x3d_root;
2617 :
2618 2020 : elt = xmt_parse_element(parser, (char *) name, name_space, attributes, nb_attributes, top);
2619 2020 : if (!elt) return;
2620 1025 : GF_SAFEALLOC(new_top, XMTNodeStack);
2621 1025 : if (!new_top) return;
2622 :
2623 1025 : new_top->node = elt;
2624 1025 : gf_list_add(parser->nodes, new_top);
2625 :
2626 : /*assign root node here to enable progressive loading*/
2627 1025 : if (!top && (parser->doc_type == 1) && !parser->parsing_proto && parser->command && (parser->command->tag==GF_SG_SCENE_REPLACE) && !parser->command->node) {
2628 10 : parser->command->node = elt;
2629 10 : gf_node_register(elt, NULL);
2630 : }
2631 : }
2632 :
2633 2675 : static void xmt_node_end(void *sax_cbck, const char *name, const char *name_space)
2634 : {
2635 : u32 tag;
2636 : GF_XMTParser *parser = (GF_XMTParser *)sax_cbck;
2637 : XMTNodeStack *top;
2638 : GF_Descriptor *desc;
2639 : GF_Node *node = NULL;
2640 2675 : if (!parser->doc_type || !parser->state) return;
2641 :
2642 2675 : top = (XMTNodeStack *)gf_list_last(parser->nodes);
2643 :
2644 2675 : if (!top) {
2645 : /*check descr*/
2646 740 : desc = (GF_Descriptor*)gf_list_last(parser->descriptors);
2647 740 : if (desc && (desc->tag == gf_odf_get_tag_by_name((char *)name)) ) {
2648 :
2649 : /*assign timescales once the ESD has been parsed*/
2650 120 : if (desc->tag == GF_ODF_ESD_TAG) {
2651 : GF_ESD *esd = (GF_ESD*)desc;
2652 30 : GF_StreamContext *sc = gf_sm_stream_new(parser->load->ctx, esd->ESID, esd->decoderConfig ? esd->decoderConfig->streamType : 0, esd->decoderConfig ? esd->decoderConfig->objectTypeIndication : 0);
2653 30 : if (sc && esd->slConfig && esd->slConfig->timestampResolution)
2654 0 : sc->timeScale = esd->slConfig->timestampResolution;
2655 : }
2656 :
2657 120 : gf_list_rem_last(parser->descriptors);
2658 120 : if (gf_list_count(parser->descriptors)) return;
2659 :
2660 25 : if ((parser->doc_type==1) && (parser->state==XMT_STATE_HEAD) && parser->load->ctx && !parser->load->ctx->root_od) {
2661 5 : parser->load->ctx->root_od = (GF_ObjectDescriptor *)desc;
2662 : }
2663 20 : else if (!parser->od_command) {
2664 0 : xmt_report(parser, GF_OK, "Warning: descriptor %s defined outside scene scope - skipping", name);
2665 0 : gf_odf_desc_del(desc);
2666 : } else {
2667 20 : switch (parser->od_command->tag) {
2668 0 : case GF_ODF_ESD_UPDATE_TAG:
2669 0 : gf_list_add( ((GF_ESDUpdate *)parser->od_command)->ESDescriptors, desc);
2670 0 : break;
2671 : /*same struct for OD update and IPMP update*/
2672 20 : case GF_ODF_OD_UPDATE_TAG:
2673 : case GF_ODF_IPMP_UPDATE_TAG:
2674 20 : gf_list_add( ((GF_ODUpdate *)parser->od_command)->objectDescriptors, desc);
2675 20 : break;
2676 : }
2677 : }
2678 :
2679 : return;
2680 : }
2681 620 : if (parser->state == XMT_STATE_HEAD) {
2682 55 : if ((parser->doc_type == 1) && !strcmp(name, "Header")) parser->state = XMT_STATE_BODY;
2683 : /*X3D header*/
2684 50 : else if ((parser->doc_type == 2) && !strcmp(name, "head")) {
2685 0 : parser->state = XMT_STATE_BODY;
2686 : /*create a group at root level*/
2687 0 : tag = xmt_get_node_tag(parser, "Group");
2688 0 : node = gf_node_new(parser->load->scene_graph, tag);
2689 0 : gf_node_register(node, NULL);
2690 0 : gf_sg_set_root_node(parser->load->scene_graph, node);
2691 0 : gf_node_init(node);
2692 :
2693 : /*create a default top for X3D*/
2694 0 : GF_SAFEALLOC(parser->x3d_root, XMTNodeStack);
2695 0 : if (!parser->x3d_root) {
2696 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("Failed to allocate X3D root\n"));
2697 : return;
2698 : }
2699 0 : parser->x3d_root->node = node;
2700 : }
2701 : /*XMT-O header*/
2702 50 : else if ((parser->doc_type == 3) && !strcmp(name, "head")) parser->state = XMT_STATE_BODY;
2703 : }
2704 565 : else if (parser->state == XMT_STATE_ELEMENTS) {
2705 : assert((parser->doc_type != 1) || parser->command);
2706 245 : if (!strcmp(name, "Replace") || !strcmp(name, "Insert") || !strcmp(name, "Delete")) {
2707 85 : parser->command = NULL;
2708 85 : parser->state = XMT_STATE_COMMANDS;
2709 : }
2710 160 : else if (!strcmp(name, "repField")) {
2711 5 : parser->state = XMT_STATE_COMMANDS;
2712 : }
2713 : /*end proto*/
2714 170 : else if (!strcmp(name, "ProtoDeclare") || !strcmp(name, "ExternProtoDeclare")) {
2715 15 : GF_Proto *cur = parser->parsing_proto;
2716 15 : xmt_resolve_routes(parser);
2717 15 : parser->parsing_proto = (GF_Proto*)cur->userpriv;
2718 15 : parser->load->scene_graph = cur->parent_graph;
2719 15 : cur->userpriv = NULL;
2720 : }
2721 140 : else if (parser->proto_field && !strcmp(name, "field")) parser->proto_field = NULL;
2722 : /*end X3D body*/
2723 50 : else if ((parser->doc_type == 2) && !strcmp(name, "Scene")) parser->state = XMT_STATE_BODY_END;
2724 : }
2725 320 : else if (parser->state == XMT_STATE_COMMANDS) {
2726 : /*end XMT-A body*/
2727 315 : if ((parser->doc_type == 1) && !strcmp(name, "Body")) parser->state = XMT_STATE_BODY_END;
2728 : /*end X3D body*/
2729 310 : else if ((parser->doc_type == 2) && !strcmp(name, "Scene")) parser->state = XMT_STATE_BODY_END;
2730 : /*end XMT-O body*/
2731 310 : else if ((parser->doc_type == 3) && !strcmp(name, "body")) parser->state = XMT_STATE_BODY_END;
2732 :
2733 : /*end scene command*/
2734 310 : else if (!strcmp(name, "Replace") || !strcmp(name, "Insert") || !strcmp(name, "Delete") ) {
2735 : /*restore parent command if in CommandBuffer*/
2736 75 : if (parser->command && parser->command_buffer && parser->command_buffer->buffer) {
2737 : //empty <Insert>
2738 0 : if ((parser->command->tag==GF_SG_ROUTE_INSERT) && !parser->command->fromNodeID) {
2739 0 : gf_list_del_item(parser->command_buffer->commandList, parser->command);
2740 : }
2741 :
2742 0 : parser->command = (GF_Command*) parser->command_buffer->buffer;
2743 0 : parser->command_buffer->buffer = NULL;
2744 0 : parser->command_buffer = NULL;
2745 : } else {
2746 : //empty <Insert>
2747 75 : if (parser->command && (parser->command->tag==GF_SG_ROUTE_INSERT) && !parser->command->fromNodeID) {
2748 0 : gf_list_del_item(parser->scene_au->commands, parser->command);
2749 : }
2750 75 : parser->command = NULL;
2751 : }
2752 : }
2753 : /*end OD command*/
2754 235 : else if (!strcmp(name, "ObjectDescriptorUpdate") || !strcmp(name, "ObjectDescriptorRemove")
2755 220 : || !strcmp(name, "ES_DescriptorUpdate") || !strcmp(name, "ES_DescriptorRemove")
2756 215 : || !strcmp(name, "IPMP_DescriptorUpdate") || !strcmp(name, "IPMP_DescriptorRemove") ) {
2757 20 : parser->od_command = NULL;
2758 : }
2759 :
2760 215 : else if (!strcmp(name, "par"))
2761 90 : parser->in_com = 1;
2762 :
2763 :
2764 : }
2765 5 : else if (parser->state == XMT_STATE_BODY_END) {
2766 : /*end XMT-A*/
2767 5 : if ((parser->doc_type == 1) && !strcmp(name, "XMT-A")) parser->state = XMT_STATE_END;
2768 : /*end X3D*/
2769 0 : else if ((parser->doc_type == 2) && !strcmp(name, "X3D")) {
2770 0 : while (1) {
2771 0 : GF_Node *n = (GF_Node *)gf_list_last(parser->script_to_load);
2772 0 : if (!n) break;
2773 0 : gf_list_rem_last(parser->script_to_load);
2774 0 : gf_sg_script_load(n);
2775 : }
2776 0 : gf_list_del(parser->script_to_load);
2777 0 : parser->script_to_load = NULL;
2778 0 : parser->state = XMT_STATE_END;
2779 : }
2780 : /*end XMT-O*/
2781 0 : else if ((parser->doc_type == 3) && !strcmp(name, "XMT-O")) parser->state = XMT_STATE_END;
2782 : }
2783 : return;
2784 : }
2785 : /*only remove created nodes ... */
2786 1935 : tag = xmt_get_node_tag(parser, name);
2787 1935 : if (!tag) {
2788 930 : if (top->container_field.name) {
2789 660 : if (!strcmp(name, top->container_field.name)) {
2790 570 : if (top->container_field.fieldType==GF_SG_VRML_SFCOMMANDBUFFER) {
2791 35 : parser->state = XMT_STATE_ELEMENTS;
2792 35 : parser->command = (GF_Command *) (void *) parser->command_buffer->buffer;
2793 35 : parser->command_buffer->buffer = NULL;
2794 35 : parser->command_buffer = NULL;
2795 : }
2796 570 : top->container_field.far_ptr = NULL;
2797 570 : top->container_field.name = NULL;
2798 570 : top->last = NULL;
2799 : }
2800 : /*end of command inside an command (conditional.buffer replace)*/
2801 90 : else if (!strcmp(name, "Replace") || !strcmp(name, "Insert") || !strcmp(name, "Delete") ) {
2802 65 : if (parser->command_buffer) {
2803 65 : if (parser->command_buffer->bufferSize) {
2804 65 : parser->command_buffer->bufferSize--;
2805 : } else {
2806 0 : SFCommandBuffer *prev = (SFCommandBuffer *) parser->command_buffer->buffer;
2807 0 : parser->command_buffer->buffer = NULL;
2808 0 : parser->command_buffer = prev;
2809 : }
2810 : /*stay in command parsing mode (state 3) until we find </buffer>*/
2811 65 : parser->state = XMT_STATE_COMMANDS;
2812 : }
2813 : }
2814 : /*end of protofield node(s) content*/
2815 25 : else if (!strcmp(name, "node") || !strcmp(name, "nodes")) {
2816 25 : top->container_field.far_ptr = NULL;
2817 25 : top->container_field.name = NULL;
2818 25 : top->last = NULL;
2819 : }
2820 : }
2821 : /*SF/MFNode proto field, just pop node stack*/
2822 270 : else if (!top->node && !strcmp(name, "field")) {
2823 10 : gf_list_rem_last(parser->nodes);
2824 10 : gf_free(top);
2825 260 : } else if (top->node && top->node->sgprivate->tag == TAG_ProtoNode) {
2826 150 : if (!strcmp(name, "node") || !strcmp(name, "nodes")) {
2827 0 : top->container_field.far_ptr = NULL;
2828 0 : top->container_field.name = NULL;
2829 0 : top->last = NULL;
2830 150 : } else if (!strcmp(name, "ProtoInstance")) {
2831 20 : gf_list_rem_last(parser->nodes);
2832 20 : node = top->node;
2833 20 : gf_free(top);
2834 20 : goto attach_node;
2835 : }
2836 : }
2837 1005 : } else if (top->node->sgprivate->tag==tag) {
2838 : node = top->node;
2839 1005 : gf_list_rem_last(parser->nodes);
2840 1005 : gf_free(top);
2841 :
2842 1025 : attach_node:
2843 1025 : top = (XMTNodeStack*)gf_list_last(parser->nodes);
2844 : /*add node to command*/
2845 1025 : if (!top || (top->container_field.fieldType==GF_SG_VRML_SFCOMMANDBUFFER)) {
2846 80 : if (parser->doc_type == 1) {
2847 : GF_CommandField *inf;
2848 : Bool single_node = 0;
2849 : assert(parser->command);
2850 80 : switch (parser->command->tag) {
2851 25 : case GF_SG_SCENE_REPLACE:
2852 25 : if (parser->parsing_proto) {
2853 15 : gf_sg_proto_add_node_code(parser->parsing_proto, node);
2854 15 : gf_node_register(node, NULL);
2855 10 : } else if (!parser->command->node) {
2856 0 : parser->command->node = node;
2857 0 : gf_node_register(node, NULL);
2858 10 : } else if (parser->command->node != node) {
2859 0 : xmt_report(parser, GF_OK, "Warning: top-node already assigned - discarding node %s", name);
2860 0 : gf_node_register(node, NULL);
2861 0 : gf_node_unregister(node, NULL);
2862 : }
2863 : break;
2864 30 : case GF_SG_GLOBAL_QUANTIZER:
2865 : case GF_SG_NODE_INSERT:
2866 : case GF_SG_INDEXED_INSERT:
2867 : case GF_SG_INDEXED_REPLACE:
2868 : single_node = 1;
2869 50 : case GF_SG_NODE_REPLACE:
2870 : case GF_SG_FIELD_REPLACE:
2871 : case GF_SG_MULTIPLE_REPLACE:
2872 50 : inf = (GF_CommandField*)gf_list_last(parser->command->command_fields);
2873 50 : if (!inf) {
2874 20 : inf = gf_sg_command_field_new(parser->command);
2875 20 : inf->fieldType = GF_SG_VRML_SFNODE;
2876 : }
2877 50 : if ((inf->fieldType==GF_SG_VRML_MFNODE) && !inf->node_list) {
2878 0 : inf->field_ptr = &inf->node_list;
2879 0 : if (inf->new_node) {
2880 0 : gf_node_list_add_child(& inf->node_list, inf->new_node);
2881 0 : inf->new_node = NULL;
2882 : }
2883 : }
2884 :
2885 50 : if (inf->new_node) {
2886 0 : if (single_node) {
2887 0 : gf_node_unregister(inf->new_node, NULL);
2888 : } else {
2889 0 : inf->field_ptr = &inf->node_list;
2890 0 : gf_node_list_add_child(& inf->node_list, inf->new_node);
2891 0 : inf->fieldType = GF_SG_VRML_MFNODE;
2892 : }
2893 0 : inf->new_node = NULL;
2894 : }
2895 50 : gf_node_register(node, NULL);
2896 50 : if (inf->node_list) {
2897 0 : gf_node_list_add_child(& inf->node_list, node);
2898 : } else {
2899 50 : inf->new_node = node;
2900 50 : inf->field_ptr = &inf->new_node;
2901 : }
2902 : break;
2903 5 : case GF_SG_PROTO_INSERT:
2904 5 : if (parser->parsing_proto) {
2905 5 : gf_sg_proto_add_node_code(parser->parsing_proto, node);
2906 5 : gf_node_register(node, NULL);
2907 5 : break;
2908 : }
2909 : default:
2910 0 : xmt_report(parser, GF_OK, "Warning: node %s defined outside scene scope - skipping", name);
2911 0 : gf_node_register(node, NULL);
2912 0 : gf_node_unregister(node, NULL);
2913 0 : break;
2914 :
2915 : }
2916 : }
2917 : /*X3D*/
2918 0 : else if (parser->doc_type == 2) {
2919 0 : if (parser->parsing_proto) {
2920 0 : gf_sg_proto_add_node_code(parser->parsing_proto, node);
2921 0 : gf_node_register(node, NULL);
2922 : } else {
2923 0 : M_Group *gr = (M_Group *)gf_sg_get_root_node(parser->load->scene_graph);
2924 0 : if (!gr) {
2925 0 : xmt_report(parser, GF_OK, "Warning: node %s defined outside scene scope - skipping", name);
2926 0 : gf_node_register(node, NULL);
2927 0 : gf_node_unregister(node, NULL);
2928 : } else {
2929 : //node has already been added to its parent with X3d parsing, because of the default container resolving
2930 : // gf_node_list_add_child(& gr->children, node);
2931 : // gf_node_register(node, NULL);
2932 : }
2933 : }
2934 : }
2935 : /*special case: replace scene has already been applied (progressive loading)*/
2936 0 : else if ((parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) && (parser->load->scene_graph->RootNode!=node) ) {
2937 0 : gf_node_register(node, NULL);
2938 : } else {
2939 0 : xmt_report(parser, GF_OK, "Warning: node %s defined outside scene scope - skipping", name);
2940 0 : gf_node_register(node, NULL);
2941 0 : gf_node_unregister(node, NULL);
2942 : }
2943 : }
2944 1025 : if (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) {
2945 : /*load scripts*/
2946 205 : if (!parser->parsing_proto) {
2947 386 : if ((tag==TAG_MPEG4_Script)
2948 : #ifndef GPAC_DISABLE_X3D
2949 193 : || (tag==TAG_X3D_Script)
2950 : #endif
2951 : ) {
2952 : /*it may happen that the script uses itself as a field (not sure this is compliant since this
2953 : implies a cyclic structure, but happens in some X3D conformance seq)*/
2954 1 : if (!top || (top->node != node)) {
2955 1 : if (parser->command) {
2956 1 : if (!parser->command->scripts_to_load) parser->command->scripts_to_load = gf_list_new();
2957 1 : gf_list_add(parser->command->scripts_to_load, node);
2958 : }
2959 : /*do not load script until all routes are established!!*/
2960 0 : else if (parser->doc_type==2) {
2961 0 : gf_list_add(parser->script_to_load, node);
2962 : } else {
2963 0 : gf_sg_script_load(node);
2964 : }
2965 : }
2966 : }
2967 : }
2968 : }
2969 0 : } else if (parser->current_node_tag==tag) {
2970 0 : gf_list_rem_last(parser->nodes);
2971 0 : gf_free(top);
2972 : } else {
2973 0 : xmt_report(parser, GF_NON_COMPLIANT_BITSTREAM, "Warning: closing element %s doesn't match created node %s", name, gf_node_get_class_name(top->node) );
2974 : }
2975 : }
2976 :
2977 4355 : static void xmt_text_content(void *sax_cbck, const char *text_content, Bool is_cdata)
2978 : {
2979 : const char *buf;
2980 : u32 len;
2981 : GF_XMTParser *parser = (GF_XMTParser *)sax_cbck;
2982 : GF_Node *node;
2983 4355 : XMTNodeStack *top = (XMTNodeStack *)gf_list_last(parser->nodes);
2984 4355 : if (!top || !top->node) return;
2985 :
2986 : node = top->node;
2987 :
2988 : buf = text_content;
2989 2995 : len = (u32) strlen(buf);
2990 :
2991 2995 : if (!len) return;
2992 :
2993 2995 : switch (gf_node_get_tag((GF_Node *)node)) {
2994 30 : case TAG_MPEG4_Script:
2995 : #ifndef GPAC_DISABLE_X3D
2996 : case TAG_X3D_Script:
2997 : #endif
2998 30 : if (is_cdata) {
2999 : SFScript *sc_f;
3000 : M_Script *sc = (M_Script *) node;
3001 0 : gf_sg_vrml_mf_reset(& sc->url, GF_SG_VRML_MFSCRIPT);
3002 0 : gf_sg_vrml_mf_append(& sc->url, GF_SG_VRML_MFSCRIPT, (void **) &sc_f);
3003 0 : sc->url.vals[0].script_text = gf_strdup(text_content);
3004 : }
3005 : break;
3006 : default:
3007 : break;
3008 : }
3009 : }
3010 :
3011 :
3012 5 : static GF_XMTParser *xmt_new_parser(GF_SceneLoader *load)
3013 : {
3014 : GF_XMTParser *parser;
3015 5 : if ((load->type==GF_SM_LOAD_XSR) && !load->ctx) return NULL;
3016 5 : GF_SAFEALLOC(parser, GF_XMTParser);
3017 5 : if (!parser) return NULL;
3018 :
3019 5 : parser->nodes = gf_list_new();
3020 5 : parser->descriptors = gf_list_new();
3021 5 : parser->od_links = gf_list_new();
3022 5 : parser->esd_links = gf_list_new();
3023 5 : parser->def_nodes = gf_list_new();
3024 5 : parser->peeked_nodes = gf_list_new();
3025 5 : parser->inserted_routes = gf_list_new();
3026 5 : parser->unresolved_routes = gf_list_new();
3027 :
3028 5 : parser->sax_parser = gf_xml_sax_new(xmt_node_start, xmt_node_end, xmt_text_content, parser);
3029 5 : parser->load = load;
3030 5 : load->loader_priv = parser;
3031 5 : if (load->ctx) load->ctx->is_pixel_metrics = 1;
3032 :
3033 : return parser;
3034 : }
3035 :
3036 0 : static GF_Err xmt_restore_context(GF_SceneLoader *load)
3037 : {
3038 : u32 i;
3039 : GF_StreamContext *sc;
3040 0 : GF_XMTParser *parser = (GF_XMTParser *)load->loader_priv;
3041 0 : if (!parser || !load->ctx) return GF_BAD_PARAM;
3042 :
3043 : /*restore context - note that base layer are ALWAYS declared BEFORE enhancement layers with gpac parsers*/
3044 0 : i=0;
3045 0 : while ((sc = (GF_StreamContext*)gf_list_enum(load->ctx->streams, &i))) {
3046 0 : switch (sc->streamType) {
3047 0 : case GF_STREAM_SCENE:
3048 : case GF_STREAM_PRIVATE_SCENE:
3049 0 : if (!parser->scene_es)
3050 0 : parser->scene_es = sc;
3051 : break;
3052 0 : case GF_STREAM_OD:
3053 0 : if (!parser->od_es)
3054 0 : parser->od_es = sc;
3055 : break;
3056 : default:
3057 : break;
3058 : }
3059 : }
3060 : /*scene creation - pick up a size*/
3061 0 : if (!parser->scene_es) {
3062 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("XMT: No BIFS Streams found in existing context - creating one\n"));
3063 0 : parser->scene_es = gf_sm_stream_new(load->ctx, 0, GF_STREAM_SCENE, GF_CODECID_BIFS);
3064 0 : parser->load->ctx->scene_width = 0;
3065 0 : parser->load->ctx->scene_height = 0;
3066 0 : parser->load->ctx->is_pixel_metrics = 1;
3067 : }
3068 0 : else parser->base_scene_id = parser->scene_es->ESID;
3069 0 : if (parser->od_es) parser->base_od_id = parser->od_es->ESID;
3070 :
3071 0 : parser->doc_type = (load->type==GF_SM_LOAD_X3D) ? 2 : 1;
3072 0 : return GF_OK;
3073 : }
3074 :
3075 :
3076 5 : static GF_Err load_xmt_initialize(GF_SceneLoader *load, const char *str_data)
3077 : {
3078 : GF_Err e;
3079 : GF_XMTParser *parser;
3080 :
3081 5 : if (str_data) {
3082 : char BOM[5];
3083 0 : if (strlen(str_data)<4) return GF_BAD_PARAM;
3084 0 : BOM[0] = str_data[0];
3085 0 : BOM[1] = str_data[1];
3086 0 : BOM[2] = str_data[2];
3087 0 : BOM[3] = str_data[3];
3088 0 : BOM[4] = 0;
3089 0 : parser = xmt_new_parser(load);
3090 0 : e = gf_xml_sax_init(parser->sax_parser, (unsigned char*)BOM);
3091 0 : if (e) {
3092 0 : xmt_report(parser, e, "Error initializing SAX parser");
3093 0 : return e;
3094 : }
3095 0 : str_data += 4;
3096 5 : } else if (load->fileName) {
3097 5 : parser = xmt_new_parser(load);
3098 : } else {
3099 : return GF_BAD_PARAM;
3100 : }
3101 :
3102 : /*chunk parsing*/
3103 5 : if (load->flags & GF_SM_LOAD_CONTEXT_READY) {
3104 0 : GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("XMT: MPEG-4 (XMT) Chunk Parsing\n"));
3105 :
3106 0 : e = xmt_restore_context(load);
3107 0 : if (e) return e;
3108 :
3109 : } else {
3110 5 : GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("XMT: MPEG-4 (XMT) Scene Parsing\n"));
3111 : }
3112 :
3113 5 : if (str_data) {
3114 0 : return gf_xml_sax_parse(parser->sax_parser, str_data);
3115 : }
3116 : return GF_OK;
3117 : }
3118 :
3119 :
3120 5 : static GF_Err load_xmt_run(GF_SceneLoader *load)
3121 : {
3122 : GF_Err e;
3123 5 : GF_XMTParser *parser = (GF_XMTParser *)load->loader_priv;
3124 5 : if (!parser) {
3125 0 : e = load_xmt_initialize(load, NULL);
3126 0 : if (e) return e;
3127 0 : parser = (GF_XMTParser *)load->loader_priv;
3128 0 : if (!parser) return GF_OUT_OF_MEM;
3129 : }
3130 :
3131 5 : e = gf_xml_sax_parse_file(parser->sax_parser, (const char *)load->fileName, xmt_progress);
3132 5 : if (e==GF_OK) e = parser->last_error;
3133 :
3134 5 : xmt_resolve_routes(parser);
3135 5 : xmt_resolve_od_links(parser);
3136 :
3137 5 : parser->last_error=GF_OK;
3138 5 : if (e<0) return xmt_report(parser, e, "Invalid XML document: %s", gf_xml_sax_get_error(parser->sax_parser));
3139 :
3140 : return GF_OK;
3141 : }
3142 :
3143 0 : static GF_Err load_xmt_parse_string(GF_SceneLoader *load, const char *str)
3144 : {
3145 : GF_Err e;
3146 0 : GF_XMTParser *parser = (GF_XMTParser *)load->loader_priv;
3147 0 : if (!parser) {
3148 0 : return load_xmt_initialize(load, str);
3149 : }
3150 0 : e = gf_xml_sax_parse(parser->sax_parser, str);
3151 0 : if (e==GF_OK) e = parser->last_error;
3152 :
3153 0 : xmt_resolve_routes(parser);
3154 0 : xmt_resolve_od_links(parser);
3155 :
3156 0 : parser->last_error=GF_OK;
3157 0 : if (e<0) return xmt_report(parser, e, "Invalid XML document: %s", gf_xml_sax_get_error(parser->sax_parser));
3158 : return GF_OK;
3159 : }
3160 :
3161 6 : static void load_xmt_done(GF_SceneLoader *load)
3162 : {
3163 6 : GF_XMTParser *parser = (GF_XMTParser *)load->loader_priv;
3164 6 : if (!parser) return;
3165 :
3166 0 : while (1) {
3167 5 : XMTNodeStack *st = (XMTNodeStack *)gf_list_last(parser->nodes);
3168 5 : if (!st) break;
3169 0 : gf_list_rem_last(parser->nodes);
3170 0 : gf_node_register(st->node, NULL);
3171 0 : gf_node_unregister(st->node, NULL);
3172 0 : gf_free(st);
3173 : }
3174 5 : if (parser->x3d_root) gf_free(parser->x3d_root);
3175 5 : gf_list_del(parser->nodes);
3176 5 : gf_list_del(parser->descriptors);
3177 5 : gf_list_del(parser->def_nodes);
3178 5 : gf_list_del(parser->peeked_nodes);
3179 :
3180 5 : gf_list_del(parser->inserted_routes);
3181 5 : gf_list_del(parser->unresolved_routes);
3182 5 : gf_list_del(parser->od_links);
3183 5 : gf_list_del(parser->esd_links);
3184 5 : gf_xml_sax_del(parser->sax_parser);
3185 5 : if (parser->script_to_load) gf_list_del(parser->script_to_load);
3186 5 : gf_free(parser);
3187 5 : load->loader_priv = NULL;
3188 : }
3189 :
3190 0 : static GF_Err load_xmt_suspend(GF_SceneLoader *load, Bool suspend)
3191 : {
3192 0 : GF_XMTParser *parser = (GF_XMTParser *)load->loader_priv;
3193 0 : if (parser) gf_xml_sax_suspend(parser->sax_parser, suspend);
3194 0 : return GF_OK;
3195 : }
3196 :
3197 :
3198 5 : GF_Err gf_sm_load_init_xmt(GF_SceneLoader *load)
3199 : {
3200 5 : load->process = load_xmt_run;
3201 5 : load->done = load_xmt_done;
3202 5 : load->parse_string = load_xmt_parse_string;
3203 5 : load->suspend = load_xmt_suspend;
3204 5 : if (load->fileName) return load_xmt_initialize(load, NULL);
3205 : return GF_OK;
3206 : }
3207 :
3208 :
3209 : #endif /*GPAC_DISABLE_LOADER_XMT*/
|