📄 loader_xmt.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * 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 <gpac/scene_manager.h>#include <gpac/constants.h>#include <gpac/utf.h>#include <gpac/xml.h>#include <gpac/internal/bifs_dev.h>#include <gpac/internal/scenegraph_dev.h>#include <gpac/nodes_x3d.h>/*for QP types*/#include "../bifs/quant.h"typedef struct{ GF_Node *node; GF_FieldInfo container_field; GF_ChildNodeItem *last;} XMTNodeStack;typedef struct{ /*1: XMT-A, 2: X3D, 3: XMT-O (not supported yet) */ u32 doc_type; /*0: not init, 1: header, 2: body*/ u32 doc_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; 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_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) { 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, u32 done, u32 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->esd->ESID == ESID) return 0; } return 1;}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, "%d", &ID) == 1) { char szURL[20]; sprintf(szURL, "%d", 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 = 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) free(l2->desc_name); gf_list_del(l2->mf_urls); 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 = 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; 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, "%d", &ID) == 1) { char szURL[20]; sprintf(szURL, "%d", ID); if (strcmp(szURL, name)) { ID = 0; } else { name = NULL; } } else ID = 0; 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 = 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) ( ( ((u32) esdl) >> 16) | ( ((u32)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 = 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 = 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 = strdup(es_name); else esdl->Depends_Name = 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, "%d", &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, "%d", &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; } } /*create a temp one*/ esdl = (XMT_ESDLink *)malloc(sizeof(XMT_ESDLink)); memset(esdl, 0, sizeof(XMT_ESDLink)); esdl->ESID = (u16) ( ((u32) esdl) >> 16) | ( ((u32)esdl) & 0x0000FFFF); if (!strnicmp(stream_name, "es", 2)) esdl->ESID = atoi(&stream_name[2]); esdl->desc_name = 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) free(esdl->desc_name); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -