/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / BIFS codec 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 #include "quant.h" GF_Err BE_EncProtoList(GF_BifsEncoder *codec, GF_List *protoList, GF_BitStream *bs); void gf_bifs_enc_name(GF_BifsEncoder *codec, GF_BitStream *bs, char *name) { u32 i = 0; while (name[i]) { gf_bs_write_int(bs, name[i], 8); i++; } gf_bs_write_int(bs, 0, 8); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] DEF\t\t%d\t\t%s\n", 8*i, name)); } static GF_Err BE_MultipleIndexedReplace(GF_BifsEncoder * codec, GF_Command *com, GF_BitStream *bs) { u32 i,nbBits, count, maxPos, nbBitsPos; GF_FieldInfo field; GF_Err e; GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); gf_bs_write_int(bs, gf_node_get_id(com->node)-1, codec->info->config.NodeIDBits); nbBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(com->node, GF_SG_FIELD_CODING_IN)-1); gf_bifs_field_index_by_mode(com->node, inf->fieldIndex, GF_SG_FIELD_CODING_IN, &i); GF_BIFS_WRITE_INT(codec, bs, i, nbBits, "field", NULL); gf_node_get_field(com->node, inf->fieldIndex, &field); field.fieldType = inf->fieldType; count = gf_list_count(com->command_fields); maxPos = 0; for (i=0; icommand_fields, i); if (maxPos < (u32) inf->pos) maxPos = inf->pos; } nbBitsPos = gf_get_bit_size(maxPos); GF_BIFS_WRITE_INT(codec, bs, nbBitsPos, 5, "nbBitsPos", NULL); nbBits = gf_get_bit_size(count); GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, count, nbBits, "count", NULL); for (i=0; icommand_fields, i); GF_BIFS_WRITE_INT(codec, bs, inf->pos, nbBitsPos, "idx", NULL); field.far_ptr = inf->field_ptr; e = gf_bifs_enc_field(codec, bs, com->node, &field); if (e) return e; } return GF_OK; } static GF_Err BE_MultipleReplace(GF_BifsEncoder * codec, GF_Command *com, GF_BitStream *bs) { u32 i, j, nbBits, count, numFields, allField; Bool use_list; GF_FieldInfo field; GF_Err e; gf_bs_write_int(bs, gf_node_get_id(com->node)-1, codec->info->config.NodeIDBits); count = gf_list_count(com->command_fields); use_list = 1; numFields = gf_node_get_num_fields_in_mode(com->node, GF_SG_FIELD_CODING_DEF); nbBits = gf_get_bit_size(numFields - 1); if (count < 1+count*(1+nbBits)) use_list = 0; GF_BIFS_WRITE_INT(codec, bs, use_list ? 0 : 1, 1, "isMask", NULL); for (i=0; inode, i, GF_SG_FIELD_CODING_DEF, &allField); for (j=0; jcommand_fields, j); if (inf->fieldIndex==allField) break; inf = NULL; } if (!inf) { if (!use_list) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "Mask", NULL); continue; } /*common case*/ gf_node_get_field(com->node, inf->fieldIndex, &field); if (use_list) { /*not end flag*/ GF_BIFS_WRITE_INT(codec, bs, 0, 1, "end", NULL); } else { /*mask flag*/ GF_BIFS_WRITE_INT(codec, bs, 1, 1, "Mask", NULL); } if (use_list) GF_BIFS_WRITE_INT(codec, bs, i, nbBits, "field", (char*)field.name); field.far_ptr = inf->field_ptr; e = gf_bifs_enc_field(codec, bs, com->node, &field); if (e) return e; } /*end flag*/ if (use_list) GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL); return GF_OK; } static GF_Err BE_GlobalQuantizer(GF_BifsEncoder * codec, GF_Command *com, GF_BitStream *bs) { GF_Err e; GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); if (inf->new_node) ((M_QuantizationParameter *)inf->new_node)->isLocal = 0; e = gf_bifs_enc_node(codec, inf->new_node, NDT_SFWorldNode, bs); if (e) return e; /*reset global QP*/ if (codec->GlobalQP) gf_node_unregister((GF_Node *) codec->GlobalQP, NULL); codec->GlobalQP = codec->ActiveQP = NULL; /*no QP*/ if (!inf->new_node) return GF_OK; /*register global QP*/ codec->GlobalQP = codec->ActiveQP = (M_QuantizationParameter *) inf->new_node; codec->GlobalQP->isLocal = 0; gf_node_register(inf->new_node, NULL); return GF_OK; } static GF_Err BE_EncProtoDelete(GF_BifsEncoder * codec, GF_Command *com, GF_BitStream *bs) { u32 nbBits, i; Bool use_list = 0; nbBits = gf_get_bit_size(com->del_proto_list_size); if (nbBits+5>com->del_proto_list_size) use_list = 1; GF_BIFS_WRITE_INT(codec, bs, use_list, 1, "isList", NULL); if (!use_list) { GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "len", NULL); GF_BIFS_WRITE_INT(codec, bs, com->del_proto_list_size, nbBits, "len", NULL); } for (i=0; idel_proto_list_size; i++) { if (use_list) GF_BIFS_WRITE_INT(codec, bs, 1, 1, "moreProto", NULL); GF_BIFS_WRITE_INT(codec, bs, com->del_proto_list[i], codec->info->config.ProtoIDBits, "protoID", NULL); } if (use_list) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "moreProto", NULL); return GF_OK; } static GF_Err BE_ExtendedUpdate(GF_BifsEncoder * codec, GF_Command *com, GF_BitStream *bs) { GF_BIFS_WRITE_INT(codec, bs, 0, 2, "Insert", NULL); GF_BIFS_WRITE_INT(codec, bs, 1, 2, "ExtendedUpdate", NULL); switch (com->tag) { case GF_SG_PROTO_INSERT: GF_BIFS_WRITE_INT(codec, bs, 0, 8, "MultipleReplace", NULL); return BE_EncProtoList(codec, com->new_proto_list, bs); case GF_SG_PROTO_DELETE: GF_BIFS_WRITE_INT(codec, bs, 1, 8, "ProtoDelete", NULL); return BE_EncProtoDelete(codec, com, bs); case GF_SG_PROTO_DELETE_ALL: GF_BIFS_WRITE_INT(codec, bs, 2, 8, "DeleteAllProtos", NULL); return GF_OK; case GF_SG_MULTIPLE_INDEXED_REPLACE: GF_BIFS_WRITE_INT(codec, bs, 3, 8, "MultipleReplace", NULL); return BE_MultipleIndexedReplace(codec, com, bs); case GF_SG_MULTIPLE_REPLACE: GF_BIFS_WRITE_INT(codec, bs, 4, 8, "MultipleReplace", NULL); return BE_MultipleReplace(codec, com, bs); case GF_SG_GLOBAL_QUANTIZER: GF_BIFS_WRITE_INT(codec, bs, 5, 8, "GlobalQuantizer", NULL); return BE_GlobalQuantizer(codec, com, bs); case GF_SG_NODE_DELETE_EX: GF_BIFS_WRITE_INT(codec, bs, 6, 8, "MultipleReplace", NULL); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); return GF_OK; default: return GF_BAD_PARAM; } } /*inserts a node in a container (node.children)*/ GF_Err BE_NodeInsert(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs) { u32 NDT; GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); NDT = gf_bifs_get_child_table(com->node); switch (inf->pos) { case 0: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "FIRST", "idx"); break; case -1: GF_BIFS_WRITE_INT(codec, bs, 3, 2, "LAST", "idx"); break; default: GF_BIFS_WRITE_INT(codec, bs, 0, 2, "pos", "idx"); GF_BIFS_WRITE_INT(codec, bs, inf->pos, 8, "pos", NULL); break; } return gf_bifs_enc_node(codec, inf->new_node, NDT, bs); } GF_Err BE_IndexInsert(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs) { GF_Err e; u32 NumBits, ind; GF_FieldInfo field, sffield; GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); /*index insertion uses IN mode for field index*/ NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(com->node, GF_SG_FIELD_CODING_IN)-1); gf_bifs_field_index_by_mode(com->node, inf->fieldIndex, GF_SG_FIELD_CODING_IN, &ind); GF_BIFS_WRITE_INT(codec, bs, ind, NumBits, "field", NULL); switch (inf->pos) { case 0: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "FIRST", "idx"); break; case -1: GF_BIFS_WRITE_INT(codec, bs, 3, 2, "LAST", "idx"); break; default: GF_BIFS_WRITE_INT(codec, bs, 0, 2, "pos", "idx"); GF_BIFS_WRITE_INT(codec, bs, inf->pos, 16, "pos", NULL); break; } e = gf_node_get_field(com->node, inf->fieldIndex, &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); sffield.far_ptr = inf->field_ptr; /*rescale the MFField and parse the SFField*/ if (field.fieldType==GF_SG_VRML_MFNODE) { return gf_bifs_enc_node(codec, inf->new_node, field.NDTtype, bs); } else { return gf_bifs_enc_sf_field(codec, bs, com->node, &sffield); } } GF_Err BE_IndexDelete(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs) { u32 NumBits, ind; GF_Err e; GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(com->node, GF_SG_FIELD_CODING_IN) - 1); e = gf_bifs_field_index_by_mode(com->node, inf->fieldIndex, GF_SG_FIELD_CODING_IN, &ind); if (e) return e; GF_BIFS_WRITE_INT(codec, bs, ind, NumBits, "field", NULL); switch (inf->pos) { case 0: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "FIRST", "idw"); break; case -1: GF_BIFS_WRITE_INT(codec, bs, 3, 2, "LAST", "idx"); break; default: GF_BIFS_WRITE_INT(codec, bs, 0, 2, "pos", "idx"); GF_BIFS_WRITE_INT(codec, bs, inf->pos, 16, "pos", NULL); break; } return GF_OK; } GF_Err BE_NodeReplace(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs) { GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); return gf_bifs_enc_node(codec, inf->new_node, NDT_SFWorldNode, bs); } GF_Err BE_FieldReplace(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs) { GF_Err e; u32 ind, NumBits; GF_FieldInfo field; GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(com->node, GF_SG_FIELD_CODING_IN)-1); gf_bifs_field_index_by_mode(com->node, inf->fieldIndex, GF_SG_FIELD_CODING_IN, &ind); GF_BIFS_WRITE_INT(codec, bs, ind, NumBits, "field", NULL); e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; field.far_ptr = inf->field_ptr; /* Warning: To be changed when proper solution is found */ if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFSCRIPT) codec->is_encoding_command = 1; e = gf_bifs_enc_field(codec, bs, com->node, &field); codec->is_encoding_command = 0; return e; } GF_Err BE_IndexFieldReplace(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs) { u32 ind, NumBits; GF_Err e; GF_FieldInfo field, sffield; GF_CommandField *inf; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField *)gf_list_get(com->command_fields, 0); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); NumBits = gf_get_bit_size(gf_node_get_num_fields_in_mode(com->node, GF_SG_FIELD_CODING_IN)-1); gf_bifs_field_index_by_mode(com->node, inf->fieldIndex, GF_SG_FIELD_CODING_IN, &ind); GF_BIFS_WRITE_INT(codec, bs, ind, NumBits, "field", NULL); e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; switch (inf->pos) { case 0: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "FIRST", "idx"); break; case -1: GF_BIFS_WRITE_INT(codec, bs, 3, 2, "LAST", "idx"); break; default: GF_BIFS_WRITE_INT(codec, bs, 0, 2, "pos", "idx"); GF_BIFS_WRITE_INT(codec, bs, inf->pos, 16, "pos", NULL); break; } if (field.fieldType == GF_SG_VRML_MFNODE) { e = gf_bifs_enc_node(codec, inf->new_node, field.NDTtype, bs); } else { memcpy(&sffield, &field, sizeof(GF_FieldInfo)); sffield.fieldType = gf_sg_vrml_get_sf_type(field.fieldType); sffield.far_ptr = inf->field_ptr; e = gf_bifs_enc_sf_field(codec, bs, com->node, &sffield); } return e; } GF_Err BE_RouteReplace(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs, Bool isInsert) { GF_Err e; GF_Node *n; u32 numBits, ind; if (isInsert) { GF_BIFS_WRITE_INT(codec, bs, com->RouteID ? 1 : 0, 1, "isDEF", NULL); if (com->RouteID) { GF_BIFS_WRITE_INT(codec, bs, com->RouteID-1, codec->info->config.RouteIDBits, "RouteID", NULL); if (codec->info->UseName) gf_bifs_enc_name(codec, bs, com->def_name); } } else { GF_BIFS_WRITE_INT(codec, bs, com->RouteID - 1, codec->info->config.RouteIDBits, "RouteID", NULL); } /*origin*/ GF_BIFS_WRITE_INT(codec, bs, com->fromNodeID - 1, codec->info->config.NodeIDBits, "outNodeID", NULL); n = gf_bifs_enc_find_node(codec, com->fromNodeID); numBits = gf_node_get_num_fields_in_mode(n, GF_SG_FIELD_CODING_OUT) - 1; numBits = gf_get_bit_size(numBits); e = gf_bifs_field_index_by_mode(n, com->fromFieldIndex, GF_SG_FIELD_CODING_OUT, &ind); if (e) return e; GF_BIFS_WRITE_INT(codec, bs, ind, numBits, "outField", NULL); /*target*/ GF_BIFS_WRITE_INT(codec, bs, com->toNodeID - 1, codec->info->config.NodeIDBits, "inNodeID", NULL); n = gf_bifs_enc_find_node(codec, com->toNodeID); numBits = gf_node_get_num_fields_in_mode(n, GF_SG_FIELD_CODING_IN) - 1; numBits = gf_get_bit_size(numBits); e = gf_bifs_field_index_by_mode(n, com->toFieldIndex, GF_SG_FIELD_CODING_IN, &ind); GF_BIFS_WRITE_INT(codec, bs, ind, numBits, "inField", NULL); return e; } GF_Err BE_EncProtoList(GF_BifsEncoder *codec, GF_List *protoList, GF_BitStream *bs) { u8 useQuant, useAnim; u32 i, j, nbRoutes, nbBits, numProtos, numFields, count; GF_Node *node; GF_ProtoFieldInterface *proto_field; GF_Proto *proto, *prev_proto; GF_Route *r; GF_Err e; GF_SceneGraph *rootSG; GF_FieldInfo field; e = GF_OK; if (!protoList || !gf_list_count(protoList)) { GF_BIFS_WRITE_INT(codec, bs, 0, 1, "moreProto", NULL); return GF_OK; } if (!codec->info->config.ProtoIDBits) return GF_NON_COMPLIANT_BITSTREAM; /*store state*/ rootSG = codec->current_proto_graph; prev_proto = codec->encoding_proto; numProtos = gf_list_count(protoList); for (i=0; iencoding_proto = proto; codec->current_proto_graph = proto->sub_graph; GF_BIFS_WRITE_INT(codec, bs, 1, 1, "moreProto", NULL); /*1- proto interface declaration*/ GF_BIFS_WRITE_INT(codec, bs, proto->ID, codec->info->config.ProtoIDBits, "protoID", NULL); if (codec->info->UseName) gf_bifs_enc_name(codec, bs, proto->Name); numFields = gf_list_count(proto->proto_fields); for (j=0; jproto_fields, j); GF_BIFS_WRITE_INT(codec, bs, 1, 1, "moreField", NULL); GF_BIFS_WRITE_INT(codec, bs, proto_field->EventType, 2, "eventType", NULL); GF_BIFS_WRITE_INT(codec, bs, proto_field->FieldType, 6, "fieldType", NULL); if (codec->info->UseName) gf_bifs_enc_name(codec, bs, proto_field->FieldName); switch (proto_field->EventType) { case GF_SG_EVENT_EXPOSED_FIELD: case GF_SG_EVENT_FIELD: gf_sg_proto_field_get_field(proto_field, &field); if (gf_sg_vrml_is_sf_field(field.fieldType)) { e = gf_bifs_enc_sf_field(codec, bs, NULL, &field); } else { if (codec->info->config.UsePredictiveMFField) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "usePredictive", NULL); e = gf_bifs_enc_mf_field(codec, bs, NULL, &field); } if (e) goto exit; break; } if (proto_field->QP_Type) useQuant = 1; if (proto_field->Anim_Type) useAnim = 1; } GF_BIFS_WRITE_INT(codec, bs, 0, 1, "moreField", NULL); GF_BIFS_WRITE_INT(codec, bs, proto->ExternProto.count ? 1 : 0, 1, "externProto", NULL); /*externProto*/ if (proto->ExternProto.count) { memset(&field, 0, sizeof(GF_FieldInfo)); field.far_ptr = &proto->ExternProto; field.fieldType = GF_SG_VRML_MFURL; field.name = "ExternProto"; if (codec->info->config.UsePredictiveMFField) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "usePredictive", NULL); e = gf_bifs_enc_mf_field(codec, bs, NULL, &field); if (e) goto exit; } else { /*encode sub-proto list*/ e = BE_EncProtoList(codec, proto->sub_graph->protos, bs); if (e) goto exit; count = gf_list_count(proto->node_code); for (j=0; jnode_code, j); e = gf_bifs_enc_node(codec, node, NDT_SFWorldNode, bs); if (e) goto exit; GF_BIFS_WRITE_INT(codec, bs, (j+1==count) ? 0 : 1, 1, "moreNodes", NULL); } /*encode routes routes*/ nbRoutes = count = gf_list_count(proto->sub_graph->Routes); for (j=0; jsub_graph->Routes, j); if (r->IS_route) nbRoutes--; } GF_BIFS_WRITE_INT(codec, bs, nbRoutes ? 1 : 0, 1, "hasRoute", NULL); if (nbRoutes) { nbBits = gf_get_bit_size(nbRoutes); if (nbBits + 5 > nbRoutes) { GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isList", NULL); /*list*/ for (j=0; jsub_graph->Routes, j); if (r->IS_route) continue; e = gf_bifs_enc_route(codec, r, bs); if (e) goto exit; nbRoutes--; GF_BIFS_WRITE_INT(codec, bs, nbRoutes ? 1 : 0, 1, "moreRoute", NULL); } } else { GF_BIFS_WRITE_INT(codec, bs, 0, 1, "isList", NULL); GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, nbRoutes, nbBits, "length", NULL); for (j=0; jsub_graph->Routes, j); if (r->IS_route) continue; e = gf_bifs_enc_route(codec, r, bs); if (e) goto exit; } } } } /*anim and Quantization stuff*/ GF_BIFS_WRITE_INT(codec, bs, useQuant, 1, "useQuant", NULL); GF_BIFS_WRITE_INT(codec, bs, useAnim, 1, "useAnim", NULL); if (!useAnim && !useQuant) continue; count = gf_sg_proto_get_field_count(proto); for (j=0; jQP_Type, 4, "QPType", NULL); if (proto_field->QP_Type==QC_LINEAR_SCALAR) GF_BIFS_WRITE_INT(codec, bs, proto_field->NumBits, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, proto_field->hasMinMax, 1, "hasMinMax", NULL); if (proto_field->hasMinMax) { field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType); switch (field.fieldType) { case GF_SG_VRML_SFINT32: case GF_SG_VRML_SFTIME: break; default: field.fieldType = GF_SG_VRML_SFFLOAT; break; } field.name = "QPMinValue"; field.far_ptr = proto_field->qp_min_value; gf_bifs_enc_sf_field(codec, bs, NULL, &field); field.name = "QPMaxValue"; field.far_ptr = proto_field->qp_max_value; gf_bifs_enc_sf_field(codec, bs, NULL, &field); } } /*anim - not supported yet*/ if (useAnim && ( (field.eventType == GF_SG_EVENT_IN) || (field.eventType == GF_SG_EVENT_EXPOSED_FIELD) )) { e = GF_NOT_SUPPORTED; goto exit; } } } GF_BIFS_WRITE_INT(codec, bs, 0, 1, "moreProto", NULL); exit: /*restore scene graph state*/ codec->encoding_proto = prev_proto; codec->current_proto_graph = rootSG; return e; } GF_Err gf_bifs_enc_route(GF_BifsEncoder *codec, GF_Route *r, GF_BitStream *bs) { GF_Err e; u32 numBits, ind; if (!r) return GF_BAD_PARAM; GF_BIFS_WRITE_INT(codec, bs, r->ID ? 1: 0, 1, "isDEF", NULL); /*def'ed route*/ if (r->ID) { GF_BIFS_WRITE_INT(codec, bs, r->ID-1, codec->info->config.RouteIDBits, "routeID", NULL); if (codec->info->UseName) gf_bifs_enc_name(codec, bs, r->name); } /*origin*/ GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(r->FromNode) - 1, codec->info->config.NodeIDBits, "outNodeID", NULL); numBits = gf_node_get_num_fields_in_mode(r->FromNode, GF_SG_FIELD_CODING_OUT) - 1; numBits = gf_get_bit_size(numBits); e = gf_bifs_field_index_by_mode(r->FromNode, r->FromField.fieldIndex, GF_SG_FIELD_CODING_OUT, &ind); if (e) return e; GF_BIFS_WRITE_INT(codec, bs, ind, numBits, "outField", NULL); /*target*/ GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(r->ToNode) - 1, codec->info->config.NodeIDBits, "inNodeID", NULL); numBits = gf_node_get_num_fields_in_mode(r->ToNode, GF_SG_FIELD_CODING_IN) - 1; numBits = gf_get_bit_size(numBits); e = gf_bifs_field_index_by_mode(r->ToNode, r->ToField.fieldIndex, GF_SG_FIELD_CODING_IN, &ind); GF_BIFS_WRITE_INT(codec, bs, ind, numBits, "inField", NULL); return e; } GF_Err BE_SceneReplaceEx(GF_BifsEncoder *codec, GF_Command *com, GF_BitStream *bs, GF_List *routes) { u32 i, nbR, nbBits; GF_Err e; /*reserved*/ GF_BIFS_WRITE_INT(codec, bs, 0, 6, "reserved", NULL); GF_BIFS_WRITE_INT(codec, bs, codec->info->UseName ? 1 : 0, 1, "useName", NULL); e = BE_EncProtoList(codec, com->new_proto_list, bs); if (e) goto exit; /*NULL root is valid for ProtoLibraries*/ e = gf_bifs_enc_node(codec, com->node, NDT_SFTopNode, bs); if (e || !gf_list_count(routes) ) { GF_BIFS_WRITE_INT(codec, bs, 0, 1, "hasRoute", NULL); return codec->LastError = e; } GF_BIFS_WRITE_INT(codec, bs, 1, 1, "hasRoute", NULL); nbR = gf_list_count(routes); nbBits = gf_get_bit_size(nbR); if (nbBits + 5 > nbR) { GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isList", NULL); /*list*/ for (i=0; iLastError = e; } GF_Err BE_SceneReplace(GF_BifsEncoder *codec, GF_SceneGraph *graph, GF_BitStream *bs) { u32 i, nbR, nbBits; GF_Err e; /*reserved*/ GF_BIFS_WRITE_INT(codec, bs, 0, 6, "reserved", NULL); GF_BIFS_WRITE_INT(codec, bs, codec->info->UseName ? 1 : 0, 1, "useName", NULL); /*assign current graph*/ codec->scene_graph = graph; e = BE_EncProtoList(codec, codec->scene_graph ? codec->scene_graph->protos : NULL, bs); if (e) goto exit; /*NULL root is valid for ProtoLibraries*/ e = gf_bifs_enc_node(codec, graph ? graph->RootNode : NULL, NDT_SFTopNode, bs); if (e || !graph || !gf_list_count(graph->Routes) ) { GF_BIFS_WRITE_INT(codec, bs, 0, 1, "hasRoute", NULL); return codec->LastError = e; } GF_BIFS_WRITE_INT(codec, bs, 1, 1, "hasRoute", NULL); nbR = gf_list_count(graph->Routes); nbBits = gf_get_bit_size(nbR); if (nbBits + 5 > nbR) { GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isList", NULL); /*list*/ for (i=0; iRoutes, i), bs); if (e) goto exit; GF_BIFS_WRITE_INT(codec, bs, (i+1==nbR) ? 0 : 1, 1, "moreRoute", NULL); } } else { GF_BIFS_WRITE_INT(codec, bs, 0, 1, "isList", NULL); GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, nbR, nbBits, "nbRoutes", NULL); for (i=0; iRoutes, i), bs); if (e) goto exit; } } exit: return codec->LastError = e; } GF_Err gf_bifs_enc_commands(GF_BifsEncoder *codec, GF_List *comList, GF_BitStream *bs) { u32 i; u32 count; GF_List *routes; GF_Err e = GF_OK; routes = NULL; codec->LastError = GF_OK; count = gf_list_count(comList); for (i=0; itag) { case GF_SG_SCENE_REPLACE: { /*reset node context*/ while (gf_list_count(codec->encoded_nodes)) gf_list_rem(codec->encoded_nodes, 0); GF_BIFS_WRITE_INT(codec, bs, 3, 2, "SceneReplace", NULL); routes = gf_list_new(); /*now the trick: get all following InsertRoutes and convert as routes*/ for (; itag!=GF_SG_ROUTE_INSERT) break; GF_SAFEALLOC(r, GF_Route); r->FromField.fieldIndex = rcom->fromFieldIndex; r->FromNode = gf_sg_find_node(codec->scene_graph, rcom->fromNodeID); r->ToField.fieldIndex = rcom->toFieldIndex; r->ToNode = gf_sg_find_node(codec->scene_graph, rcom->toNodeID); r->ID = rcom->RouteID; r->name = rcom->def_name; gf_list_add(routes, r); } e = BE_SceneReplaceEx(codec, com, bs, routes); } break; /*replace commands*/ case GF_SG_NODE_REPLACE: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "Replace", NULL); GF_BIFS_WRITE_INT(codec, bs, 0, 2, "Node", NULL); e = BE_NodeReplace(codec, com, bs); break; case GF_SG_FIELD_REPLACE: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "Replace", NULL); GF_BIFS_WRITE_INT(codec, bs, 1, 2, "Field", NULL); e = BE_FieldReplace(codec, com, bs); break; case GF_SG_INDEXED_REPLACE: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "Replace", NULL); GF_BIFS_WRITE_INT(codec, bs, 2, 2, "FieldIndex", NULL); e = BE_IndexFieldReplace(codec, com, bs); break; case GF_SG_ROUTE_REPLACE: GF_BIFS_WRITE_INT(codec, bs, 2, 2, "Replace", NULL); GF_BIFS_WRITE_INT(codec, bs, 3, 2, "Route", NULL); e = BE_RouteReplace(codec, com, bs, 0); break; case GF_SG_NODE_INSERT: GF_BIFS_WRITE_INT(codec, bs, 0, 2, "Insert", NULL); GF_BIFS_WRITE_INT(codec, bs, 0, 2, "Node", NULL); e = BE_NodeInsert(codec, com, bs); break; case GF_SG_INDEXED_INSERT: GF_BIFS_WRITE_INT(codec, bs, 0, 2, "Insert", NULL); GF_BIFS_WRITE_INT(codec, bs, 2, 2, "FieldIndex", NULL); e = BE_IndexInsert(codec, com, bs); break; case GF_SG_ROUTE_INSERT: GF_BIFS_WRITE_INT(codec, bs, 0, 2, "Insert", NULL); GF_BIFS_WRITE_INT(codec, bs, 3, 2, "Route", NULL); e = BE_RouteReplace(codec, com, bs, 1); break; case GF_SG_NODE_DELETE: GF_BIFS_WRITE_INT(codec, bs, 1, 2, "Delete", NULL); GF_BIFS_WRITE_INT(codec, bs, 0, 2, "Node", NULL); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(com->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); break; case GF_SG_INDEXED_DELETE: GF_BIFS_WRITE_INT(codec, bs, 1, 2, "Delete", NULL); GF_BIFS_WRITE_INT(codec, bs, 2, 2, "FieldIndex", NULL); e = BE_IndexDelete(codec, com, bs); break; case GF_SG_ROUTE_DELETE: GF_BIFS_WRITE_INT(codec, bs, 1, 2, "Delete", NULL); GF_BIFS_WRITE_INT(codec, bs, 3, 2, "Route", NULL); GF_BIFS_WRITE_INT(codec, bs, com->RouteID - 1, codec->info->config.RouteIDBits, "RouteID", NULL); break; default: e = BE_ExtendedUpdate(codec, com, bs); break; } if (e) break; GF_BIFS_WRITE_INT(codec, bs, (i+1==count) ? 0 : 1, 1, "moreCommands", NULL); } if (routes) { while (gf_list_count(routes)) { GF_Route *r = (GF_Route*)gf_list_get(routes, 0); gf_list_rem(routes, 0); free(r); } gf_list_del(routes); } while (gf_list_count(codec->QPs)) gf_bifs_enc_qp_remove(codec, 1); return e; } GF_EXPORT GF_Err gf_bifs_encoder_get_rap(GF_BifsEncoder *codec, char **out_data, u32 *out_data_length) { GF_BitStream *bs; GF_Err e; GF_List *ctx_bck; /*reset context for RAP encoding*/ ctx_bck = codec->encoded_nodes; codec->encoded_nodes = gf_list_new(); if (!codec->info) codec->info = (BIFSStreamInfo*)gf_list_get(codec->streamInfo, 0); bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); GF_BIFS_WRITE_INT(codec, bs, 3, 2, "SceneReplace", NULL); e = BE_SceneReplace(codec, codec->scene_graph, bs); if (e == GF_OK) { GF_BIFS_WRITE_INT(codec, bs, 0, 1, "moreCommands", NULL); gf_bs_get_content(bs, out_data, out_data_length); } gf_bs_del(bs); /*restore context*/ gf_list_del(codec->encoded_nodes); codec->encoded_nodes = ctx_bck; return e; }