PageRenderTime 71ms CodeModel.GetById 25ms 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

Large files files are truncated, but you can click here to view the full file

  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(na

Large files files are truncated, but you can click here to view the full file