PageRenderTime 69ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/src/scene_manager/loader_xmt.c

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