📄 scene_dump.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/internal/scenegraph_dev.h>#include <gpac/nodes_x3d.h>#include <gpac/nodes_svg_da.h>#ifndef GPAC_READ_ONLY#ifndef __SYMBIAN32__#include <wchar.h>#endif/*for QP types*/#include "../bifs/quant.h"struct _scenedump{ /*the scene we're dumping - set at each SceneReplace or mannually*/ GF_SceneGraph *sg; /*the proto we're dumping*/ GF_Proto *current_proto; FILE *trace; u32 indent; u32 dump_mode; u16 CurrentESID; u8 ind_char; Bool XMLDump, X3DDump, LSRDump; GF_List *dump_nodes; /*nodes created through conditionals while parsing but not applied*/ GF_List *mem_def_nodes; Bool skip_scene_replace; /*for route insert/replace in conditionals in current scene replace*/ GF_List *current_com_list; GF_List *inserted_routes; Bool in_text;};GF_Err DumpRoute(GF_SceneDumper *sdump, GF_Route *r, u32 dump_type);void DumpNode(GF_SceneDumper *sdump, GF_Node *node, Bool in_list, char *fieldContainer);#ifndef GPAC_DISABLE_SVGvoid SD_DumpSVG_Element(GF_SceneDumper *sdump, GF_Node *n, GF_Node *parent, Bool is_root);#endifGF_Err gf_sm_dump_command_list(GF_SceneDumper *sdump, GF_List *comList, u32 indent, Bool skip_first_replace);GF_EXPORTGF_SceneDumper *gf_sm_dumper_new(GF_SceneGraph *graph, char *rad_name, char indent_char, u32 dump_mode){ GF_SceneDumper *tmp; if (!graph) return NULL; GF_SAFEALLOC(tmp, GF_SceneDumper); /*store original*/ tmp->dump_mode = dump_mode;#ifndef GPAC_DISABLE_SVG if ((graph->RootNode && (graph->RootNode->sgprivate->tag>=GF_NODE_RANGE_LAST_VRML) ) || (dump_mode==GF_SM_DUMP_LASER) || (dump_mode==GF_SM_DUMP_SVG)) { tmp->XMLDump = 1; if (dump_mode==GF_SM_DUMP_LASER) tmp->LSRDump = 1; if (rad_name) { strcat(rad_name, tmp->LSRDump ? ".xsr" : ".svg"); tmp->trace = fopen(rad_name, "wt"); if (!tmp->trace) { free(tmp); return NULL; } } else { tmp->trace = stdout; } } else #endif { if (dump_mode==GF_SM_DUMP_AUTO_TXT) { if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) { dump_mode = GF_SM_DUMP_BT; } else if (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_X3D) { dump_mode = GF_SM_DUMP_X3D_VRML; } } else if (dump_mode==GF_SM_DUMP_AUTO_XML) { if (!graph->RootNode || (graph->RootNode->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) ) { dump_mode = GF_SM_DUMP_XMTA; } else { dump_mode = GF_SM_DUMP_X3D_XML; } } if (rad_name) { switch (dump_mode) { case GF_SM_DUMP_X3D_XML: strcat(rad_name, ".x3d"); tmp->XMLDump = 1; tmp->X3DDump = 1; break; case GF_SM_DUMP_XMTA: strcat(rad_name, ".xmt"); tmp->XMLDump = 1; break; case GF_SM_DUMP_X3D_VRML: strcat(rad_name, ".x3dv"); tmp->X3DDump = 1; break; case GF_SM_DUMP_VRML: strcat(rad_name, ".wrl"); break; default: strcat(rad_name, ".bt"); break; } tmp->trace = fopen(rad_name, "wt"); if (!tmp->trace) { free(tmp); return NULL; } } else { tmp->trace = stdout; switch (dump_mode) { case GF_SM_DUMP_X3D_XML: tmp->XMLDump = 1; tmp->X3DDump = 1; break; case GF_SM_DUMP_XMTA: tmp->XMLDump = 1; break; case GF_SM_DUMP_X3D_VRML: tmp->X3DDump = 1; break; default: break; } } } tmp->ind_char = indent_char; tmp->dump_nodes = gf_list_new(); tmp->mem_def_nodes = gf_list_new(); tmp->inserted_routes = gf_list_new(); tmp->sg = graph; return tmp;}GF_EXPORTvoid gf_sm_dumper_del(GF_SceneDumper *sdump){ gf_list_del(sdump->dump_nodes); while (gf_list_count(sdump->mem_def_nodes)) { GF_Node *tmp = (GF_Node *)gf_list_get(sdump->mem_def_nodes, 0); gf_list_rem(sdump->mem_def_nodes, 0); gf_node_unregister(tmp, NULL); } gf_list_del(sdump->mem_def_nodes); gf_list_del(sdump->inserted_routes); if (sdump->trace != stdout) fclose(sdump->trace); free(sdump);}void SD_SetupDump(GF_SceneDumper *sdump, GF_Descriptor *root_od){ if (sdump->XMLDump) { fprintf(sdump->trace, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fprintf(sdump->trace, "<!-- %s Scene Dump - GPAC version " GPAC_VERSION " -->\n", (sdump->dump_mode==GF_SM_DUMP_SVG) ? "SVG" : (sdump->dump_mode==GF_SM_DUMP_LASER) ? "LASeR" : sdump->X3DDump ? "X3D" : "XMT-A" ); } if (sdump->dump_mode==GF_SM_DUMP_SVG) return; if (sdump->LSRDump) { fprintf(sdump->trace, "<saf:SAFSession xmlns:saf=\"urn:mpeg:mpeg4:SAF:2005\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:lsr=\"urn:mpeg:mpeg4:LASeR:2005\" xmlns=\"http://www.w3.org/2000/svg\">\n"); if (root_od) { GF_ObjectDescriptor *iod = (GF_ObjectDescriptor *)root_od; u32 i, count; fprintf(sdump->trace, "<saf:sceneHeader>\n"); count = gf_list_count(iod->ESDescriptors); for (i=0; i<count; i++) { GF_LASERConfig lsrcfg; GF_ESD *esd = (GF_ESD *)gf_list_get(iod->ESDescriptors, i); if (esd->decoderConfig->streamType != GF_STREAM_SCENE) continue; if (esd->decoderConfig->objectTypeIndication != 0x09) continue; if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) continue; gf_odf_get_laser_config(esd->decoderConfig->decoderSpecificInfo, &lsrcfg); gf_odf_dump_desc(&lsrcfg, sdump->trace, 1, 1); } fprintf(sdump->trace, "</saf:sceneHeader>\n"); } return; } if (!sdump->X3DDump) { /*setup XMT*/ if (sdump->XMLDump) { fprintf(sdump->trace, "<XMT-A xmlns=\"urn:mpeg:mpeg4:xmta:schema:2002\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:mpeg:mpeg4:xmta:schema:2002 xmt-a.xsd\">\n"); fprintf(sdump->trace, " <Header>\n"); if (root_od) gf_odf_dump_desc(root_od, sdump->trace, 1, 1); fprintf(sdump->trace, " </Header>\n"); fprintf(sdump->trace, " <Body>\n"); if (!root_od) { fprintf(sdump->trace, " <Replace>\n"); fprintf(sdump->trace, " <Scene>\n"); } } else { if (sdump->dump_mode==GF_SM_DUMP_VRML) { fprintf(sdump->trace, "#VRML V2.0\n"); } else { /*dump root OD*/ if (root_od) gf_odf_dump_desc(root_od, sdump->trace, 0, 0); } fprintf(sdump->trace, "\n"); } } else { if (sdump->XMLDump) { fprintf(sdump->trace, "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n"); fprintf(sdump->trace, "<X3D xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.0.xsd\" version=\"3.0\">\n"); fprintf(sdump->trace, "<head>\n"); fprintf(sdump->trace, "<meta content=\"X3D File Converted/Dumped by GPAC Version %s\" name=\"generator\"/>\n", GPAC_VERSION); fprintf(sdump->trace, "</head>\n"); fprintf(sdump->trace, "<Scene>\n"); } else { fprintf(sdump->trace, "#X3D V3.0\n\n"); } }}void SD_FinalizeDump(GF_SceneDumper *sdump, GF_Descriptor *root_od){ if (sdump->dump_mode==GF_SM_DUMP_SVG) return; if (sdump->LSRDump) { fprintf(sdump->trace, "<saf:endOfSAFSession/>\n</saf:SAFSession>\n"); return; } if (!sdump->XMLDump) return; if (!sdump->X3DDump) { if (!root_od) { fprintf(sdump->trace, " </Scene>\n"); fprintf(sdump->trace, " </Replace>\n"); } fprintf(sdump->trace, " </Body>\n"); fprintf(sdump->trace, "</XMT-A>\n"); } else { fprintf(sdump->trace, "</Scene>\n"); fprintf(sdump->trace, "</X3D>\n"); }}Bool SD_IsDEFNode(GF_SceneDumper *sdump, GF_Node *node){ s32 i = gf_list_find(sdump->dump_nodes, node); if (i>=0) return 0; gf_list_add(sdump->dump_nodes, node); return 1;}GF_Node *SD_FindNode(GF_SceneDumper *sdump, u32 ID){ GF_Node *ret = gf_sg_find_node(sdump->sg, ID); if (ret) return ret; return NULL;}#define DUMP_IND(sdump) \ if (sdump->trace) { \ u32 z; \ for (z=0; z<sdump->indent; z++) fprintf(sdump->trace, "%c", sdump->ind_char); \ }void StartElement(GF_SceneDumper *sdump, const char *name){ if (!sdump->trace) return; DUMP_IND(sdump); if (!sdump->XMLDump) { fprintf(sdump->trace, "%s {\n", name); } else if (sdump->XMLDump) { fprintf(sdump->trace, "<%s", name); }}void EndElementHeader(GF_SceneDumper *sdump, Bool has_sub_el){ if (!sdump->trace) return; if (sdump->XMLDump) { if (has_sub_el) { fprintf(sdump->trace, ">\n"); } else { fprintf(sdump->trace, "/>\n"); } }}void EndElement(GF_SceneDumper *sdump, const char *name, Bool had_sub_el){ if (!sdump->trace) return; if (!sdump->XMLDump) { DUMP_IND(sdump); fprintf(sdump->trace, "}\n"); } else { if (had_sub_el) { DUMP_IND(sdump); fprintf(sdump->trace, "</%s>\n", name); } }}void StartAttribute(GF_SceneDumper *sdump, char *name){ if (!sdump->trace) return; if (!sdump->XMLDump) { DUMP_IND(sdump); fprintf(sdump->trace, "%s ", name); } else { fprintf(sdump->trace, " %s=\"", name); }}void EndAttribute(GF_SceneDumper *sdump){ if (!sdump->trace) return; if (!sdump->XMLDump) { fprintf(sdump->trace, "\n"); } else { fprintf(sdump->trace, "\""); }}void StartList(GF_SceneDumper *sdump, char *name){ if (!sdump->trace) return; DUMP_IND(sdump); if (!sdump->XMLDump) { if (name) fprintf(sdump->trace, "%s [\n", name); else fprintf(sdump->trace, "[\n"); } else { fprintf(sdump->trace, "<%s>\n", name); }}void EndList(GF_SceneDumper *sdump, char *name){ if (!sdump->trace) return; DUMP_IND(sdump); if (!sdump->XMLDump) { fprintf(sdump->trace, "]\n"); } else { fprintf(sdump->trace, "</%s>\n", name); }}void DumpNodeID(GF_SceneDumper *sdump, GF_Node *node){ u32 id; const char *node_name; if (!sdump->trace) return; /*FIXME - optimize id/name fetch*/ node_name = gf_node_get_name_and_id(node, &id); if (node_name) fprintf(sdump->trace, "%s", node_name); else fprintf(sdump->trace, "N%d", id - 1);}Bool DumpFindRouteName(GF_SceneDumper *sdump, u32 ID, const char **outName){ GF_Route *r; u32 i; GF_Command *com; r = gf_sg_route_find(sdump->sg, ID); if (r) { (*outName) = r->name; return 1; } i=0; while ((com = (GF_Command *)gf_list_enum(sdump->inserted_routes, &i))) { if ((com->tag == GF_SG_ROUTE_INSERT)) { if (com->RouteID==ID) { (*outName) = com->def_name; return 1; } } } if (!sdump->current_com_list) return 0; i=1; while ((com = (GF_Command *)gf_list_enum(sdump->current_com_list, &i))) { if ((com->tag == GF_SG_ROUTE_INSERT) || (com->tag == GF_SG_ROUTE_REPLACE)) { if (com->RouteID==ID) { (*outName) = com->def_name; return 1; } } else return 0; } return 0;}void DumpRouteID(GF_SceneDumper *sdump, u32 routeID, char *rName){ if (!sdump->trace) return; if (!rName) DumpFindRouteName(sdump, routeID, (const char **) &rName); if (rName) fprintf(sdump->trace, "%s", rName); else fprintf(sdump->trace, "R%d", routeID - 1);}void DumpBool(GF_SceneDumper *sdump, char *name, u32 value){ if (!sdump->trace) return; StartAttribute(sdump, name); fprintf(sdump->trace, "%s", value ? "true" : "false"); EndAttribute(sdump);}void DumpUTFString(GF_SceneDumper *sdump, char *str){ u32 len, i; u16 *uniLine; if (!str) return; len = strlen(str); uniLine = (u16*)malloc(sizeof(u16) * len); len = gf_utf8_mbstowcs(uniLine, len, (const char **) &str); if (len != (size_t) (-1)) { for (i=0; i<len; i++) { if (uniLine[i] == (u16) '\"') fprintf(sdump->trace, "\\"); switch (uniLine[i]) { case '\'': fprintf(sdump->trace, "'"); break; case '\"': fprintf(sdump->trace, """); break; case '&': fprintf(sdump->trace, "&"); break; case '>': fprintf(sdump->trace, ">"); break; case '<': fprintf(sdump->trace, "<"); break; default: if (uniLine[i]<128) { fprintf(sdump->trace, "%c", (u8) uniLine[i]); } else { fprintf(sdump->trace, "&#%d;", uniLine[i]); } break; } } } free(uniLine);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -