/src/scene_manager/loader_xmt.c
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
- /*
- * GPAC - Multimedia Framework C SDK
- *
- * Authors: Jean Le Feuvre
- * Copyright (c) Telecom ParisTech 2000-2012
- * All rights reserved
- *
- * This file is part of GPAC / Scene Management sub-project
- *
- * GPAC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GPAC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
- #include "../../include/gpac/scene_manager.h"
- #include "../../include/gpac/constants.h"
- #include "../../include/gpac/utf.h"
- #include "../../include/gpac/xml.h"
- #include "../../include/gpac/internal/bifs_dev.h"
- #include "../../include/gpac/internal/scenegraph_dev.h"
- #include "../../include/gpac/nodes_x3d.h"
- #ifndef GPAC_DISABLE_LOADER_XMT
- void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName);
- /*for QP types*/
- #include "../bifs/quant.h"
- typedef struct
- {
- GF_Node *node;
- GF_FieldInfo container_field;
- GF_ChildNodeItem *last;
- } XMTNodeStack;
- /**/
- enum
- {
- /*document is not yet initialized*/
- XMT_STATE_INIT = 0,
- /*document head is being parsed*/
- XMT_STATE_HEAD = 1,
- /*document body being parsed*/
- XMT_STATE_BODY = 2,
- /*commands are being parsed*/
- XMT_STATE_COMMANDS = 3,
- /*elements are being parsed*/
- XMT_STATE_ELEMENTS = 4,
- /*end of body parsing*/
- XMT_STATE_BODY_END = 5,
- /*end of parsing*/
- XMT_STATE_END = 6,
- };
- typedef struct
- {
- /*1: XMT-A, 2: X3D, 3: XMT-O (not supported yet) */
- u32 doc_type;
- /*0: not init, 1: header, 2: body*/
- u32 state;
- u32 current_node_tag;
- GF_SceneLoader *load;
- GF_Err last_error;
- GF_SAXParser *sax_parser;
- XMTNodeStack *x3d_root;
- /* stack of nodes for SAX parsing*/
- GF_List *nodes;
- /* stack of descriptors for SAX parsing*/
- GF_List *descriptors;
- GF_List *peeked_nodes;
- GF_List *def_nodes;
- GF_List *inserted_routes, *unresolved_routes;
- /* OD and ESD links*/
- GF_List *od_links, *esd_links;
- /*set when parsing proto*/
- GF_Proto *parsing_proto;
- GF_ProtoFieldInterface *proto_field;
- GF_StreamContext *scene_es;
- GF_AUContext *scene_au;
- u32 base_scene_id;
- /*current scene command*/
- GF_Command *command;
- SFCommandBuffer *command_buffer;
- GF_StreamContext *od_es;
- GF_AUContext *od_au;
- u32 base_od_id;
- /*current od command*/
- GF_ODCom *od_command;
- /*current stream ID, AU time and RAP flag*/
- u32 stream_id;
- Double au_time;
- Bool au_is_rap;
- Bool in_com;
- GF_List *script_to_load;
- } GF_XMTParser;
- typedef struct
- {
- char *desc_name;
- u32 ID;
- /*store nodes refering to this URL*/
- GF_List *mf_urls;
- GF_ObjectDescriptor *od;
- } XMT_ODLink;
- typedef struct
- {
- char *desc_name;
- u32 ESID;
- GF_ESD *esd;
- char *OCR_Name;
- char *Depends_Name;
- } XMT_ESDLink;
- static GF_Err xmt_report(GF_XMTParser *parser, GF_Err e, char *format, ...)
- {
- #ifndef GPAC_DISABLE_LOG
- if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
- char szMsg[2048];
- va_list args;
- va_start(args, format);
- vsprintf(szMsg, format, args);
- va_end(args);
- 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)) );
- }
- #endif
- if (e) parser->last_error = e;
- return e;
- }
- static void xmt_progress(void *cbk, u64 done, u64 total)
- {
- gf_set_progress("XMT Parsing", done, total);
- }
- static Bool xmt_esid_available(GF_XMTParser *parser, u16 ESID)
- {
- u32 i;
- XMT_ESDLink *esdl;
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- if (esdl->ESID == ESID) return 0;
- }
- return 1;
- }
- static char *xmt_get_es_name(GF_XMTParser *parser, u16 ESID)
- {
- u32 i;
- XMT_ESDLink *esdl;
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- if (esdl->ESID == ESID) return esdl->desc_name;
- }
- return NULL;
- }
- static void xmt_new_od_link(GF_XMTParser *parser, GF_ObjectDescriptor *od, char *name, u32 ID)
- {
- u32 i, j, count;
- XMT_ODLink *odl;
- if (!ID) {
- if (!strnicmp(name, "od", 2)) ID = atoi(name + 2);
- else if (!strnicmp(name, "iod", 3)) ID = atoi(name+ 3);
- /*be carefull, an url like "11-regression-test.mp4" will return 1 on sscanf :)*/
- else if (sscanf(name, "%u", &ID) == 1) {
- char szURL[20];
- sprintf(szURL, "%u", ID);
- if (strcmp(szURL, name)) {
- ID = 0;
- } else {
- name = NULL;
- }
- }
- }
- count = gf_list_count(parser->od_links);
- for (i=0; i<count; i++) {
- odl = (XMT_ODLink*)gf_list_get(parser->od_links, i);
- if ( (ID && (odl->ID == ID))
- || (odl->od == od)
- || (odl->desc_name && name && !strcmp(odl->desc_name, name))
- ) {
- if (!odl->od) odl->od = od;
- if (!odl->desc_name && name) odl->desc_name = gf_strdup(name);
- if (!od->objectDescriptorID) {
- od->objectDescriptorID = ID;
- } else if (ID && (od->objectDescriptorID != ID)) {
- xmt_report(parser, GF_BAD_PARAM, "Conflicting OD IDs %d vs %d\n", ID, od->objectDescriptorID);
- }
- for (j=i+1; j<count; j++) {
- XMT_ODLink *l2 = (XMT_ODLink*)gf_list_get(parser->od_links, j);
- if (l2->od == od) {
- odl->ID = od->objectDescriptorID = odl->od->objectDescriptorID;
- gf_list_rem(parser->od_links, j);
- if (l2->desc_name) gf_free(l2->desc_name);
- gf_list_del(l2->mf_urls);
- gf_free(l2);
- break;
- }
- }
- return;
- }
- }
- GF_SAFEALLOC(odl, XMT_ODLink);
- odl->mf_urls = gf_list_new();
- odl->od = od;
- if (ID) od->objectDescriptorID = ID;
- if (name) odl->desc_name = gf_strdup(name);
- gf_list_add(parser->od_links, odl);
- }
- static void xmt_new_od_link_from_node(GF_XMTParser *parser, char *name, MFURL *url)
- {
- u32 i, ID;
- XMT_ODLink *odl;
- /*find OD_ID*/
- ID = 0;
- if (!strnicmp(name, "od", 2)) ID = atoi(name + 2);
- else if (!strnicmp(name, "iod", 3)) ID = atoi(name + 3);
- /*be carefull, an url like "11-regression-test.mp4" will return 1 on sscanf :)*/
- else if (sscanf(name, "%u", &ID) == 1) {
- char szURL[20];
- sprintf(szURL, "%u", ID);
- if (strcmp(szURL, name)) {
- ID = 0;
- } else {
- name = NULL;
- }
- }
- else ID = 0;
- /*write OD_ID*/
- assert(url->count);
- i = url->count - 1;
- url->vals[i].OD_ID = 0;
- url->vals->OD_ID = ID;
- i=0;
- while ((odl = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
- if ( (name && odl->desc_name && !strcmp(odl->desc_name, name))
- || (ID && odl->od && odl->od->objectDescriptorID==ID)
- || (ID && (odl->ID==ID))
- ) {
- if (url && (gf_list_find(odl->mf_urls, url)<0) ) gf_list_add(odl->mf_urls, url);
- return;
- }
- }
- GF_SAFEALLOC(odl, XMT_ODLink);
- odl->mf_urls = gf_list_new();
- if (url) gf_list_add(odl->mf_urls, url);
- if (ID) odl->ID = ID;
- else odl->desc_name = gf_strdup(name);
- gf_list_add(parser->od_links, odl);
- }
- static void xmt_new_esd_link(GF_XMTParser *parser, GF_ESD *esd, char *desc_name, u32 binID)
- {
- u32 i, j;
- XMT_ESDLink *esdl;
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- if (esdl->esd && (esd!=esdl->esd)) continue;
- if (!esdl->esd) {
- if (!esdl->ESID || !desc_name || strcmp(esdl->desc_name, desc_name)) continue;
- esdl->esd = esd;
- }
- if (binID) {
- /*remove temp links*/
- if (esdl->ESID == (u16) ( ( (PTR_TO_U_CAST esdl) >> 16) | ( (PTR_TO_U_CAST esdl) & 0x0000FFFF) ) ) {
- GF_StreamContext *sc;
- j=0;
- while ((sc = (GF_StreamContext *)gf_list_enum(parser->load->ctx->streams, &j))) {
- if (sc->ESID!=esdl->ESID) continue;
- /*reassign*/
- sc->ESID = binID;
- break;
- }
- }
- esdl->ESID = esdl->esd->ESID = binID;
- }
- if (desc_name && !esdl->desc_name) {
- esdl->desc_name = gf_strdup(desc_name);
- if (!esdl->ESID && !strnicmp(desc_name, "es", 2)) esdl->ESID = atoi(&desc_name[2]);
- }
- return;
- }
- GF_SAFEALLOC(esdl, XMT_ESDLink);
- esdl->esd = esd;
- esd->ESID = esdl->ESID = binID;
- if (desc_name) {
- if (!esdl->ESID && !strnicmp(desc_name, "es", 2)) esdl->ESID = atoi(&desc_name[2]);
- esdl->desc_name = gf_strdup(desc_name);
- }
- if (!esd->ESID) {
- esd->ESID = 1;
- while (!xmt_esid_available(parser, esd->ESID)) esd->ESID++;
- esdl->ESID = esd->ESID;
- }
- gf_list_add(parser->esd_links, esdl);
- }
- static Bool xmt_set_depend_id(GF_XMTParser *parser, GF_ESD *desc, char *es_name, Bool is_ocr_dep)
- {
- u32 i;
- XMT_ESDLink *esdl;
- if (!desc || !es_name) return 0;
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- if (esdl->esd == desc) {
- if (is_ocr_dep)
- esdl->OCR_Name = gf_strdup(es_name);
- else
- esdl->Depends_Name = gf_strdup(es_name);
- return 1;
- }
- }
- return 0;
- }
- static u32 xmt_get_od_id(GF_XMTParser *parser, char *od_name)
- {
- u32 i, ID;
- XMT_ODLink *l;
- if (sscanf(od_name, "%u", &ID)==1) return ID;
- i=0;
- while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
- if (!l->od) continue;
- if (l->desc_name && !strcmp(l->desc_name, od_name)) return l->od->objectDescriptorID;
- }
- return 0;
- }
- static u32 xmt_get_esd_id(GF_XMTParser *parser, char *esd_name)
- {
- u32 i, ID;
- XMT_ESDLink *l;
- if (sscanf(esd_name, "%u", &ID)==1) return ID;
- i=0;
- while ((l = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- if (!l->esd) continue;
- if (l->desc_name && !strcmp(l->desc_name, esd_name)) return l->esd->ESID;
- }
- return 0;
- }
- static u32 xmt_locate_stream(GF_XMTParser *parser, char *stream_name)
- {
- XMT_ESDLink *esdl;
- u32 i;
- char szN[200];
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- if (esdl->desc_name && !strcmp(esdl->desc_name, stream_name)) return esdl->ESID;
- if (esdl->ESID) {
- sprintf(szN, "es%d", esdl->ESID);
- if (!strcmp(szN, stream_name)) return esdl->ESID;
- sprintf(szN, "%d", esdl->ESID);
- if (!strcmp(szN, stream_name)) return esdl->ESID;
- }
- }
- if (parser->load->ctx) {
- GF_StreamContext *sc;
- i=0;
- while ((sc = gf_list_enum(parser->load->ctx->streams, &i))) {
- if (sc->name && !strcmp(sc->name, stream_name)) return sc->ESID;
- sprintf(szN, "%d", sc->ESID);
- if (!strcmp(szN, stream_name)) return sc->ESID;
- }
- }
- /*create a temp one*/
- esdl = (XMT_ESDLink *)gf_malloc(sizeof(XMT_ESDLink));
- memset(esdl, 0, sizeof(XMT_ESDLink));
- esdl->ESID = (u16) ( (PTR_TO_U_CAST esdl) >> 16) | ( (PTR_TO_U_CAST esdl) & 0x0000FFFF);
- if (!strnicmp(stream_name, "es", 2)) esdl->ESID = atoi(&stream_name[2]);
- esdl->desc_name = gf_strdup(stream_name);
- gf_list_add(parser->esd_links, esdl);
- return esdl->ESID;
- }
- static Bool xmt_odid_available(GF_XMTParser *parser, u16 ODID)
- {
- u32 i;
- XMT_ODLink *l;
- i=0;
- while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
- if (l->ID == ODID) return 0;
- if (l->od && l->od->objectDescriptorID == ODID) return 0;
- }
- return 1;
- }
- static void xmt_resolve_od_links(GF_XMTParser *parser)
- {
- u32 i, j;
- XMT_ESDLink *esdl, *esdl2;
- XMT_ODLink *l;
- char szURL[5000];
- /*fix ESD IDs*/
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- if (!esdl->esd) {
- xmt_report(parser, GF_BAD_PARAM, "Stream %s ID %d has no associated ES descriptor\n", esdl->desc_name ? esdl->desc_name : "", esdl->ESID);
- i--;
- gf_list_rem(parser->esd_links, i);
- if (esdl->desc_name) gf_free(esdl->desc_name);
- gf_free(esdl);
- continue;
- }
- if (esdl->ESID) esdl->esd->ESID = esdl->ESID;
- else if (!esdl->esd->ESID) {
- u16 ESID = 1;
- while (!xmt_esid_available(parser, ESID)) ESID++;
- esdl->esd->ESID = ESID;
- }
- }
- /*set OCR es ids*/
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- Bool use_old_fmt;
- u16 ocr_id;
- char szTest[50];
- esdl->esd->OCRESID = 0;
- if (!esdl->OCR_Name) continue;
- use_old_fmt = 0;
- ocr_id = atoi(esdl->OCR_Name);
- sprintf(szTest, "%d", ocr_id);
- if (!stricmp(szTest, esdl->OCR_Name)) use_old_fmt = 1;
- j=0;
- while ((esdl2 = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &j))) {
- if (esdl2->desc_name && !strcmp(esdl2->desc_name, esdl->OCR_Name)) {
- esdl->esd->OCRESID = esdl2->esd->ESID;
- break;
- }
- if (use_old_fmt && (esdl2->esd->ESID==ocr_id)) {
- esdl->esd->OCRESID = ocr_id;
- break;
- }
- }
- if (!esdl->esd->OCRESID) {
- xmt_report(parser, GF_OK, "WARNING: Could not find clock reference %s for ES %s - forcing self-synchronization", esdl->OCR_Name, esdl->desc_name);
- }
- gf_free(esdl->OCR_Name);
- esdl->OCR_Name = NULL;
- }
- /*set dependsOn es ids*/
- i=0;
- while ((esdl = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &i))) {
- Bool use_old_fmt;
- u16 dep_id;
- char szTest[50];
- esdl->esd->dependsOnESID = 0;
- if (!esdl->Depends_Name) continue;
- use_old_fmt = 0;
- dep_id = atoi(esdl->Depends_Name);
- sprintf(szTest, "%d", dep_id);
- if (!stricmp(szTest, esdl->Depends_Name)) use_old_fmt = 1;
- j=0;
- while ((esdl2 = (XMT_ESDLink *)gf_list_enum(parser->esd_links, &j))) {
- if (esdl2->desc_name && !strcmp(esdl2->desc_name, esdl->Depends_Name)) {
- esdl->esd->dependsOnESID = esdl2->esd->ESID;
- break;
- }
- if (use_old_fmt && (esdl2->esd->ESID==dep_id)) {
- esdl->esd->dependsOnESID = dep_id;
- break;
- }
- }
- if (!esdl->esd->dependsOnESID) {
- xmt_report(parser, GF_OK, "WARNING: Could not find stream dependance %s for ES %s - forcing self-synchronization", esdl->Depends_Name, esdl->desc_name);
- }
- gf_free(esdl->Depends_Name);
- esdl->Depends_Name = NULL;
- }
- while (gf_list_count(parser->esd_links)) {
- esdl = (XMT_ESDLink *)gf_list_get(parser->esd_links, 0);
- gf_list_rem(parser->esd_links, 0);
- if (esdl->desc_name) gf_free(esdl->desc_name);
- gf_free(esdl);
- }
- i=0;
- while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
- if (l->od && !l->od->objectDescriptorID) {
- u16 ODID = 1;
- while (!xmt_odid_available(parser, ODID)) ODID++;
- l->od->objectDescriptorID = ODID;
- }
- if (l->od) {
- if (!l->ID) l->ID = l->od->objectDescriptorID;
- assert(l->ID == l->od->objectDescriptorID);
- }
- }
- /*unroll dep in case some URLs reference ODs by their binary IDs not their string ones*/
- i=0;
- while ((l = (XMT_ODLink*)gf_list_enum(parser->od_links, &i))) {
- XMT_ODLink *l2;
- /*not OD URL*/
- if (!l->ID) continue;
- j=i+1;
- while ((l2 = (XMT_ODLink*)gf_list_enum(parser->od_links, &j))) {
- /*not OD URL*/
- if (!l2->ID) continue;
- if (l->ID == l2->ID) {
- while (gf_list_count(l2->mf_urls)) {
- MFURL *url = (MFURL *)gf_list_get(l2->mf_urls, 0);
- gf_list_rem(l2->mf_urls, 0);
- gf_list_add(l->mf_urls, url);
- }
- j--;
- gf_list_rem(parser->od_links, j);
- if (l2->desc_name) gf_free(l2->desc_name);
- gf_list_del(l2->mf_urls);
- gf_free(l2);
- }
- }
- }
- while (gf_list_count(parser->od_links) ) {
- l = (XMT_ODLink*)gf_list_get(parser->od_links, 0);
- if (!l->od) {
- /*if no ID found this is not an OD URL*/
- if (l->ID) {
- if (l->desc_name) {
- xmt_report(parser, GF_OK, "WARNING: OD \"%s\" (ID %d) not assigned", l->desc_name, l->ID);
- } else{
- xmt_report(parser, GF_OK, "WARNING: OD ID %d not assigned", l->ID);
- }
- }
- } else {
- MFURL *the_url;
- j=0;
- while ((the_url = (MFURL *)gf_list_enum(l->mf_urls, &j))) {
- u32 k;
- char *seg = NULL;
- for (k=0; k<the_url->count; k++) {
- SFURL *url = &the_url->vals[k];
- if (url->url) seg = strstr(url->url, "#");
- if (seg) {
- sprintf(szURL, "od:%d#%s", l->od->objectDescriptorID, seg+1);
- gf_free(url->url);
- url->url = gf_strdup(szURL);
- } else {
- if (url->url) gf_free(url->url);
- url->url = NULL;
- url->OD_ID = l->od->objectDescriptorID;
- }
- }
- }
- }
- if (l->desc_name) gf_free(l->desc_name);
- gf_list_del(l->mf_urls);
- gf_free(l);
- gf_list_rem(parser->od_links, 0);
- }
- }
- static u32 xmt_get_next_node_id(GF_XMTParser *parser)
- {
- u32 ID;
- GF_SceneGraph *sc = parser->load->scene_graph;
- if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
- ID = gf_sg_get_next_available_node_id(sc);
- if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
- parser->load->ctx->max_node_id = ID;
- return ID;
- }
- static u32 xmt_get_node_id(GF_XMTParser *parser, char *name)
- {
- GF_Node *n = NULL;
- u32 ID = 0;
- if (sscanf(name, "N%u", &ID) == 1) {
- u32 k=1;
- while (name[k]) {
- if (strchr("0123456789", name[k])==0) {
- ID = 0;
- break;
- }
- k++;
- }
- if (ID) {
- ID ++;
- n = gf_sg_find_node(parser->load->scene_graph, ID);
- if (!n) {
- if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
- return ID;
- }
- }
- }
- ID = xmt_get_next_node_id(parser);
- if (n) {
- 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));
- }
- return ID;
- }
- static u32 xmt_get_node_tag(GF_XMTParser *parser, const char *node_name)
- {
- u32 tag;
- /*if VRML and allowing non MPEG4 nodes, use X3D*/
- if ((parser->doc_type==2) && !(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) {
- #ifndef GPAC_DISABLE_X3D
- tag = gf_node_x3d_type_by_class_name(node_name);
- if (!tag)
- #endif
- tag = gf_node_mpeg4_type_by_class_name(node_name);
- } else {
- tag = gf_node_mpeg4_type_by_class_name(node_name);
- /*if allowing non MPEG4 nodes, try X3D*/
- #ifndef GPAC_DISABLE_X3D
- if (!tag && !(parser->load->flags & GF_SM_LOAD_MPEG4_STRICT)) tag = gf_node_x3d_type_by_class_name(node_name);
- #endif
- }
- return tag;
- }
- static GF_Node *xmt_find_node(GF_XMTParser *parser, char *ID)
- {
- u32 i, count, tag;
- Bool is_proto;
- char *node_class;
- GF_Node *n = gf_sg_find_node_by_name(parser->load->scene_graph, ID);
- if (n) return n;
- count = gf_list_count(parser->peeked_nodes);
- for (i=0; i<count; i++) {
- n = (GF_Node*)gf_list_get(parser->peeked_nodes, i);
- if (!strcmp(gf_node_get_name(n), ID)) return n;
- }
- node_class = gf_xml_sax_peek_node(parser->sax_parser, "DEF", ID, "ProtoInstance", "name", "<par", &is_proto);
- if (!node_class) return NULL;
- n = NULL;
- if (is_proto) {
- GF_Proto *p;
- GF_SceneGraph *sg = parser->load->scene_graph;
- while (1) {
- p = gf_sg_find_proto(sg, 0, node_class);
- if (p) break;
- sg = sg->parent_scene;
- if (!sg) break;
- }
- if (!p) {
- xmt_report(parser, GF_BAD_PARAM, "%s: not a valid/supported proto", node_class);
- gf_free(node_class);
- return NULL;
- }
- n = gf_sg_proto_create_instance(parser->load->scene_graph, p);
- } else {
- tag = xmt_get_node_tag(parser, node_class);
- n = gf_node_new(parser->load->scene_graph, tag);
- }
- gf_free(node_class);
- if (n) {
- u32 nID = xmt_get_node_id(parser, ID);
- gf_node_set_id(n, nID, ID);
- if (!parser->parsing_proto) gf_node_init(n);
- gf_list_add(parser->peeked_nodes, n);
- }
- return n;
- }
- #define XMT_GET_ONE_VAL \
- char value[100]; \
- u32 i; \
- char *str = a_value; \
- if (!str) { \
- xmt_report(parser, GF_BAD_PARAM, "%s: Number expected", name); \
- return 0; \
- } \
- while (str[0] == ' ') str += 1; \
- i = 0; \
- while ((str[i] != ' ') && str[i]) { \
- value[i] = str[i]; \
- i++; \
- } \
- value[i] = 0; \
- while ((str[i] == ' ') && str[i]) i++;
- static u32 xmt_parse_int(GF_XMTParser *parser, const char *name, SFInt32 *val, char *a_value)
- {
- XMT_GET_ONE_VAL
- *val = atoi(value);
- return i;
- }
- static u32 xmt_parse_float(GF_XMTParser *parser, const char *name, SFFloat *val, char *a_value)
- {
- XMT_GET_ONE_VAL
- *val = FLT2FIX(atof(value));
- return i;
- }
- static u32 xmt_parse_time(GF_XMTParser *parser, const char *name, SFTime *val, char *a_value)
- {
- XMT_GET_ONE_VAL
- *val = atof(value);
- return i;
- }
- static u32 xmt_parse_bool(GF_XMTParser *parser, const char *name, SFBool *val, char *a_value)
- {
- XMT_GET_ONE_VAL
- if (!stricmp(value, "1") || !stricmp(value, "true"))
- *val = 1;
- else
- *val = 0;
- return i;
- }
- static u32 xmt_parse_string(GF_XMTParser *parser, const char *name, SFString *val, Bool is_mf, char *a_value)
- {
- char *value;
- char sep[10];
- u32 len;
- u32 i=0;
- u32 k=0;
- char *str = a_value;
- if (!str) return 0;
- /*SF string, no inspection*/
- if (!is_mf) {
- len = (u32) strlen(str);
- if (val->buffer) gf_free(val->buffer);
- val->buffer = NULL;
- if (len) val->buffer = gf_strdup(str);
- return len+1;
- }
- /*now this is the REAL pain:
- X3D allows '"String1" "String2"' and therefore '"String "test""'
- XMT allows '"String1" "String2"' and therefore '"String \"test\""'
- thus translating the string from xml to UTF may screw up the separators !! We need to identify them
- */
- i = 0;
- while ((str[i]==' ') || (str[i]=='\t')) i++;
- if (!strncmp(&str[i], """, 6)) strcpy(sep, """);
- else if (!strncmp(&str[i], "'", 6)) strcpy(sep, "'");
- else if (str[i]=='\'') strcpy(sep, "\'");
- else if (str[i]=='\"') strcpy(sep, "\"");
- /*handle as a single field (old GPAC XMT & any unknown cases...*/
- else {
- len = (u32) strlen(str);
- if (val->buffer) gf_free(val->buffer);
- val->buffer = NULL;
- if (len) val->buffer = gf_strdup(str);
- return len;
- }
- k = 0;
- i += (u32) strlen(sep);
- value = gf_strdup(str);
- if (strncmp(&str[i], sep, strlen(sep))) {
- while (str[i]) {
- if ((str[i] == '\\') && !strncmp(&str[i+1], sep, strlen(sep))) {
- i++;
- continue;
- }
- value[k] = str[i];
- i++;
- k++;
- if (!strncmp(&str[i], sep, strlen(sep)) && (str[i-1] != '\\')) break;
- }
- }
- value[k] = 0;
- len = (u32) strlen(sep) + i;
- if (val->buffer) gf_free(val->buffer);
- val->buffer = NULL;
- if (strlen(value)) val->buffer = gf_strdup(value);
- gf_free(value);
- return len;
- }
- static u32 xmt_parse_url(GF_XMTParser *parser, const char *name, MFURL *val, GF_Node *owner, Bool is_mf, char *a_value)
- {
- SFString sfstr;
- u32 res, idx;
- char value[5000], *tmp;
- /*parse as a string*/
- sfstr.buffer = NULL;
- res = xmt_parse_string(parser, name, &sfstr, is_mf, a_value);
- if (parser->last_error) return res;
- assert(val->count);
- idx = val->count - 1;
- if (val->vals[idx].url) gf_free(val->vals[idx].url);
- val->vals[idx].url = sfstr.buffer;
- val->vals[idx].OD_ID = 0;
- /*empty*/
- if (!val->vals[idx].url) return res;
- /*remove segments & viewpoints info to create OD link*/
- strcpy(value, val->vals[idx].url);
- tmp = strstr(value, "#");
- if (tmp) tmp[0] = 0;
- /*according to XMT-A spec, both 'od:' and 'od://' are tolerated in XMT-A*/
- if (!strnicmp(value, "od://", 5))
- xmt_new_od_link_from_node(parser, value+5, val);
- else if (!strnicmp(value, "od:", 3))
- xmt_new_od_link_from_node(parser, value+3, val);
- else
- xmt_new_od_link_from_node(parser, value, val);
- return res;
- }
- static u32 xmt_parse_script(GF_XMTParser *parser, const char *name, SFScript *val, Bool is_mf, char *a_value)
- {
- SFString sfstr;
- u32 res;
- /*parse as a string*/
- sfstr.buffer = NULL;
- res = xmt_parse_string(parser, name, &sfstr, is_mf, a_value);
- if (parser->last_error) return res;
- if (val->script_text) gf_free(val->script_text);
- val->script_text = (char*)sfstr.buffer;
- return res;
- }
- static void xmt_offset_time(GF_XMTParser *parser, Double *time)
- {
- *time += parser->au_time;
- }
- static void xmt_check_time_offset(GF_XMTParser *parser, GF_Node *n, GF_FieldInfo *info)
- {
- if (!(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
- if (gf_node_get_tag(n) != TAG_ProtoNode) {
- if (!stricmp(info->name, "startTime") || !stricmp(info->name, "stopTime"))
- xmt_offset_time(parser, (Double *)info->far_ptr);
- } else if (gf_sg_proto_field_is_sftime_offset(n, info)) {
- xmt_offset_time(parser, (Double *)info->far_ptr);
- }
- }
- static u32 xmt_parse_sf_field(GF_XMTParser *parser, GF_FieldInfo *info, GF_Node *n, char *a_value)
- {
- u32 res = 0;
- switch (info->fieldType) {
- case GF_SG_VRML_SFINT32:
- res = xmt_parse_int(parser, info->name, (SFInt32 *)info->far_ptr, a_value);
- break;
- case GF_SG_VRML_SFBOOL:
- res = xmt_parse_bool(parser, info->name, (SFBool *)info->far_ptr, a_value);
- break;
- case GF_SG_VRML_SFFLOAT:
- res = xmt_parse_float(parser, info->name, (SFFloat *)info->far_ptr, a_value);
- break;
- case GF_SG_VRML_SFTIME:
- res = xmt_parse_time(parser, info->name, (SFTime *)info->far_ptr, a_value);
- xmt_check_time_offset(parser, n, info);
- break;
- case GF_SG_VRML_SFCOLOR:
- res = xmt_parse_float(parser, info->name, & ((SFColor *)info->far_ptr)->red, a_value);
- res += xmt_parse_float(parser, info->name, & ((SFColor *)info->far_ptr)->green, a_value + res);
- res += xmt_parse_float(parser, info->name, & ((SFColor *)info->far_ptr)->blue, a_value + res);
- break;
- case GF_SG_VRML_SFVEC2F:
- res = xmt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->x, a_value);
- res += xmt_parse_float(parser, info->name, & ((SFVec2f *)info->far_ptr)->y, a_value + res);
- break;
- case GF_SG_VRML_SFVEC3F:
- res = xmt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->x, a_value);
- res += xmt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->y, a_value + res);
- res += xmt_parse_float(parser, info->name, & ((SFVec3f *)info->far_ptr)->z, a_value + res);
- break;
- case GF_SG_VRML_SFROTATION:
- res = xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->x, a_value);
- res += xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->y, a_value + res);
- res += xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->z, a_value + res);
- res += xmt_parse_float(parser, info->name, & ((SFRotation *)info->far_ptr)->q, a_value + res);
- break;
- case GF_SG_VRML_SFSTRING:
- res = xmt_parse_string(parser, info->name, (SFString*)info->far_ptr, 0, a_value);
- if (n && (n->sgprivate->tag==TAG_MPEG4_BitWrapper)) {
- gf_sm_update_bitwrapper_buffer(n, parser->load->fileName);
- }
- break;
- case GF_SG_VRML_SFSCRIPT:
- res = xmt_parse_script(parser, info->name, (SFScript *)info->far_ptr, 0, a_value);
- break;
- case GF_SG_VRML_SFCOMMANDBUFFER:
- {
- SFCommandBuffer *cb = (SFCommandBuffer *)info->far_ptr;
- if (parser->command_buffer) {
- cb->buffer = (unsigned char*)parser->command_buffer;
- } else {
- cb->buffer = (unsigned char*)parser->command;
- }
- parser->command_buffer = cb;
- }
- break;
- case GF_SG_VRML_SFIMAGE:
- {
- u32 k, size, v;
- SFImage *img = (SFImage *)info->far_ptr;
- res = xmt_parse_int(parser, "width", (SFInt32*)&img->width, a_value);
- if (parser->last_error) return res;
- res += xmt_parse_int(parser, "height", (SFInt32*)&img->height, a_value + res);
- if (parser->last_error) return res;
- res += xmt_parse_int(parser, "nbComp", (SFInt32*)&v, a_value + res);
- if (parser->last_error) return res;
- img->numComponents = v;
- size = img->width * img->height * img->numComponents;
- if (img->pixels) gf_free(img->pixels);
- img->pixels = (unsigned char*)gf_malloc(sizeof(char) * size);
- a_value += res;
- res = 0;
- for (k=0; k<size; k++) {
- char *name = "pixels";
- XMT_GET_ONE_VAL
- if (strstr(value, "0x")) sscanf(value, "%x", &v);
- else sscanf(value, "%u", &v);
- switch (img->numComponents) {
- case 1:
- img->pixels[k] = (char) v;
- break;
- case 2:
- img->pixels[k] = (char) (v>>8)&0xFF;
- img->pixels[k+1] = (char) (v)&0xFF;
- k++;
- break;
- case 3:
- img->pixels[k] = (char) (v>>16)&0xFF;
- img->pixels[k+1] = (char) (v>>8)&0xFF;
- img->pixels[k+2] = (char) (v)&0xFF;
- k+=2;
- break;
- case 4:
- img->pixels[k] = (char) (v>>24)&0xFF;
- img->pixels[k+1] = (char) (v>>16)&0xFF;
- img->pixels[k+2] = (char) (v>>8)&0xFF;
- img->pixels[k+3] = (char) (v)&0xFF;
- k+=3;
- break;
- }
- res += i;
- a_value += i;
- }
- }
- break;
- default:
- parser->last_error = GF_NOT_SUPPORTED;
- break;
- }
- return res;
- }
- static void xmt_parse_mf_field(GF_XMTParser *parser, GF_FieldInfo *info, GF_Node *n, char *value)
- {
- u32 res;
- GF_FieldInfo sfInfo;
- sfInfo.fieldType = gf_sg_vrml_get_sf_type(info->fieldType);
- sfInfo.name = info->name;
- gf_sg_vrml_mf_reset(info->far_ptr, info->fieldType);
- if (!value || !strlen(value)) return;
- while (value[0] && !parser->last_error) {
- while (value[0] && value[0] == ' ') value++;
- if (!value[0]) break;
- gf_sg_vrml_mf_append(info->far_ptr, info->fieldType, &sfInfo.far_ptr);
- /*special case for MF type based on string (MFString, MFURL and MFScript), we need to take care
- of all possible forms of XML multi string encoding*/
- if (sfInfo.fieldType == GF_SG_VRML_SFSTRING) {
- res = xmt_parse_string(parser, info->name, (SFString*)sfInfo.far_ptr, 1, value);
- } else if (sfInfo.fieldType == GF_SG_VRML_SFURL) {
- res = xmt_parse_url(parser, info->name, (MFURL *)info->far_ptr, n, 1, value);
- } else if (sfInfo.fieldType == GF_SG_VRML_SFSCRIPT) {
- res = xmt_parse_script(parser, info->name, (SFScript*)sfInfo.far_ptr, 1, value);
- } else {
- res = xmt_parse_sf_field(parser, &sfInfo, n, value);
- }
- if (res) {
- value += res;
- } else {
- break;
- }
- }
- }
- static Bool xmt_has_been_def(GF_XMTParser *parser, char *node_name)
- {
- u32 i, count;
- count = gf_list_count(parser->def_nodes);
- for (i=0; i<count; i++) {
- GF_Node *n = (GF_Node *)gf_list_get(parser->def_nodes, i);
- if (!strcmp(gf_node_get_name(n), node_name)) return 1;
- }
- return 0;
- }
- static u32 xmt_get_route(GF_XMTParser *parser, char *name, Bool del_com)
- {
- u32 i;
- GF_Command *com;
- GF_Route *r = gf_sg_route_find_by_name(parser->load->scene_graph, name);
- if (r) return r->ID;
- i=0;
- while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
- if (com->def_name && !strcmp(com->def_name, name)) {
- if (del_com) gf_list_rem(parser->inserted_routes, i);
- return com->RouteID;
- }
- }
- return 0;
- }
- static Bool xmt_route_id_used(GF_XMTParser *parser, u32 ID)
- {
- u32 i;
- GF_Command *com;
- GF_Route *r = gf_sg_route_find(parser->load->scene_graph, ID);
- if (r) return 1;
- i=0;
- while ((com = (GF_Command *)gf_list_enum(parser->inserted_routes, &i))) {
- if (com->RouteID == ID) return 1;
- }
- return 0;
- }
- static u32 xmt_get_next_route_id(GF_XMTParser *parser)
- {
- u32 ID;
- GF_SceneGraph *sc = parser->load->scene_graph;
- if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
- ID = gf_sg_get_next_available_route_id(sc);
- if (parser->load->ctx && (ID>parser->load->ctx->max_route_id))
- parser->load->ctx->max_route_id = ID;
- return ID;
- }
- static void xmt_resolve_routes(GF_XMTParser *parser)
- {
- GF_Command *com;
- /*resolve all commands*/
- while (1) {
- com = (GF_Command *)gf_list_last(parser->unresolved_routes);
- if (!com) break;
- gf_list_rem_last(parser->unresolved_routes);
- switch (com->tag) {
- case GF_SG_ROUTE_DELETE:
- case GF_SG_ROUTE_REPLACE:
- com->RouteID = xmt_get_route(parser, com->unres_name, 0);
- if (!com->RouteID) {
- xmt_report(parser, GF_BAD_PARAM, "Cannot resolve GF_Route DEF %s", com->unres_name);
- } else {
- com->unresolved = 0;
- }
- gf_free(com->unres_name);
- com->unres_name = NULL;
- break;
- }
- }
- while (gf_list_count(parser->inserted_routes)) gf_list_rem(parser->inserted_routes, 0);
- }
- static void xmt_parse_route(GF_XMTParser *parser, const GF_XMLAttribute *attributes, u32 nb_attributes, Bool is_insert, GF_Command *com)
- {
- GF_Route *r;
- char *toN, *toNF, *fromN, *fromNF, *ID;
- GF_Node *orig, *dest;
- GF_Err e;
- u32 rID, i;
- GF_FieldInfo orig_field, dest_field;
- toN = toNF = fromN = fromNF = ID = NULL;
- for (i=0; i<nb_attributes; i++) {
- GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
- if (!att->value || !strlen(att->value)) continue;
- if (!strcmp(att->name, "fromNode")) fromN = att->value;
- else if (!strcmp(att->name, "fromField")) fromNF = att->value;
- else if (!strcmp(att->name, "toNode")) toN = att->value;
- else if (!strcmp(att->name, "toField")) toNF = att->value;
- else if (!strcmp(att->name, "DEF")) ID = att->value;
- }
- orig = xmt_find_node(parser, fromN);
- if (!orig) {
- xmt_report(parser, GF_BAD_PARAM, "ROUTE: Cannot find origin node %s", fromN);
- return;
- }
- e = gf_node_get_field_by_name(orig, fromNF, &orig_field);
- if ((e != GF_OK) && strstr(fromNF, "_changed")) {
- char *sz = strstr(fromNF, "_changed");
- sz[0] = 0;
- e = gf_node_get_field_by_name(orig, fromNF, &orig_field);
- }
- if (e!=GF_OK) {
- xmt_report(parser, GF_BAD_PARAM, "%s is not an attribute of node %s", fromNF, fromN);
- return;
- }
- dest = xmt_find_node(parser, toN);
- if (!dest) {
- xmt_report(parser, GF_BAD_PARAM, "ROUTE: Cannot find destination node %s", toN);
- return;
- }
- e = gf_node_get_field_by_name(dest, toNF, &dest_field);
- if ((e != GF_OK) && !strnicmp(toNF, "set_", 4)) e = gf_node_get_field_by_name(dest, &toNF[4], &dest_field);
- if (e != GF_OK) {
- xmt_report(parser, GF_BAD_PARAM, "%s is not an attribute of node %s", toNF, toN);
- return;
- }
- rID = 0;
- if (ID && strlen(ID)) {
- rID = xmt_get_route(parser, ID, 0);
- if (!rID && (ID[0]=='R') ) {
- rID = atoi(&ID[1]);
- if (rID) {
- rID++;
- if (xmt_route_id_used(parser, rID)) rID = 0;
- }
- }
- if (!rID) rID = xmt_get_next_route_id(parser);
- }
- if (com) {
- /*for insert command*/
- if (rID) {
- com->RouteID = rID;
- com->def_name = gf_strdup(ID);
- /*whenever not inserting in graph, keep track of max defined ID*/
- gf_sg_set_max_defined_route_id(parser->load->scene_graph, rID);
- if (rID>parser->load->ctx->max_route_id) parser->load->ctx->max_route_id = rID;
- }
- com->fromNodeID = gf_node_get_id(orig);
- com->fromFieldIndex = orig_field.fieldIndex;
- com->toNodeID = gf_node_get_id(dest);
- com->toFieldIndex = dest_field.fieldIndex;
- return;
- }
- r = gf_sg_route_new(parser->load->scene_graph, orig, orig_field.fieldIndex, dest, dest_field.fieldIndex);
- if (rID) {
- gf_sg_route_set_id(r, rID);
- gf_sg_route_set_name(r, ID);
- }
- }
- static void xmt_update_timenode(GF_XMTParser *parser, GF_Node *node)
- {
- if (!(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;
- switch (gf_node_get_tag(node)) {
- case TAG_MPEG4_AnimationStream:
- xmt_offset_time(parser, & ((M_AnimationStream*)node)->startTime);
- xmt_offset_time(parser, & ((M_AnimationStream*)node)->stopTime);
- break;
- case TAG_MPEG4_AudioBuffer:
- xmt_offset_time(parser, & ((M_AudioBuffer*)node)->startTime);
- xmt_offset_time(parser, & ((M_AudioBuffer*)node)->stopTime);
- break;
- case TAG_MPEG4_AudioClip:
- xmt_offset_time(parser, & ((M_AudioClip*)node)->startTime);
- xmt_offset_time(parser, & ((M_AudioClip*)node)->stopTime);
- break;
- case TAG_MPEG4_AudioSource:
- xmt_offset_time(parser, & ((M_AudioSource*)node)->startTime);
- xmt_offset_time(parser, & ((M_AudioSource*)node)->stopTime);
- break;
- case TAG_MPEG4_MovieTexture:
- xmt_offset_time(parser, & ((M_MovieTexture*)node)->startTime);
- xmt_offset_time(parser, & ((M_MovieTexture*)node)->stopTime);
- break;
- case TAG_MPEG4_TimeSensor:
- xmt_offset_time(parser, & ((M_TimeSensor*)node)->startTime);
- xmt_offset_time(parser, & ((M_TimeSensor*)node)->stopTime);
- break;
- case TAG_ProtoNode:
- {
- u32 i, nbFields;
- GF_FieldInfo inf;
- nbFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL);
- for (i=0; i<nbFields; i++) {
- gf_node_get_field(node, i, &inf);
- if (inf.fieldType != GF_SG_VRML_SFTIME) continue;
- xmt_check_time_offset(parser, node, &inf);
- }
- }
- break;
- }
- }
- static void xmt_strip_name(const char *in, char *out)
- {
- while (in[0]==' ') in++;
- strcpy(out, in);
- while (out[strlen(out)-1] == ' ') out[strlen(out)-1] = 0;
- }
- static u32 xmt_get_ft_by_name(const char *_name)
- {
- char name[1024];
- xmt_strip_name(_name, name);
- if (!strcmp(name, "Boolean") || !strcmp(name, "SFBool")) return GF_SG_VRML_SFBOOL;
- else if (!strcmp(name, "Integer") || !strcmp(name, "SFInt32")) return GF_SG_VRML_SFINT32;
- else if (!strcmp(name, "Color") || !strcmp(name, "SFColor")) return GF_SG_VRML_SFCOLOR;
- else if (!strcmp(name, "Vector2") || !strcmp(name, "SFVec2f")) return GF_SG_VRML_SFVEC2F;
- else if (!strcmp(name, "Image") || !strcmp(name, "SFImage")) return GF_SG_VRML_SFIMAGE;
- else if (!strcmp(name, "Time") || !strcmp(name, "SFTime")) return GF_SG_VRML_SFTIME;
- else if (!strcmp(name, "Float") || !strcmp(name, "SFFloat")) return GF_SG_VRML_SFFLOAT;
- else if (!strcmp(name, "Vector3") || !strcmp(name, "SFVec3f")) return GF_SG_VRML_SFVEC3F;
- else if (!strcmp(name, "Rotation") || !strcmp(name, "SFRotation")) return GF_SG_VRML_SFROTATION;
- else if (!strcmp(name, "String") || !strcmp(name, "SFString")) return GF_SG_VRML_SFSTRING;
- else if (!strcmp(name, "Node") || !strcmp(name, "SFNode")) return GF_SG_VRML_SFNODE;
- else if (!strcmp(name, "Booleans") || !strcmp(name, "MFBool")) return GF_SG_VRML_MFBOOL;
- else if (!strcmp(name, "Integers") || !strcmp(name, "MFInt32")) return GF_SG_VRML_MFINT32;
- else if (!strcmp(name, "Colors") || !strcmp(name, "MFColor")) return GF_SG_VRML_MFCOLOR;
- else if (!strcmp(name, "Vector2s") || !strcmp(name, "Vector2Array") || !strcmp(name, "MFVec2f")) return GF_SG_VRML_MFVEC2F;
- else if (!strcmp(name, "Images") || !strcmp(name, "MFImage")) return GF_SG_VRML_MFIMAGE;
- else if (!strcmp(name, "Times") || !strcmp(name, "MFTime")) return GF_SG_VRML_MFTIME;
- else if (!strcmp(name, "Floats") || !strcmp(name, "MFFloat")) return GF_SG_VRML_MFFLOAT;
- else if (!strcmp(name, "Vector3s") || !strcmp(name, "Vector3Array") || !strcmp(name, "MFVec3f")) return GF_SG_VRML_MFVEC3F;
- else if (!strcmp(name, "Rotations") || !strcmp(name, "MFRotation")) return GF_SG_VRML_MFROTATION;
- else if (!strcmp(name, "Strings") || !strcmp(name, "MFString")) return GF_SG_VRML_MFSTRING;
- else if (!strcmp(name, "Nodes") || !strcmp(name, "MFNode")) return GF_SG_VRML_MFNODE;
- else if (!strcmp(name, "SFColorRGBA")) return GF_SG_VRML_SFCOLORRGBA;
- else if (!strcmp(name, "MFColorRGBA")) return GF_SG_VRML_MFCOLORRGBA;
- else if (!strcmp(name, "SFDouble")) return GF_SG_VRML_SFDOUBLE;
- else if (!strcmp(name, "MFDouble")) return GF_SG_VRML_MFDOUBLE;
- else if (!strcmp(name, "SFVec3d")) return GF_SG_VRML_SFVEC3D;
- else if (!strcmp(name, "MFVec3d")) return GF_SG_VRML_MFVEC3D;
- else if (!strcmp(name, "SFVec2d")) return GF_SG_VRML_SFVEC2D;
- else if (!strcmp(name, "MFVec2d")) return GF_SG_VRML_MFVEC2D;
- else return GF_SG_VRML_UNKNOWN;
- }
- static u32 xmt_get_script_et_by_name(const char *_name)
- {
- char name[1024];
- xmt_strip_name((char *)_name, name);
- if (!strcmp(name, "eventIn") || !strcmp(name, "inputOnly") ) return GF_SG_SCRIPT_TYPE_EVENT_IN;
- else if (!strcmp(name, "eventOut") || !strcmp(name, "outputOnly")) return GF_SG_SCRIPT_TYPE_EVENT_OUT;
- else if (!strcmp(name, "field") || !strcmp(name, "initializeOnly") ) return GF_SG_SCRIPT_TYPE_FIELD;
- else return GF_SG_EVENT_UNKNOWN;
- }
- static u32 xmt_get_et_by_name(const char *_name)
- {
- char name[1024];
- xmt_strip_name((char *)_name, name);
- if (!strcmp(name, "eventIn") || !strcmp(name, "inputOnly") ) return GF_SG_EVENT_IN;
- else if (!strcmp(name, "eventOut") || !strcmp(name, "outputOnly")) return GF_SG_EVENT_OUT;
- else if (!strcmp(name, "field") || !strcmp(name, "initializeOnly") ) return GF_SG_EVENT_FIELD;
- else if (!strcmp(name, "exposedField") || !strcmp(name, "inputOutput")) return GF_SG_EVENT_EXPOSED_FIELD;
- else return GF_SG_EVENT_UNKNOWN;
- }
- static void xmt_parse_script_field(GF_XMTParser *parser, GF_Node *node, const GF_XMLAttribute *attributes, u32 nb_attributes)
- {
- GF_ScriptField *scfield;
- GF_FieldInfo field;
- char *val = NULL;
- u32 fieldType, eventType, i;
- char *fieldName = NULL;
- fieldType = eventType = 0;
- val = NULL;
- for (i=0; i<nb_attributes; i++) {
- GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
- if (!att->value || !strlen(att->value)) continue;
- if (!strcmp(att->name, "name")) fieldName = att->value;
- else if (!strcmp(att->name, "type")) fieldType = xmt_get_ft_by_name(att->value);
- else if (!strcmp(att->name, "vrml97Hint") || !strcmp(att->name, "accessType")) eventType = xmt_get_script_et_by_name(att->value);
- else if (strstr(att->name, "value") || strstr(att->name, "Value")) val = att->value;
- }
- scfield = gf_sg_script_field_new(node, eventType, fieldType, fieldName);
- if (!scfield) {
- xmt_report(parser, GF_BAD_PARAM, "Cannot create script field - please check syntax");
- return;
- }
- if (val) {
- gf_node_get_field_by_name(node, fieldName, &field);
- if (gf_sg_vrml_is_sf_field(fieldType)) {
- xmt_parse_sf_field(parser, &field, node, val);
- } else {
- xmt_parse_mf_field(parser, &field, node, val);
- }
- }
- }
- static u32 xmt_get_next_proto_id(GF_XMTParser *parser)
- {
- u32 ID;
- GF_SceneGraph *sc = parser->load->scene_graph;
- if (parser->parsing_proto) sc = gf_sg_proto_get_graph(parser->parsing_proto);
- ID = gf_sg_get_next_available_proto_id(sc);
- if (parser->load->ctx && (ID>parser->load->ctx->max_node_id))
- parser->load->ctx->max_proto_id = ID;
- return ID;
- }
- static void xmt_parse_proto(GF_XMTParser *parser, const GF_XMLAttribute *attributes, u32 nb_attributes, GF_List *proto_list)
- {
- GF_FieldInfo info;
- GF_Proto *proto;
- char *szName, *extURL;
- u32 ID, i;
- ID = 0;
- szName = extURL = NULL;
- for (i=0; i<nb_attributes; i++) {
- GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
- if (!att->value || !strlen(att->value)) continue;
- if (!strcmp(att->name, "name")) szName = att->value;
- else if (!strcmp(att->name, "protoID")) ID = atoi(att->value);
- else if (!strcmp(att->name, "locations")) extURL = att->value;
- else if (!strcmp(att->name, "url")) extURL = att->value;
- }
- ID = xmt_get_next_proto_id(parser);
- proto = gf_sg_proto_new(parser->load->scene_graph, ID, szName, proto_list ? 1 : 0);
- if (proto_list) gf_list_add(proto_list, proto);
- if (parser->load->ctx && (parser->load->ctx->max_proto_id<ID)) parser->load->ctx->max_proto_id=ID;
- /*store previous proto*/
- proto->userpriv = parser->parsing_proto;
- parser->parsing_proto = proto;
- parser->load->scene_graph = gf_sg_proto_get_graph(proto);
- if (extURL) {
- info.fieldType = GF_SG_VRML_MFURL;
- info.far_ptr = &proto->ExternProto;
- info.name = "ExternURL";
- xmt_parse_mf_field(parser, &info, NULL, extURL);
- }
- }
- static u32 xmt_get_protofield_qp_type(const char *QP_Type)
- {
- #ifndef GPAC_DISABLE_BIFS
- if (!strcmp(QP_Type, "position3D")) return QC_3DPOS;
- else if (!strcmp(QP_Type, "position2D")) return QC_2DPOS;
- else if (!strcmp(QP_Type, "drawingOrder")) return QC_ORDER;
- else if (!strcmp(QP_Type, "color")) return QC_COLOR;
- else if (!strcmp(QP_Type, "textureCoordinate")) return QC_TEXTURE_COORD;
- else if (!strcmp(QP_Type, "angle")) return QC_ANGLE;
- else if (!strcmp(QP_Type, "scale")) return QC_SCALE;
- else if (!strcmp(QP_Type, "keys")) return QC_INTERPOL_KEYS;
- else if (!strcmp(QP_Type, "normals")) return QC_NORMALS;
- else if (!strcmp(QP_Type, "rotations")) return QC_ROTATION;
- else if (!strcmp(QP_Type, "size3D")) return QC_SIZE_3D;
- else if (!strcmp(QP_Type, "size2D")) return QC_SIZE_2D;
- else if (!strcmp(QP_Type, "linear")) return QC_LINEAR_SCALAR;
- else if (!strcmp(QP_Type, "coordIndex")) return QC_COORD_INDEX;
- #endif
- return 0;
- }
- static GF_Err x3d_get_default_container(GF_Node *par, GF_Node *n, GF_FieldInfo *info)
- {
- u32 i, count;
- count = gf_node_get_field_count(par);
- /*get the first field/exposedField accepting this child*/
- for (i=0; i<count; i++) {
- gf_node_get_field(par, i, info);
- if ((info->fieldType!=GF_SG_VRML_SFNODE) && (info->fieldType!=GF_SG_VRML_MFNODE)) continue;
- if ((info->eventType==GF_SG_EVENT_OUT) || (info->eventType==GF_SG_EVENT_IN)) continue;
- if (gf_node_in_table(n, info->NDTtype)) return GF_OK;
- }
- return GF_BAD_PARAM;
- }
- static GF_Node *xmt_parse_element(GF_XMTParser *parser, char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes, XMTNodeStack *parent)
- {
- GF_Err e;
- GF_FieldInfo info;
- u32 tag, i, ID;
- Bool register_def = 0;
- Bool is_script = 0;
- GF_Node *node;
- GF_FieldInfo container;
- char *def_name;
- GF_Proto *proto = NULL;
- node = NULL;
- if (!strcmp(name, "NULL")) return NULL;
- if (!strcmp(name, "ROUTE")) {
- if (!parser->parsing_proto && (parser->doc_type==1) ) {
- GF_Command *sgcom = gf_sg_command_new(parser->load->scene_graph, GF_SG_ROUTE_INSERT);
- gf_list_add(parser->scene_au->commands, sgcom);
- xmt_parse_route(parser, attributes, nb_attributes, 0, sgcom);
- if (sgcom->RouteID) gf_list_add(parser->inserted_routes, sgcom);
- } else {
- xmt_parse_route(parser, attributes, nb_attributes, 0, NULL);
- }
- return NULL;
- }
- if (parent && parent->node && ((parent->node->sgprivate->tag==TAG_MPEG4_Script)
- #ifndef GPAC_DISABLE_X3D
- || (parent->node->sgprivate->tag==TAG_X3D_Script)
- #endif
- ) ) {
- is_script = 1;
- if (!strcmp(name, "field")) {
- xmt_parse_script_field(parser, parent->node, attributes, nb_attributes);
- return NULL;
- }
- else if (!strcmp(name, "node") || !strcmp(name, "nodes") ) return NULL;
- }
- /*proto declaration*/
- if (!strcmp(name, "ProtoDeclare") || !strcmp(name, "ExternProtoDeclare")) {
- if (!parser->parsing_proto && parser->command && !parser->command->new_proto_list) parser->command->new_proto_list = gf_list_new();
- xmt_parse_proto(parser, attributes, nb_attributes, (!parser->parsing_proto && parser->command) ? parser->command->new_proto_list : NULL);
- return NULL;
- }
- /*proto parsing*/
- if (parser->parsing_proto) {
- if (!strcmp(name, "IS"))
- return NULL;
- if (!strcmp(name, "field")) {
- char *fieldName = NULL;
- char *value = NULL;
- u32 fType, eType;
- fType = eType = 0;
- for (i=0; i<nb_attributes; i++) {
- GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
- if (!att->value || !strlen(att->value)) continue;
- if (!strcmp(att->name, "name")) fieldName = att->value;
- else if (!strcmp(att->name, "type")) fType = xmt_get_ft_by_name(att->value);
- else if (!strcmp(att->name, "vrml97Hint") || !strcmp(att->name, "accessType") ) eType = xmt_get_et_by_name(att->value);
- else if (strstr(att->name, "value") || strstr(att->name, "Value")) value = att->value;
- }
- parser->proto_field = gf_sg_proto_field_new(parser->parsing_proto, fType, eType, fieldName);
- if (value && strlen(value)) {
- gf_sg_proto_field_get_field(parser->proto_field, &info);
- if (gf_sg_vrml_is_sf_field(fType)) {
- xmt_parse_sf_field(parser, &info, NULL, value);
- } else {
- xmt_parse_mf_field(parser, &info, NULL, value);
- }
- } else if (gf_sg_vrml_get_sf_type(fType) != GF_SG_VRML_SFNODE) {
- /*value not specified for exter proto*/
- }
- /*SF/MFNode proto field: push node stack with container info but no parent*/
- else {
- XMTNodeStack *pf_stack;
- GF_SAFEALLOC(pf_stack, XMTNodeStack);
- gf_sg_proto_field_get_field(parser->proto_field, &pf_stack->container_field);
- gf_list_add(parser->nodes, pf_stack);
- }
- return NULL;
- }
- /*X3D style*/
- if (!strcmp(name, "ProtoInterface") || !strcmp(name, "ProtoBody"))
- return NULL;
- /*XMT1 decl for SFNode proto fields*/
- if (parser->proto_field && (!strcmp(name, "node") || !strcmp(name, "nodes")) )
- return NULL;
- /*anim & QP info */
- if (parser->proto_field && !strcmp(name, "InterfaceCodingParameters")) {
- u32 qp_type, nbBits, hasMinMax, qp_sftype;
- Fixed ftMin, ftMax;
- ftMin = ftMax = 0;
- qp_type = hasMinMax = nbBits = 0;
- for (i=0; i<nb_attributes; i++) {
- GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
- if (!att->value || !strlen(att->value)) continue;
- if (!strcmp(att->name, "quantCategory")) qp_type = xmt_get_protofield_qp_type(att->value);
- else if (!strcmp(att->name, "nbBits")) nbBits = atoi(att->value);
- else if (!strncmp(att->name, "position3DM", 11) || !strncmp(att->name, "position2DM", 11)
- || !strncmp(att->name, "drawOrderM", 10) || !strncmp(att->name, "colorM", 6)
- || !strncmp(att->name, "textureCoordinateM", 18) || !strncmp(att->name, "angleM", 6)
- || !strncmp(att->name, "scaleM", 6) || !strncmp(att->name, "keyM", 4) || !strncmp(att->name, "sizeM", 5)
- ) {
- hasMinMax = 1;
- if (strstr(att->name, "Min")) xmt_parse_float(parser, att->name, &ftMin, att->value);
- else xmt_parse_float(parser, att->name, &ftMax, att->value);
- }
- }
- if (gf_sg_vrml_get_sf_type(parser->proto_field->FieldType) == GF_SG_VRML_SFINT32) {
- qp_sftype = GF_SG_VRML_SFINT32;
- } else {
- qp_sftype = GF_SG_VRML_SFFLOAT;
- }
- gf_bifs_proto_field_set_aq_info(parser->proto_field, qp_type, hasMinMax, qp_sftype, &ftMin, &ftMax, nbBits);
- return NULL;
- }
- /*connect */
- if (!strcmp(name, "connect")) {
- GF_ProtoFieldInterface *pf;
- Bool is_script = 0;
- GF_FieldInfo pfield, nfield;
- char *atField, *atProtoField;
- XMTNodeStack *last = (XMTNodeStack*)gf_list_last(parser->nodes);
- if (!last) {
- xmt_report(parser, GF_OK, "connect: no parent node specified - skipping");
- return NULL;
- }
- atField = atProtoField = NULL;
- for (i=0; i<nb_attributes; i++) {
- GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
- if (!att->value || !strlen(att->value)) continue;
- if (!strcmp(att->name, "nodeField")) atField = att->value;
- else if (!strcmp(att->name, "protoField")) atProtoField = att->value;
- }
- if (!atField) {
- xmt_report(parser, GF_OK, "connect: Missing node field - skipping");
- return NULL;
- }
- if (!atProtoField) {
- xmt_report(parser, GF_OK, "connect: Missing proto field - skipping");
- return NULL;
- }
- if ( (e = gf_node_get_field_by_name(last->node, atField, &nfield)) != GF_OK) {
- u32 l_tag = gf_node_get_tag(last->node);
- if ((l_tag!=TAG_MPEG4_Script)
- #ifndef GPAC_DISABLE_X3D
- && (l_tag!=TAG_X3D_Script)
- #endif
- ) {
- xmt_report(parser, e, "connect: %s not an field of node %s", atField, gf_node_get_class_name(last->node) );
- return NULL;
- }
- is_script = 1;
- }
- pf = gf_sg_proto_field_find_by_name(parser->parsing_proto, atProtoField);
- if (!pf) {
- xmt_report(parser, GF_BAD_PARAM, "connect: Proto field %s is not defined", atProtoField);
- return NULL;
- }
- gf_sg_proto_field_get_field(pf, &pfield);
- if (is_script) {
- gf_sg_script_field_new(last->node, pfield.eventType, pfield.fieldType, atField);
- gf_node_get_field_by_name(last->node, atField, &nfield);
- }
- e = gf_sg_proto_field_set_ised(parser->parsing_proto, pfield.fieldIndex, last->node, nfield.fieldIndex);
- if (e) xmt_report(parser, GF_BAD_PARAM, "connect: %s", gf_error_to_string(e));
- return NULL;
- }
- }
- /*proto instance field*/
- if (!strcmp(na…
Large files files are truncated, but you can click here to view the full file