GF_Err BM_ParseDelete(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u8 type; u32 ID; GF_Command *com; GF_Node *n; type = gf_bs_read_int(bs, 2); switch (type) { case 0: ID = 1+gf_bs_read_int(bs, codec->info->config.NodeIDBits); n = gf_sg_find_node(codec->current_graph, ID); if (!n) return GF_OK; com = gf_sg_command_new(codec->current_graph, GF_SG_NODE_DELETE); BM_SetCommandNode(com, n); gf_list_add(com_list, com); return GF_OK; case 2: return BM_ParseIndexDelete(codec, bs, com_list); case 3: com = gf_sg_command_new(codec->current_graph, GF_SG_ROUTE_DELETE); com->RouteID = 1+gf_bs_read_int(bs, codec->info->config.RouteIDBits); gf_list_add(com_list, com); return GF_OK; default: return GF_NON_COMPLIANT_BITSTREAM; } return GF_OK; }
static GF_Err BM_ParseProtoDelete(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 flag, count; GF_Command *com = gf_sg_command_new(codec->current_graph, GF_SG_PROTO_DELETE); flag = gf_bs_read_int(bs, 1); if (flag) { count = 0; flag = gf_bs_read_int(bs, 1); while (flag) { com->del_proto_list = (u32*)gf_realloc(com->del_proto_list, sizeof(u32) * (com->del_proto_list_size+1)); com->del_proto_list[count] = gf_bs_read_int(bs, codec->info->config.ProtoIDBits); com->del_proto_list_size++; flag = gf_bs_read_int(bs, 1); } } else { flag = gf_bs_read_int(bs, 5); com->del_proto_list_size = gf_bs_read_int(bs, flag); com->del_proto_list = (u32*)gf_realloc(com->del_proto_list, sizeof(u32) * (com->del_proto_list_size)); flag = 0; while (flag<com->del_proto_list_size) { com->del_proto_list[flag] = gf_bs_read_int(bs, codec->info->config.ProtoIDBits); flag++; } } gf_list_add(com_list, com); return GF_OK; }
static GF_Err BM_ParseGlobalQuantizer(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { GF_Node *node; GF_Command *com; GF_CommandField *inf; node = gf_bifs_dec_node(codec, bs, NDT_SFWorldNode); /*reset global QP*/ if (codec->scenegraph->global_qp) { gf_node_unregister(codec->scenegraph->global_qp, NULL); } codec->ActiveQP = NULL; codec->scenegraph->global_qp = NULL; if (node && (gf_node_get_tag(node) != TAG_MPEG4_QuantizationParameter)) { gf_node_unregister(node, NULL); return GF_NON_COMPLIANT_BITSTREAM; } /*register global QP*/ codec->ActiveQP = (M_QuantizationParameter *) node; codec->ActiveQP->isLocal = 0; codec->scenegraph->global_qp = node; if (node) { /*register TWICE: once for the command, and for the scenegraph globalQP*/ node->sgprivate->num_instances = 2; } com = gf_sg_command_new(codec->current_graph, GF_SG_GLOBAL_QUANTIZER); inf = gf_sg_command_field_new(com); inf->new_node = node; inf->field_ptr = &inf->new_node; inf->fieldType = GF_SG_VRML_SFNODE; gf_list_add(com_list, com); return GF_OK; }
void V4SceneGraph::LoadNew() { if (m_pSm) { gf_sr_set_scene(m_pSr, NULL); gf_sm_del(m_pSm); m_pSm = NULL; gf_sg_del(m_pSg); m_pSg = NULL; } if (m_pOriginal_mp4) gf_free(m_pOriginal_mp4); m_pOriginal_mp4 = NULL; m_pIs = gf_is_new(NULL); m_pSg = m_pIs->graph; gf_sg_set_init_callback(m_pSg, v4s_node_init, this); gf_sr_set_scene(m_pSr, m_pSg); m_pSm = gf_sm_new(m_pSg); /* Create a BIFS stream with one AU with on ReplaceScene */ GF_StreamContext *sc = gf_sm_stream_new(m_pSm, 1, GF_STREAM_SCENE, 0); GF_AUContext *au = gf_sm_stream_au_new(sc, 0, 0, 1); GF_Command *command = gf_sg_command_new(m_pSg, GF_SG_SCENE_REPLACE); gf_list_add(au->commands, command); // reinitializes the node pool frame->pools.Clear(); }
GF_Err BM_ParseIndexValueReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 NodeID, ind, field_ind, NumBits; s32 type, pos; GF_Command *com; GF_Node *node; GF_Err e; GF_FieldInfo field, sffield; GF_CommandField *inf; /*get the node*/ NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); node = gf_sg_find_node(codec->current_graph, NodeID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_IN)-1); ind = gf_bs_read_int(bs, NumBits); e = gf_bifs_get_field_index(node, ind, GF_SG_FIELD_CODING_IN, &field_ind); if (e) return e; e = gf_node_get_field(node, field_ind, &field); if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; type = gf_bs_read_int(bs, 2); switch (type) { case 0: pos = gf_bs_read_int(bs, 16); break; case 2: pos = 0; break; case 3: pos = ((GenMFField *) field.far_ptr)->count - 1; break; default: return GF_NON_COMPLIANT_BITSTREAM; } com = gf_sg_command_new(codec->current_graph, GF_SG_INDEXED_REPLACE); BM_SetCommandNode(com, node); inf = gf_sg_command_field_new(com); inf->fieldIndex = field.fieldIndex; inf->pos = pos; if (field.fieldType == GF_SG_VRML_MFNODE) { inf->fieldType = GF_SG_VRML_SFNODE; inf->new_node = gf_bifs_dec_node(codec, bs, field.NDTtype); inf->field_ptr = &inf->new_node; if (inf->new_node) gf_node_register(inf->new_node, NULL); } else { memcpy(&sffield, &field, sizeof(GF_FieldInfo)); sffield.fieldType = gf_sg_vrml_get_sf_type(field.fieldType); inf->fieldType = sffield.fieldType; sffield.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(sffield.fieldType); codec->LastError = gf_bifs_dec_sf_field(codec, bs, node, &sffield, 1); } gf_list_add(com_list, com); return codec->LastError; }
GF_Command *gf_sg_command_clone(GF_Command *com, GF_SceneGraph *inGraph) { u32 i, count; GF_Command *dest; if (com->tag==GF_SG_SCENE_REPLACE) return NULL; /*FIXME - to do*/ if (gf_list_count(com->new_proto_list)) return NULL; dest = gf_sg_command_new(inGraph, com->tag); /*node the command applies to - may be NULL*/ dest->node = gf_node_clone(inGraph, com->node, NULL); /*route insert, replace and delete*/ dest->RouteID = com->RouteID; if (com->def_name) dest->def_name = strdup(com->def_name); dest->fromNodeID = com->fromNodeID; dest->fromFieldIndex = com->fromFieldIndex; dest->toNodeID = com->toNodeID; dest->toFieldIndex = com->toFieldIndex; dest->del_proto_list_size = com->del_proto_list_size; if (com->del_proto_list_size) { dest->del_proto_list = (u32*)malloc(sizeof(u32) * com->del_proto_list_size); memcpy(dest->del_proto_list, com->del_proto_list, sizeof(u32) * com->del_proto_list_size); } count = gf_list_count(com->command_fields); for (i=0; i<count; i++) { GF_CommandField *fo = (GF_CommandField *)gf_list_get(com->command_fields, i); GF_CommandField *fd = (GF_CommandField *)gf_sg_command_field_new(dest); fd->fieldIndex = fo->fieldIndex; fd->fieldType = fo->fieldType; fd->pos = fo->pos; if (fo->field_ptr) { fd->field_ptr = gf_sg_vrml_field_pointer_new(fd->fieldType); gf_sg_vrml_field_copy(fd->field_ptr, fo->field_ptr, fo->fieldType); } if (fo->new_node) { fd->new_node = gf_node_clone(inGraph, fo->new_node, dest->node); fd->field_ptr = &fd->new_node; } if (fo->node_list) { GF_ChildNodeItem *child, *cur, *prev; prev = NULL; child = fo->node_list; while (child) { cur = (GF_ChildNodeItem*) malloc(sizeof(GF_ChildNodeItem)); cur->node = gf_node_clone(inGraph, child->node, dest->node); cur->next = NULL; if (prev) prev->next = cur; else fd->node_list = cur; prev = cur; child = child->next; } fd->field_ptr = &fd->node_list; } } return dest; }
static GF_Err BM_ParseExtendedUpdates(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 type = gf_bs_read_int(bs, 8); GF_Err e; switch (type) { case 0: { GF_Command *com = gf_sg_command_new(codec->current_graph, GF_SG_PROTO_INSERT); e = gf_bifs_dec_proto_list(codec, bs, com->new_proto_list); if (e) gf_sg_command_del(com); else gf_list_add(com_list, com); } return e; case 1: return BM_ParseProtoDelete(codec, bs, com_list); case 2: { GF_Command *com = gf_sg_command_new(codec->current_graph, GF_SG_PROTO_DELETE_ALL); return gf_list_add(com_list, com); } case 3: return BM_ParseMultipleIndexedReplace(codec, bs, com_list); case 4: return BM_ParseMultipleReplace(codec, bs, com_list); case 5: return BM_ParseGlobalQuantizer(codec, bs, com_list); case 6: { GF_Command *com; u32 ID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); GF_Node *n = gf_sg_find_node(codec->current_graph, ID); if (!n) return GF_OK; com = gf_sg_command_new(codec->current_graph, GF_SG_NODE_DELETE_EX); BM_SetCommandNode(com, n); gf_list_add(com_list, com); } return GF_OK; case 7: return BM_XReplace(codec, bs, com_list); default: return GF_BIFS_UNKNOWN_VERSION; } }
static GF_Err BM_ParseMultipleIndexedReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 ID, ind, field_ind, NumBits, lenpos, lennum, count; GF_Node *node; GF_Err e; GF_Command *com; GF_CommandField *inf; GF_FieldInfo field; ID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); node = gf_sg_find_node(codec->current_graph, ID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_IN)-1); ind = gf_bs_read_int(bs, NumBits); e = gf_bifs_get_field_index(node, ind, GF_SG_FIELD_CODING_IN, &field_ind); if (e) return e; e = gf_node_get_field(node, field_ind, &field); if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; lenpos = gf_bs_read_int(bs, 5); lennum = gf_bs_read_int(bs, 5); count = gf_bs_read_int(bs, lennum); com = gf_sg_command_new(codec->current_graph, GF_SG_MULTIPLE_INDEXED_REPLACE); BM_SetCommandNode(com, node); field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType); while (count) { inf = gf_sg_command_field_new(com); inf->pos = gf_bs_read_int(bs, lenpos); inf->fieldIndex = field.fieldIndex; inf->fieldType = field.fieldType; if (field.fieldType==GF_SG_VRML_SFNODE) { inf->new_node = gf_bifs_dec_node(codec, bs, field.NDTtype); if (codec->LastError) goto err; inf->field_ptr = &inf->new_node; gf_node_register(inf->new_node, NULL); } else { field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType); e = gf_bifs_dec_sf_field(codec, bs, node, &field, 1); if (e) goto err; } count--; } err: if (e) gf_sg_command_del(com); else gf_list_add(com_list, com); return e; }
GF_Err BM_SceneReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { GF_Command *com; GF_Node *backup_root; GF_List *backup_routes; GF_Err BD_DecSceneReplace(GF_BifsDecoder * codec, GF_BitStream *bs, GF_List *proto_list); backup_routes = codec->scenegraph->Routes; backup_root = codec->scenegraph->RootNode; com = gf_sg_command_new(codec->current_graph, GF_SG_SCENE_REPLACE); codec->scenegraph->Routes = gf_list_new(); codec->current_graph = codec->scenegraph; codec->LastError = BD_DecSceneReplace(codec, bs, com->new_proto_list); com->use_names = codec->UseName; /*restore*/ com->node = codec->scenegraph->RootNode; codec->scenegraph->RootNode = backup_root; gf_list_add(com_list, com); /*insert routes*/ while (gf_list_count(codec->scenegraph->Routes)) { GF_Route *r = (GF_Route*)gf_list_get(codec->scenegraph->Routes, 0); GF_Command *ri = gf_sg_command_new(codec->current_graph, GF_SG_ROUTE_INSERT); gf_list_rem(codec->scenegraph->Routes, 0); ri->fromFieldIndex = r->FromField.fieldIndex; ri->fromNodeID = gf_node_get_id(r->FromNode); ri->toFieldIndex = r->ToField.fieldIndex; ri->toNodeID = gf_node_get_id(r->ToNode); if (r->ID) ri->RouteID = r->ID; ri->def_name = r->name ? gf_strdup(r->name) : NULL; gf_list_add(com_list, ri); gf_sg_route_del(r); } gf_list_del(codec->scenegraph->Routes); codec->scenegraph->Routes = backup_routes; return codec->LastError; }
GF_Err BM_ParseRouteInsert(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { GF_Err e; u8 flag; GF_Command *com; GF_Node *InNode, *OutNode; u32 RouteID, outField, inField, numBits, ind, node_id; char name[1000]; RouteID = 0; flag = gf_bs_read_int(bs, 1); /*def'ed route*/ if (flag) { RouteID = 1 + gf_bs_read_int(bs, codec->info->config.RouteIDBits); if (codec->UseName) gf_bifs_dec_name(bs, name); } /*origin*/ node_id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); OutNode = gf_sg_find_node(codec->current_graph, node_id); if (!OutNode) return GF_SG_UNKNOWN_NODE; numBits = gf_node_get_num_fields_in_mode(OutNode, GF_SG_FIELD_CODING_OUT) - 1; numBits = gf_get_bit_size(numBits); ind = gf_bs_read_int(bs, numBits); e = gf_bifs_get_field_index(OutNode, ind, GF_SG_FIELD_CODING_OUT, &outField); /*target*/ node_id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); InNode = gf_sg_find_node(codec->current_graph, node_id); if (!InNode) return GF_SG_UNKNOWN_NODE; numBits = gf_node_get_num_fields_in_mode(InNode, GF_SG_FIELD_CODING_IN) - 1; numBits = gf_get_bit_size(numBits); ind = gf_bs_read_int(bs, numBits); e = gf_bifs_get_field_index(InNode, ind, GF_SG_FIELD_CODING_IN, &inField); if (e) return e; com = gf_sg_command_new(codec->current_graph, GF_SG_ROUTE_INSERT); com->RouteID = RouteID; if (codec->UseName) com->def_name = gf_strdup( name); com->fromNodeID = gf_node_get_id(OutNode); com->fromFieldIndex = outField; com->toNodeID = gf_node_get_id(InNode); com->toFieldIndex = inField; gf_list_add(com_list, com); return codec->LastError; }
void V4SceneManager::LoadNew() { LoadCommon(); /* Create a BIFS stream with one AU with one ReplaceScene */ GF_StreamContext *sc = gf_sm_stream_new(m_pSm, 1, GF_STREAM_SCENE, 0); GF_AUContext *au = gf_sm_stream_au_new(sc, 0, 0, 1); GF_Command *command = gf_sg_command_new(m_pIs->graph, GF_SG_SCENE_REPLACE); gf_list_add(au->commands, command); SetLength(50); SetFrameRate(25); // reinitializes the node pool pools.Clear(); }
GF_EXPORT GF_Err gf_sm_make_random_access(GF_SceneManager *ctx) { GF_Err e; u32 i, j, stream_count, au_count, com_count; GF_AUContext *au; GF_Command *com; e = GF_OK; stream_count = gf_list_count(ctx->streams); for (i=0; i<stream_count; i++) { GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i); /*FIXME - do this as well for ODs*/ if (sc->streamType == GF_STREAM_SCENE) { /*apply all commands - this will also apply the SceneReplace*/ j=0; while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { e = gf_sg_command_apply_list(ctx->scene_graph, au->commands, 0); if (e) return e; } /* Delete all the commands in the stream */ while ( (au_count = gf_list_count(sc->AUs)) ) { au = (GF_AUContext *)gf_list_get(sc->AUs, au_count-1); gf_list_rem(sc->AUs, au_count-1); while ( (com_count = gf_list_count(au->commands)) ) { com = (GF_Command*)gf_list_get(au->commands, com_count - 1); gf_list_rem(au->commands, com_count - 1); gf_sg_command_del(com); } gf_list_del(au->commands); free(au); } /*and recreate scene replace*/ au = gf_sm_stream_au_new(sc, 0, 0, 1); com = gf_sg_command_new(ctx->scene_graph, GF_SG_SCENE_REPLACE); com->node = ctx->scene_graph->RootNode; ctx->scene_graph->RootNode = NULL; gf_list_del(com->new_proto_list); com->new_proto_list = ctx->scene_graph->protos; ctx->scene_graph->protos = NULL; /*FIXME - check routes & protos*/ gf_list_add(au->commands, com); } } return e; }
GF_Err BM_ParseIndexDelete(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 NodeID, NumBits, ind, field_ind; s32 pos; GF_Command *com; u8 type; GF_Node *node; GF_Err e; GF_CommandField *inf; GF_FieldInfo field; NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); node = gf_sg_find_node(codec->current_graph, NodeID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_IN) - 1); ind = gf_bs_read_int(bs, NumBits); type = gf_bs_read_int(bs, 2); switch (type) { case 0: pos = (u32) gf_bs_read_int(bs, 16); break; case 2: pos = 0; break; case 3: pos = -1; break; default: return GF_NON_COMPLIANT_BITSTREAM; } e = gf_bifs_get_field_index(node, ind, GF_SG_FIELD_CODING_IN, &field_ind); if (e) return e; e = gf_node_get_field(node, field_ind, &field); if (e) return e; if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; com = gf_sg_command_new(codec->current_graph, GF_SG_INDEXED_DELETE); BM_SetCommandNode(com, node); inf = gf_sg_command_field_new(com); inf->pos = pos; inf->fieldIndex = field.fieldIndex; inf->fieldType = gf_sg_vrml_get_sf_type(field.fieldType); gf_list_add(com_list, com); return codec->LastError; }
/*inserts a node in a container (node.children)*/ GF_Err BM_ParseNodeInsert(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 NodeID, NDT; GF_Command *com; GF_CommandField *inf; s32 type, pos; GF_Node *node, *def; NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); def = gf_sg_find_node(codec->current_graph, NodeID); if (!def) return GF_NON_COMPLIANT_BITSTREAM; NDT = gf_bifs_get_child_table(def); if (!NDT) return GF_NON_COMPLIANT_BITSTREAM; type = gf_bs_read_int(bs, 2); switch (type) { case 0: pos = gf_bs_read_int(bs, 8); break; case 2: pos = 0; break; case 3: /*-1 means append*/ pos = -1; break; default: return GF_NON_COMPLIANT_BITSTREAM; } node = gf_bifs_dec_node(codec, bs, NDT); if (!codec->LastError) { com = gf_sg_command_new(codec->current_graph, GF_SG_NODE_INSERT); BM_SetCommandNode(com, def); inf = gf_sg_command_field_new(com); inf->pos = pos; inf->new_node = node; inf->field_ptr = &inf->new_node; inf->fieldType = GF_SG_VRML_SFNODE; gf_list_add(com_list, com); /*register*/ gf_node_register(node, NULL); } return codec->LastError; }
GF_Err BM_ParseNodeReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 NodeID; GF_Command *com; GF_Node *node; GF_CommandField *inf; NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); /*this is delete / new on a DEF node: replace ALL instances*/ node = gf_sg_find_node(codec->current_graph, NodeID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; com = gf_sg_command_new(codec->current_graph, GF_SG_NODE_REPLACE); BM_SetCommandNode(com, node); inf = gf_sg_command_field_new(com); inf->new_node = gf_bifs_dec_node(codec, bs, NDT_SFWorldNode); inf->fieldType = GF_SG_VRML_SFNODE; inf->field_ptr = &inf->new_node; gf_list_add(com_list, com); gf_node_register(inf->new_node, NULL); return codec->LastError; }
GF_Err BM_ParseRouteReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { GF_Err e; GF_Command *com; u32 RouteID, numBits, ind, node_id, fromID, toID; GF_Route *r; GF_Node *OutNode, *InNode; RouteID = 1+gf_bs_read_int(bs, codec->info->config.RouteIDBits); r = gf_sg_route_find(codec->current_graph, RouteID); /*origin*/ node_id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); OutNode = gf_sg_find_node(codec->current_graph, node_id); if (!OutNode) return GF_NON_COMPLIANT_BITSTREAM; numBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(OutNode, GF_SG_FIELD_CODING_OUT) - 1); ind = gf_bs_read_int(bs, numBits); e = gf_bifs_get_field_index(OutNode, ind, GF_SG_FIELD_CODING_OUT, &fromID); if (e) return e; /*target*/ node_id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); InNode = gf_sg_find_node(codec->current_graph, node_id); if (!InNode) return GF_NON_COMPLIANT_BITSTREAM; numBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(InNode, GF_SG_FIELD_CODING_IN) - 1); ind = gf_bs_read_int(bs, numBits); e = gf_bifs_get_field_index(InNode, ind, GF_SG_FIELD_CODING_IN, &toID); if (e) return e; com = gf_sg_command_new(codec->current_graph, GF_SG_ROUTE_REPLACE); com->RouteID = RouteID; com->fromNodeID = gf_node_get_id(OutNode); com->fromFieldIndex = fromID; com->toNodeID = gf_node_get_id(InNode); com->toFieldIndex = toID; gf_list_add(com_list, com); return codec->LastError; }
GF_Err BM_ParseFieldReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { GF_Err e; GF_Command *com; u32 NodeID, ind, field_ind, NumBits; GF_Node *node; GF_FieldInfo field; GF_CommandField *inf; NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); node = gf_sg_find_node(codec->current_graph, NodeID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_IN)-1); ind = gf_bs_read_int(bs, NumBits); e = gf_bifs_get_field_index(node, ind, GF_SG_FIELD_CODING_IN, &field_ind); if (e) return e; e = gf_node_get_field(node, field_ind, &field); com = gf_sg_command_new(codec->current_graph, GF_SG_FIELD_REPLACE); BM_SetCommandNode(com, node); inf = gf_sg_command_field_new(com); inf->fieldIndex = field_ind; inf->fieldType = field.fieldType; if (inf->fieldType == GF_SG_VRML_SFNODE) { field.far_ptr = inf->field_ptr = &inf->new_node; } else if (inf->fieldType == GF_SG_VRML_MFNODE) { field.far_ptr = inf->field_ptr = &inf->node_list; } else { field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(field.fieldType); } /*parse the field*/ codec->LastError = gf_bifs_dec_field(codec, bs, node, &field, 1); gf_list_add(com_list, com); return codec->LastError; }
GF_EXPORT GF_Err gf_sm_aggregate(GF_SceneManager *ctx, u16 ESID) { GF_Err e; u32 i, stream_count; #ifndef GPAC_DISABLE_VRML u32 j; GF_AUContext *au; GF_Command *com; #endif e = GF_OK; #if DEBUG_RAP com_count = 0; stream_count = gf_list_count(ctx->streams); for (i=0; i<stream_count; i++) { GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i); if (sc->streamType == GF_STREAM_SCENE) { au_count = gf_list_count(sc->AUs); for (j=0; j<au_count; j++) { au = (GF_AUContext *)gf_list_get(sc->AUs, j); com_count += gf_list_count(au->commands); } } } GF_LOG(GF_LOG_INFO, GF_LOG_SCENE, ("[SceneManager] Making RAP with %d commands\n", com_count)); #endif stream_count = gf_list_count(ctx->streams); for (i=0; i<stream_count; i++) { GF_AUContext *carousel_au; GF_List *carousel_commands; GF_StreamContext *aggregate_on_stream; GF_StreamContext *sc = (GF_StreamContext *)gf_list_get(ctx->streams, i); if (ESID && (sc->ESID!=ESID)) continue; /*locate the AU in which our commands will be aggregated*/ carousel_au = NULL; carousel_commands = NULL; aggregate_on_stream = sc->aggregate_on_esid ? gf_sm_get_stream(ctx, sc->aggregate_on_esid) : NULL; if (aggregate_on_stream==sc) { carousel_commands = gf_list_new(); } else if (aggregate_on_stream) { if (!gf_list_count(aggregate_on_stream->AUs)) { carousel_au = gf_sm_stream_au_new(aggregate_on_stream, 0, 0, 1); } else { /* assert we already performed aggregation */ assert(gf_list_count(aggregate_on_stream->AUs)==1); carousel_au = gf_list_get(aggregate_on_stream->AUs, 0); } carousel_commands = carousel_au->commands; } /*TODO - do this as well for ODs*/ #ifndef GPAC_DISABLE_VRML if (sc->streamType == GF_STREAM_SCENE) { Bool has_modif = 0; /*we check for each stream if it is a base stream (SceneReplace ...) - several streams may carry RAPs if inline nodes are used*/ Bool base_stream_found = 0; /*in DIMS we use an empty initial AU with no commands to signal the RAP*/ if (sc->objectType == GPAC_OTI_SCENE_DIMS) base_stream_found = 1; /*apply all commands - this will also apply the SceneReplace*/ while (gf_list_count(sc->AUs)) { u32 count; au = (GF_AUContext *) gf_list_get(sc->AUs, 0); gf_list_rem(sc->AUs, 0); /*AU not aggregated*/ if (au->flags & GF_SM_AU_NOT_AGGREGATED) { gf_sm_au_del(sc, au); continue; } count = gf_list_count(au->commands); for (j=0; j<count; j++) { u32 store=0; com = gf_list_get(au->commands, j); if (!base_stream_found) { switch (com->tag) { case GF_SG_SCENE_REPLACE: case GF_SG_LSR_NEW_SCENE: case GF_SG_LSR_REFRESH_SCENE: base_stream_found = 1; break; } } /*aggregate the command*/ /*if stream doesn't carry a carousel or carries the base carousel (scene replace), always apply the command*/ if (base_stream_found || !sc->aggregate_on_esid) { store = 0; } /*otherwise, check wether the command should be kept in this stream as is, or can be aggregated on this stream*/ else { switch (com->tag) { /*the following commands do not impact a sub-tree (eg do not deal with nodes), we cannot aggregate them... */ case GF_SG_ROUTE_REPLACE: case GF_SG_ROUTE_DELETE: case GF_SG_ROUTE_INSERT: case GF_SG_PROTO_INSERT: case GF_SG_PROTO_DELETE: case GF_SG_PROTO_DELETE_ALL: case GF_SG_GLOBAL_QUANTIZER: case GF_SG_LSR_RESTORE: case GF_SG_LSR_SAVE: case GF_SG_LSR_SEND_EVENT: case GF_SG_LSR_CLEAN: /*todo check in which category to put these commands*/ // case GF_SG_LSR_ACTIVATE: // case GF_SG_LSR_DEACTIVATE: store = 1; break; /*other commands: !!! we need to know if the target node of the command has been inserted in this stream !!! This is a tedious task, for now we will consider the following cases: - locate a similar command in the stored list: remove the similar one and aggregate on stream - by default all AUs are stored if the stream is in aggregate mode - we should fix that by checking insertion points: if a command apllies on a node that has been inserted in this stream, we can aggregate, otherwise store */ default: /*check if we can directly store the command*/ assert(carousel_commands); store = store_or_aggregate(sc, com, carousel_commands, &has_modif); break; } } switch (store) { /*command has been merged with a previous command in carousel and needs to be destroyed*/ case 2: gf_list_rem(au->commands, j); j--; count--; gf_sg_command_del((GF_Command *)com); break; /*command shall be moved to carousel without being applied*/ case 1: gf_list_insert(carousel_commands, com, 0); gf_list_rem(au->commands, j); j--; count--; break; /*command can be applied*/ default: e = gf_sg_command_apply(ctx->scene_graph, com, 0); break; } } gf_sm_au_del(sc, au); } /*and recreate scene replace*/ if (base_stream_found) { au = gf_sm_stream_au_new(sc, 0, 0, 1); switch (sc->objectType) { case GPAC_OTI_SCENE_BIFS: case GPAC_OTI_SCENE_BIFS_V2: com = gf_sg_command_new(ctx->scene_graph, GF_SG_SCENE_REPLACE); break; case GPAC_OTI_SCENE_LASER: com = gf_sg_command_new(ctx->scene_graph, GF_SG_LSR_NEW_SCENE); break; case GPAC_OTI_SCENE_DIMS: /* We do not create a new command, empty AU is enough in DIMS*/ default: com = NULL; break; } if (com) { com->node = ctx->scene_graph->RootNode; ctx->scene_graph->RootNode = NULL; gf_list_del(com->new_proto_list); com->new_proto_list = ctx->scene_graph->protos; ctx->scene_graph->protos = NULL; /*indicate the command is the aggregated scene graph, so that PROTOs and ROUTEs are taken from the scenegraph when encoding*/ com->aggregated = 1; gf_list_add(au->commands, com); } } /*update carousel flags of the AU*/ else if (carousel_commands) { /*if current stream caries its own carousel*/ if (!carousel_au) { carousel_au = gf_sm_stream_au_new(sc, 0, 0, 1); gf_list_del(carousel_au->commands); carousel_au->commands = carousel_commands; } carousel_au->flags |= GF_SM_AU_RAP | GF_SM_AU_CAROUSEL; if (has_modif) carousel_au->flags |= GF_SM_AU_MODIFIED; } } #endif } return e; }
GF_Command *gf_sg_vrml_command_clone(GF_Command *com, GF_SceneGraph *inGraph, Bool force_clone) { u32 i, count; GF_Command *dest; /*FIXME - to do*/ if (gf_list_count(com->new_proto_list)) return NULL; dest = gf_sg_command_new(inGraph, com->tag); if (com->in_scene!=inGraph) force_clone = 1; /*node the command applies to - may be NULL*/ if (force_clone) { dest->node = gf_node_clone(inGraph, com->node, NULL, "", 0); } else { dest->node = com->node; gf_node_register(dest->node, NULL); } /*route insert, replace and delete*/ dest->RouteID = com->RouteID; if (com->def_name) dest->def_name = gf_strdup(com->def_name); dest->fromNodeID = com->fromNodeID; dest->fromFieldIndex = com->fromFieldIndex; dest->toNodeID = com->toNodeID; dest->toFieldIndex = com->toFieldIndex; dest->send_event_integer = com->send_event_integer; dest->send_event_x = com->send_event_x; dest->send_event_y = com->send_event_y; if (com->send_event_string) dest->send_event_string = gf_strdup(com->send_event_string); dest->del_proto_list_size = com->del_proto_list_size; if (com->del_proto_list_size) { dest->del_proto_list = (u32*)gf_malloc(sizeof(u32) * com->del_proto_list_size); memcpy(dest->del_proto_list, com->del_proto_list, sizeof(u32) * com->del_proto_list_size); } count = gf_list_count(com->command_fields); for (i=0; i<count; i++) { GF_CommandField *fo = (GF_CommandField *)gf_list_get(com->command_fields, i); GF_CommandField *fd = (GF_CommandField *)gf_sg_command_field_new(dest); fd->fieldIndex = fo->fieldIndex; fd->fieldType = fo->fieldType; fd->pos = fo->pos; /*FIXME - this can also be LASeR commands, not supported for now*/ if (fo->field_ptr) { fd->field_ptr = gf_sg_vrml_field_pointer_new(fd->fieldType); gf_sg_vrml_field_clone(fd->field_ptr, fo->field_ptr, fo->fieldType, dest->in_scene); } if (fo->new_node) { if (force_clone) { fd->new_node = gf_node_clone(inGraph, fo->new_node, dest->node, "", 0); } else { fd->new_node = fo->new_node; gf_node_register(fd->new_node, NULL); } fd->field_ptr = &fd->new_node; } if (fo->node_list) { GF_ChildNodeItem *child, *cur, *prev; prev = NULL; child = fo->node_list; while (child) { cur = (GF_ChildNodeItem*) gf_malloc(sizeof(GF_ChildNodeItem)); if (force_clone) { cur->node = gf_node_clone(inGraph, child->node, dest->node, "", 0); } else { cur->node = child->node; gf_node_register(cur->node, NULL); } cur->next = NULL; if (prev) prev->next = cur; else fd->node_list = cur; prev = cur; child = child->next; } fd->field_ptr = &fd->node_list; } } return dest; }
/*import cubic QTVR to mp4*/ GF_Err gf_sm_load_init_qt(GF_SceneLoader *load) { u32 i, di, w, h, tk, nb_samp; Bool has_qtvr; GF_ISOSample *samp; GF_ISOFile *src; GF_StreamContext *st; GF_AUContext *au; GF_Command *com; M_Background *back; M_NavigationInfo *ni; M_Group *gr; GF_ODUpdate *odU; GF_SceneGraph *sg; GF_ObjectDescriptor *od; GF_ESD *esd; if (!load->ctx) return GF_NOT_SUPPORTED; src = gf_isom_open(load->fileName, GF_ISOM_OPEN_READ, NULL); if (!src) return gf_qt_report(load, GF_URL_ERROR, "Opening file %s failed", load->fileName); w = h = tk = 0; nb_samp = 0; has_qtvr = 0; for (i=0; i<gf_isom_get_track_count(src); i++) { switch (gf_isom_get_media_type(src, i+1)) { case GF_ISOM_MEDIA_VISUAL: if (gf_isom_get_media_subtype(src, i+1, 1) == GF_4CC('j', 'p', 'e', 'g')) { GF_GenericSampleDescription *udesc = gf_isom_get_generic_sample_description(src, i+1, 1); if ((udesc->width>w) || (udesc->height>h)) { w = udesc->width; h = udesc->height; tk = i+1; nb_samp = gf_isom_get_sample_count(src, i+1); } if (udesc->extension_buf) gf_free(udesc->extension_buf); gf_free(udesc); } break; case GF_4CC('q','t','v','r'): has_qtvr = 1; break; } } if (!has_qtvr) { gf_isom_delete(src); return gf_qt_report(load, GF_NOT_SUPPORTED, "QTVR not found - no conversion available for this QuickTime movie"); } if (!tk) { gf_isom_delete(src); return gf_qt_report(load, GF_NON_COMPLIANT_BITSTREAM, "No associated visual track with QTVR movie"); } if (nb_samp!=6) { gf_isom_delete(src); return gf_qt_report(load, GF_NOT_SUPPORTED, "Movie %s doesn't look a Cubic QTVR - sorry...", load->fileName); } GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("QT: Importing Cubic QTVR Movie")); /*create scene*/ sg = load->ctx->scene_graph; gr = (M_Group *) gf_node_new(sg, TAG_MPEG4_Group); gf_node_register((GF_Node *)gr, NULL); st = gf_sm_stream_new(load->ctx, 1, GF_STREAM_SCENE, 1); au = gf_sm_stream_au_new(st, 0, 0, 1); com = gf_sg_command_new(load->ctx->scene_graph, GF_SG_SCENE_REPLACE); gf_list_add(au->commands, com); com->node = (GF_Node *)gr; back = (M_Background *) gf_node_new(sg, TAG_MPEG4_Background); gf_node_list_add_child( &gr->children, (GF_Node*)back); gf_node_register((GF_Node *)back, (GF_Node *)gr); gf_sg_vrml_mf_alloc(&back->leftUrl, GF_SG_VRML_MFURL, 1); back->leftUrl.vals[0].OD_ID = 2; gf_sg_vrml_mf_alloc(&back->frontUrl, GF_SG_VRML_MFURL, 1); back->frontUrl.vals[0].OD_ID = 3; gf_sg_vrml_mf_alloc(&back->rightUrl, GF_SG_VRML_MFURL, 1); back->rightUrl.vals[0].OD_ID = 4; gf_sg_vrml_mf_alloc(&back->backUrl, GF_SG_VRML_MFURL, 1); back->backUrl.vals[0].OD_ID = 5; gf_sg_vrml_mf_alloc(&back->topUrl, GF_SG_VRML_MFURL, 1); back->topUrl.vals[0].OD_ID = 6; gf_sg_vrml_mf_alloc(&back->bottomUrl, GF_SG_VRML_MFURL, 1); back->bottomUrl.vals[0].OD_ID = 7; ni = (M_NavigationInfo *) gf_node_new(sg, TAG_MPEG4_NavigationInfo); gf_node_list_add_child(&gr->children, (GF_Node*)ni); gf_node_register((GF_Node *)ni, (GF_Node *)gr); gf_sg_vrml_mf_reset(&ni->type, GF_SG_VRML_MFSTRING); gf_sg_vrml_mf_alloc(&ni->type, GF_SG_VRML_MFSTRING, 1); ni->type.vals[0] = gf_strdup("QTVR"); /*create ODs*/ st = gf_sm_stream_new(load->ctx, 2, GF_STREAM_OD, 1); au = gf_sm_stream_au_new(st, 0, 0, 1); odU = (GF_ODUpdate*) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG); gf_list_add(au->commands, odU); for (i=0; i<6; i++) { GF_MuxInfo *mi; FILE *img; char szName[1024]; od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); od->objectDescriptorID = 2+i; esd = gf_odf_desc_esd_new(2); esd->decoderConfig->streamType = GF_STREAM_VISUAL; esd->decoderConfig->objectTypeIndication = GPAC_OTI_IMAGE_JPEG; esd->ESID = 3+i; /*extract image and remember it*/ mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG); gf_list_add(esd->extensionDescriptors, mi); mi->delete_file = 1; sprintf(szName, "%s_img%d.jpg", load->fileName, esd->ESID); mi->file_name = gf_strdup(szName); gf_list_add(od->ESDescriptors, esd); gf_list_add(odU->objectDescriptors, od); samp = gf_isom_get_sample(src, tk, i+1, &di); img = gf_f64_open(mi->file_name, "wb"); fwrite(samp->data, samp->dataLength, 1, img); fclose(img); gf_isom_sample_del(&samp); } gf_isom_delete(src); return GF_OK; }
static GF_Err gf_text_import_srt_bifs(GF_SceneManager *ctx, GF_ESD *src, GF_MuxInfo *mux) { GF_Err e; GF_Node *text, *font; GF_StreamContext *srt; FILE *srt_in; GF_FieldInfo string, style; u32 sh, sm, ss, sms, eh, em, es, ems, start, end; GF_AUContext *au; GF_Command *com; SFString *sfstr; GF_CommandField *inf; Bool italic, underlined, bold; u32 state, curLine, line, i, len; char szLine[2048], szText[2048], *ptr; GF_StreamContext *sc = NULL; if (!ctx->scene_graph) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] base scene not assigned\n")); return GF_BAD_PARAM; } i=0; while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) { if (sc->streamType==GF_STREAM_SCENE) break; sc = NULL; } if (!sc) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot locate base scene\n")); return GF_BAD_PARAM; } if (!mux->textNode) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target text node unspecified\n")); return GF_BAD_PARAM; } text = gf_sg_find_node_by_name(ctx->scene_graph, mux->textNode); if (!text) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot find target text node %s\n", mux->textNode)); return GF_BAD_PARAM; } if (gf_node_get_field_by_name(text, "string", &string) != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target text node %s doesn't look like text\n", mux->textNode)); return GF_BAD_PARAM; } font = NULL; if (mux->fontNode) { font = gf_sg_find_node_by_name(ctx->scene_graph, mux->fontNode); if (!font) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot find target font node %s\n", mux->fontNode)); return GF_BAD_PARAM; } if (gf_node_get_field_by_name(font, "style", &style) != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target font node %s doesn't look like font\n", mux->fontNode)); return GF_BAD_PARAM; } } srt_in = gf_f64_open(mux->file_name, "rt"); if (!srt_in) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot open input file %s\n", mux->file_name)); return GF_URL_ERROR; } srt = gf_sm_stream_new(ctx, src->ESID, GF_STREAM_SCENE, 1); if (!srt) return GF_OUT_OF_MEM; if (!src->slConfig) src->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); src->slConfig->timestampResolution = 1000; if (!src->decoderConfig) src->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG); src->decoderConfig->streamType = GF_STREAM_SCENE; src->decoderConfig->objectTypeIndication = 1; e = GF_OK; state = end = 0; curLine = 0; au = NULL; com = NULL; italic = underlined = bold = 0; inf = NULL; while (1) { char *sOK = fgets(szLine, 2048, srt_in); if (sOK) REM_TRAIL_MARKS(szLine, "\r\n\t ") if (!sOK || !strlen(szLine)) { state = 0; if (au) { /*if italic or underscore do it*/ if (font && (italic || underlined || bold)) { com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = font; gf_node_register(font, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = style.fieldIndex; inf->fieldType = style.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(style.fieldType); sfstr = (SFString *)inf->field_ptr; if (bold && italic && underlined) sfstr->buffer = gf_strdup("BOLDITALIC UNDERLINED"); else if (italic && underlined) sfstr->buffer = gf_strdup("ITALIC UNDERLINED"); else if (bold && underlined) sfstr->buffer = gf_strdup("BOLD UNDERLINED"); else if (underlined) sfstr->buffer = gf_strdup("UNDERLINED"); else if (bold && italic) sfstr->buffer = gf_strdup("BOLDITALIC"); else if (bold) sfstr->buffer = gf_strdup("BOLD"); else sfstr->buffer = gf_strdup("ITALIC"); gf_list_add(au->commands, com); } au = gf_sm_stream_au_new(srt, end, 0, 1); com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = text; gf_node_register(text, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = string.fieldIndex; inf->fieldType = string.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType); gf_list_add(au->commands, com); /*reset font styles so that all AUs are true random access*/ if (font) { com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = font; gf_node_register(font, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = style.fieldIndex; inf->fieldType = style.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(style.fieldType); gf_list_add(au->commands, com); } au = NULL; } inf = NULL; if (!sOK) break; continue; } switch (state) { case 0: if (sscanf(szLine, "%u", &line) != 1) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame format (src: %s)\n", szLine)); e = GF_CORRUPTED_DATA; goto exit; } if (line != curLine + 1) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame: previous %d - current %d (src: %s)\n", curLine, line, szLine)); e = GF_CORRUPTED_DATA; goto exit; } curLine = line; state = 1; break; case 1: if (sscanf(szLine, "%u:%u:%u,%u --> %u:%u:%u,%u", &sh, &sm, &ss, &sms, &eh, &em, &es, &ems) != 8) { GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame %u (src: %s)\n", curLine, szLine)); e = GF_CORRUPTED_DATA; goto exit; } start = (3600*sh + 60*sm + ss)*1000 + sms; if (start<end) { GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[srt->bifs] corrupted frame starts before end of previous one (SRT Frame %d) - adjusting time stamps\n", curLine)); start = end; } end = (3600*eh + 60*em + es)*1000 + ems; /*make stream start at 0 by inserting a fake AU*/ if ((curLine==1) && start>0) { au = gf_sm_stream_au_new(srt, 0, 0, 1); com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = text; gf_node_register(text, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = string.fieldIndex; inf->fieldType = string.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType); gf_list_add(au->commands, com); } au = gf_sm_stream_au_new(srt, start, 0, 1); com = NULL; state = 2; italic = underlined = bold = 0; break; default: ptr = szLine; /*FIXME - other styles posssibles ??*/ while (1) { if (!strnicmp(ptr, "<i>", 3)) { italic = 1; ptr += 3; } else if (!strnicmp(ptr, "<u>", 3)) { underlined = 1; ptr += 3; } else if (!strnicmp(ptr, "<b>", 3)) { bold = 1; ptr += 3; } else break; } /*if style remove end markers*/ while ((strlen(ptr)>4) && (ptr[strlen(ptr) - 4] == '<') && (ptr[strlen(ptr) - 1] == '>')) { ptr[strlen(ptr) - 4] = 0; } if (!com) { com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE); com->node = text; gf_node_register(text, NULL); inf = gf_sg_command_field_new(com); inf->fieldIndex = string.fieldIndex; inf->fieldType = string.fieldType; inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType); gf_list_add(au->commands, com); } assert(inf); gf_sg_vrml_mf_append(inf->field_ptr, GF_SG_VRML_MFSTRING, (void **) &sfstr); len = 0; for (i=0; i<strlen(ptr); i++) { /*FIXME - UTF16 support !!*/ if (ptr[i] & 0x80) { /*non UTF8 (likely some win-CP)*/ if ((ptr[i+1] & 0xc0) != 0x80) { szText[len] = 0xc0 | ( (ptr[i] >> 6) & 0x3 ); len++; ptr[i] &= 0xbf; } /*we only handle UTF8 chars on 2 bytes (eg first byte is 0b110xxxxx)*/ else if ((ptr[i] & 0xe0) == 0xc0) { szText[len] = ptr[i]; len++; i++; } } szText[len] = ptr[i]; len++; } szText[len] = 0; sfstr->buffer = gf_strdup(szText); break; }
static GF_Err BM_ParseMultipleReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { u32 i, numFields, index, flag, nbBits, field_ref, fieldind; GF_Err e; GF_FieldInfo field; u32 NodeID; GF_Node *node; GF_Command *com; GF_CommandField *inf; NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); node = gf_sg_find_node(codec->current_graph, NodeID); if (!node) return GF_NON_COMPLIANT_BITSTREAM; e = GF_OK; com = gf_sg_command_new(codec->current_graph, GF_SG_MULTIPLE_REPLACE); BM_SetCommandNode(com, node); flag = gf_bs_read_int(bs, 1); if (flag) { numFields = gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_DEF); for (i=0; i<numFields; i++) { flag = gf_bs_read_int(bs, 1); if (!flag) continue; gf_bifs_get_field_index(node, i, GF_SG_FIELD_CODING_DEF, &index); e = gf_node_get_field(node, index, &field); if (e) goto exit; inf = gf_sg_command_field_new(com); inf->fieldType = field.fieldType; inf->fieldIndex = field.fieldIndex; if (inf->fieldType==GF_SG_VRML_SFNODE) { field.far_ptr = inf->field_ptr = &inf->new_node; } else if (inf->fieldType==GF_SG_VRML_MFNODE) { field.far_ptr = inf->field_ptr = &inf->node_list; } else { field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType); } e = gf_bifs_dec_field(codec, bs, node, &field, 1); if (e) goto exit; } } else { flag = gf_bs_read_int(bs, 1); nbBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_DEF)-1); while (!flag && (codec->LastError>=0)) { field_ref = gf_bs_read_int(bs, nbBits); e = gf_bifs_get_field_index(node, field_ref, GF_SG_FIELD_CODING_DEF, &fieldind); if (e) goto exit; e = gf_node_get_field(node, fieldind, &field); if (e) goto exit; inf = gf_sg_command_field_new(com); inf->fieldType = field.fieldType; inf->fieldIndex = field.fieldIndex; if (inf->fieldType==GF_SG_VRML_SFNODE) { field.far_ptr = inf->field_ptr = &inf->new_node; } else if (inf->fieldType==GF_SG_VRML_MFNODE) { field.far_ptr = inf->field_ptr = &inf->node_list; } else { field.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType); } e = gf_bifs_dec_field(codec, bs, node, &field, 1); if (e) goto exit; flag = gf_bs_read_int(bs, 1); } } exit: if (e) gf_sg_command_del(com); else gf_list_add(com_list, com); return e; }
static GF_Err BM_XReplace(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { GF_FieldInfo targetField, fromField, decfield; GF_Node *target, *n, *fromNode; s32 pos = -2; u32 id, nbBits, ind, aind; GF_Err e; GF_Command *com; GF_CommandField *inf; id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); target = gf_sg_find_node(codec->current_graph, id); if (!target) return GF_SG_UNKNOWN_NODE; e = GF_OK; com = gf_sg_command_new(codec->current_graph, GF_SG_XREPLACE); BM_SetCommandNode(com, target); nbBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(target, GF_SG_FIELD_CODING_IN)-1); ind = gf_bs_read_int(bs, nbBits); e = gf_bifs_get_field_index(target, ind, GF_SG_FIELD_CODING_IN, &aind); if (e) return e; e = gf_node_get_field(target, aind, &targetField); if (e) return e; inf = gf_sg_command_field_new(com); inf->fieldIndex = aind; if (!gf_sg_vrml_is_sf_field(targetField.fieldType)) { /*this is indexed replacement*/ if (gf_bs_read_int(bs, 1)) { /*index is dynamic*/ if (gf_bs_read_int(bs, 1)) { id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); n = gf_sg_find_node(codec->current_graph, id); if (!n) return GF_SG_UNKNOWN_NODE; com->toNodeID = id; nbBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(n, GF_SG_FIELD_CODING_DEF)-1); ind = gf_bs_read_int(bs, nbBits); e = gf_bifs_get_field_index(n, ind, GF_SG_FIELD_CODING_DEF, &aind); if (e) return e; e = gf_node_get_field(n, aind, &fromField); if (e) return e; com->toFieldIndex = aind; } else { u32 type = gf_bs_read_int(bs, 2); switch (type) { case 0: pos = gf_bs_read_int(bs, 16); break; case 2: pos = 0; break; case 3: pos = -1; break; } } } if (targetField.fieldType==GF_SG_VRML_MFNODE) { if (gf_bs_read_int(bs, 1)) { target = gf_node_list_get_child(*(GF_ChildNodeItem **)targetField.far_ptr, pos); if (!target) return GF_SG_UNKNOWN_NODE; nbBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(target, GF_SG_FIELD_CODING_IN)-1); ind = gf_bs_read_int(bs, nbBits); e = gf_bifs_get_field_index(target, ind, GF_SG_FIELD_CODING_IN, &aind); if (e) return e; e = gf_node_get_field(target, aind, &targetField); if (e) return e; pos = -2; com->child_field = aind; com->ChildNodeTag = gf_node_get_tag(target); if (com->ChildNodeTag == TAG_ProtoNode) { s32 p_id = gf_sg_proto_get_id(gf_node_get_proto(target)); com->ChildNodeTag = -p_id; } } } inf->pos = pos; } fromNode = NULL; if (gf_bs_read_int(bs, 1)) { id = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); fromNode = gf_sg_find_node(codec->current_graph, id); if (!fromNode) return GF_SG_UNKNOWN_NODE; com->fromNodeID = id; nbBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(fromNode, GF_SG_FIELD_CODING_DEF)-1); ind = gf_bs_read_int(bs, nbBits); e = gf_bifs_get_field_index(fromNode, ind, GF_SG_FIELD_CODING_DEF, &aind); if (e) return e; e = gf_node_get_field(fromNode, aind, &fromField); if (e) return e; com->fromFieldIndex = aind; return GF_OK; } if (pos>= -1) { inf->fieldType = gf_sg_vrml_get_sf_type(targetField.fieldType); } else { inf->fieldType = targetField.fieldType; } decfield.fieldIndex = inf->fieldIndex; decfield.fieldType = inf->fieldType; if (inf->fieldType==GF_SG_VRML_SFNODE) { decfield.far_ptr = inf->field_ptr = &inf->new_node; } else if (inf->fieldType==GF_SG_VRML_MFNODE) { decfield.far_ptr = inf->field_ptr = &inf->node_list; } else { decfield.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(inf->fieldType); } e = gf_bifs_dec_sf_field(codec, bs, target, &decfield, 1); if (e) return e; gf_list_add(com_list, com); return GF_OK; }
/*NB This can insert a node as well (but usually not in the .children field)*/ GF_Err BM_ParseIndexInsert(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list) { GF_Err e; u32 NodeID; u32 NumBits, ind, field_ind; u8 type; GF_Command *com; GF_CommandField *inf; s32 pos; GF_Node *def, *node; GF_FieldInfo field, sffield; NodeID = 1 + gf_bs_read_int(bs, codec->info->config.NodeIDBits); def = gf_sg_find_node(codec->current_graph, NodeID); if (!def) return GF_NON_COMPLIANT_BITSTREAM; /*index insertion uses IN mode for field index*/ NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(def, GF_SG_FIELD_CODING_IN)-1); ind = gf_bs_read_int(bs, NumBits); e = gf_bifs_get_field_index(def, ind, GF_SG_FIELD_CODING_IN, &field_ind); if (e) return e; type = gf_bs_read_int(bs, 2); switch (type) { case 0: pos = gf_bs_read_int(bs, 16); break; case 2: pos = 0; break; case 3: pos = -1; break; default: return GF_NON_COMPLIANT_BITSTREAM; } e = gf_node_get_field(def, field_ind, &field); if (e) return e; if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; memcpy(&sffield, &field, sizeof(GF_FieldInfo)); sffield.fieldType = gf_sg_vrml_get_sf_type(field.fieldType); /*rescale the MFField and parse the SFField*/ if (field.fieldType==GF_SG_VRML_MFNODE) { node = gf_bifs_dec_node(codec, bs, field.NDTtype); if (!codec->LastError) { com = gf_sg_command_new(codec->current_graph, GF_SG_INDEXED_INSERT); BM_SetCommandNode(com, def); inf = gf_sg_command_field_new(com); inf->pos = pos; inf->fieldIndex = field_ind; inf->fieldType = sffield.fieldType; inf->new_node = node; inf->field_ptr = &inf->new_node; gf_list_add(com_list, com); /*register*/ gf_node_register(node, NULL); } } else { com = gf_sg_command_new(codec->current_graph, GF_SG_INDEXED_INSERT); BM_SetCommandNode(com, def); inf = gf_sg_command_field_new(com); inf->pos = pos; inf->fieldIndex = field_ind; inf->fieldType = sffield.fieldType; sffield.far_ptr = inf->field_ptr = gf_sg_vrml_field_pointer_new(sffield.fieldType); codec->LastError = gf_bifs_dec_sf_field(codec, bs, def, &sffield, 1); gf_list_add(com_list, com); } return codec->LastError; }