/*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); }
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->scene_graph->global_qp) { gf_node_unregister(codec->scene_graph->global_qp, NULL); codec->scene_graph->global_qp = NULL; } codec->ActiveQP = NULL; /*no QP*/ if (!inf->new_node) return GF_OK; /*register global QP*/ codec->scene_graph->global_qp = inf->new_node; gf_node_register(inf->new_node, NULL); codec->ActiveQP = (M_QuantizationParameter *) inf->new_node; codec->ActiveQP->isLocal = 0; 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_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->UseName ? 1 : 0, 1, "useName", NULL); if (gf_list_count(com->new_proto_list)) { e = BE_EncProtoList(codec, com->new_proto_list, bs); if (e) goto exit; } else { e = BE_EncProtoList(codec, com->in_scene->protos, 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; i<nbR; i++) { e = gf_bifs_enc_route(codec, (GF_Route*)gf_list_get(routes, 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; i<nbR; i++) { e = gf_bifs_enc_route(codec, (GF_Route*)gf_list_get(routes, i), bs); if (e) goto exit; } } exit: return codec->LastError = 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->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; i<nbR; i++) { e = gf_bifs_enc_route(codec, (GF_Route*)gf_list_get(graph->Routes, 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; i<nbR; i++) { e = gf_bifs_enc_route(codec, (GF_Route*)gf_list_get(graph->Routes, i), bs); if (e) goto exit; } } exit: return codec->LastError = e; }
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 gf_bifs_enc_sf_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field) { GF_Err e; if (node) { e = gf_bifs_enc_quant_field(codec, bs, node, field); if (e != GF_EOS) return e; } switch (field->fieldType) { case GF_SG_VRML_SFBOOL: GF_BIFS_WRITE_INT(codec, bs, * ((SFBool *)field->far_ptr), 1, "SFBool", NULL); break; case GF_SG_VRML_SFCOLOR: BE_WriteSFFloat(codec, ((SFColor *)field->far_ptr)->red, bs, "color.red"); BE_WriteSFFloat(codec, ((SFColor *)field->far_ptr)->green, bs, "color.green"); BE_WriteSFFloat(codec, ((SFColor *)field->far_ptr)->blue, bs, "color.blue"); break; case GF_SG_VRML_SFFLOAT: BE_WriteSFFloat(codec, * ((SFFloat *)field->far_ptr), bs, NULL); break; case GF_SG_VRML_SFINT32: GF_BIFS_WRITE_INT(codec, bs, * ((SFInt32 *)field->far_ptr), 32, "SFInt32", NULL); break; case GF_SG_VRML_SFROTATION: BE_WriteSFFloat(codec, ((SFRotation *)field->far_ptr)->x, bs, "rot.x"); BE_WriteSFFloat(codec, ((SFRotation *)field->far_ptr)->y, bs, "rot.y"); BE_WriteSFFloat(codec, ((SFRotation *)field->far_ptr)->z, bs, "rot.z"); BE_WriteSFFloat(codec, ((SFRotation *)field->far_ptr)->q, bs, "rot.theta"); break; case GF_SG_VRML_SFSTRING: if (node && (node->sgprivate->tag==TAG_MPEG4_CacheTexture) && (field->fieldIndex<=2)) { u32 size, val; char buf[4096]; char *res_src = NULL; const char *src = ((SFString*)field->far_ptr)->buffer; FILE *f; if (codec->src_url) res_src = gf_url_concatenate(codec->src_url, src); f = gf_fopen(res_src ? res_src : src, "rb"); if (!f) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[BIFS] Cannot open source file %s for encoding CacheTexture\n", res_src ? res_src : src)); return GF_URL_ERROR; } if (res_src) gf_free(res_src); gf_fseek(f, 0, SEEK_END); size = (u32) gf_ftell(f); val = gf_get_bit_size(size); GF_BIFS_WRITE_INT(codec, bs, val, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, size, val, "length", NULL); gf_fseek(f, 0, SEEK_SET); while (size) { u32 read = (u32) fread(buf, 1, 4096, f); gf_bs_write_data(bs, buf, read); size -= read; } } else { u32 i, val, len; char *str = (char *) ((SFString*)field->far_ptr)->buffer; if (node && (node->sgprivate->tag==TAG_MPEG4_BitWrapper) ) { len = ((M_BitWrapper*)node)->buffer_len; } else { len = str ? (u32) strlen(str) : 0; } val = gf_get_bit_size(len); GF_BIFS_WRITE_INT(codec, bs, val, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, len, val, "length", NULL); for (i=0; i<len; i++) gf_bs_write_int(bs, str[i], 8); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] string\t\t%d\t\t%s\n", 8*len, str) ); } break; case GF_SG_VRML_SFTIME: gf_bs_write_double(bs, *((SFTime *)field->far_ptr)); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] SFTime\t\t%d\t\t%g\n", 64, *((SFTime *)field->far_ptr))); break; case GF_SG_VRML_SFVEC2F: BE_WriteSFFloat(codec, ((SFVec2f *)field->far_ptr)->x, bs, "vec2f.x"); BE_WriteSFFloat(codec, ((SFVec2f *)field->far_ptr)->y, bs, "vec2f.y"); break; case GF_SG_VRML_SFVEC3F: BE_WriteSFFloat(codec, ((SFVec3f *)field->far_ptr)->x, bs, "vec3f.x"); BE_WriteSFFloat(codec, ((SFVec3f *)field->far_ptr)->y, bs, "vec3f.y"); BE_WriteSFFloat(codec, ((SFVec3f *)field->far_ptr)->z, bs, "vec3f.z"); break; case GF_SG_VRML_SFURL: { SFURL *url = (SFURL *) field->far_ptr; GF_BIFS_WRITE_INT(codec, bs, (url->OD_ID>0) ? 1 : 0, 1, "hasODID", "SFURL"); if (url->OD_ID>0) { GF_BIFS_WRITE_INT(codec, bs, url->OD_ID, 10, "ODID", "SFURL"); } else { u32 i, len = url->url ? (u32) strlen(url->url) : 0; u32 val = gf_get_bit_size(len); GF_BIFS_WRITE_INT(codec, bs, val, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, len, val, "length", NULL); for (i=0; i<len; i++) gf_bs_write_int(bs, url->url[i], 8); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] string\t\t%d\t\t%s\t\t//SFURL\n", 8*len, url->url)); } } break; case GF_SG_VRML_SFIMAGE: { u32 size, i; SFImage *img = (SFImage *)field->far_ptr; GF_BIFS_WRITE_INT(codec, bs, img->width, 12, "width", "SFImage"); GF_BIFS_WRITE_INT(codec, bs, img->height, 12, "height", "SFImage"); GF_BIFS_WRITE_INT(codec, bs, img->numComponents - 1, 2, "nbComp", "SFImage"); size = img->width * img->height * img->numComponents; for (i=0; i<size; i++) gf_bs_write_int(bs, img->pixels[i], 8); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] pixels\t\t%d\t\tnot dumped\t\t//SFImage\n", 8*size)); } break; case GF_SG_VRML_SFCOMMANDBUFFER: { SFCommandBuffer *cb = (SFCommandBuffer *) field->far_ptr; if (cb->buffer) gf_free(cb->buffer); cb->buffer = NULL; cb->bufferSize = 0; if (gf_list_count(cb->commandList)) { u32 i, nbBits; GF_BitStream *bs_cond = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] /*SFCommandBuffer*/\n" )); e = gf_bifs_enc_commands(codec, cb->commandList, bs_cond); if (!e) gf_bs_get_content(bs_cond, (char**)&cb->buffer, &cb->bufferSize); gf_bs_del(bs_cond); if (e) return e; GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] /*End SFCommandBuffer*/\n")); nbBits = gf_get_bit_size(cb->bufferSize); GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "NbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, cb->bufferSize, nbBits, "BufferSize", NULL); for (i=0; i<cb->bufferSize; i++) GF_BIFS_WRITE_INT(codec, bs, cb->buffer[i], 8, "buffer byte", NULL); } /*empty command buffer*/ else { GF_BIFS_WRITE_INT(codec, bs, 0, 5, "NbBits", NULL); } } break; case GF_SG_VRML_SFNODE: return gf_bifs_enc_node(codec, *((GF_Node **)field->far_ptr), field->NDTtype, bs, node); case GF_SG_VRML_SFSCRIPT: #ifdef GPAC_HAS_SPIDERMONKEY codec->LastError = SFScript_Encode(codec, (SFScript *)field->far_ptr, bs, node); #else return GF_NOT_SUPPORTED; #endif break; case GF_SG_VRML_SFATTRREF: { u32 idx=0; SFAttrRef *ar = (SFAttrRef *)field->far_ptr; u32 nbBitsDEF = gf_get_bit_size(gf_node_get_num_fields_in_mode(ar->node, GF_SG_FIELD_CODING_DEF) - 1); GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(ar->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL); gf_bifs_field_index_by_mode(ar->node, ar->fieldIndex, GF_SG_FIELD_CODING_DEF, &idx); GF_BIFS_WRITE_INT(codec, bs, idx, nbBitsDEF, "field", NULL); } break; default: return GF_NOT_SUPPORTED; } return codec->LastError; }
GF_Err gf_bifs_enc_mf_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field) { GF_ChildNodeItem *list = NULL; GF_Err e; u32 nbBits, qp_local; Bool use_list, qp_on, initial_qp; u32 nbF, i; GF_FieldInfo sffield; nbF = 0; if (field->fieldType != GF_SG_VRML_MFNODE) { nbF = field->far_ptr ? ((GenMFField *)field->far_ptr)->count : 0; if (!nbF && (field->fieldType == GF_SG_VRML_MFSCRIPT)) nbF = 1; } else if (field->far_ptr) { list = *((GF_ChildNodeItem **)field->far_ptr); nbF = gf_node_list_get_count(list); } /*reserved*/ GF_BIFS_WRITE_INT(codec, bs, 0, 1, "reserved", NULL); if (!nbF) { /*is list*/ GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isList", NULL); /*end flag*/ GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL); return GF_OK; } /*do we work in list or vector*/ use_list = GF_FALSE; nbBits = gf_get_bit_size(nbF); if (nbBits + 5 > nbF + 1) use_list = GF_TRUE; GF_BIFS_WRITE_INT(codec, bs, use_list, 1, "isList", NULL); if (!use_list) { GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, nbF, nbBits, "length", NULL); } memset(&sffield, 0, sizeof(GF_FieldInfo)); sffield.fieldIndex = field->fieldIndex; sffield.fieldType = gf_sg_vrml_get_sf_type(field->fieldType); sffield.NDTtype = field->NDTtype; initial_qp = qp_on = GF_FALSE; qp_local = 0; initial_qp = codec->ActiveQP ? GF_TRUE : GF_FALSE; for (i=0; i<nbF; i++) { if (use_list) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "end", NULL); if (field->fieldType != GF_SG_VRML_MFNODE) { gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &sffield.far_ptr, i); e = gf_bifs_enc_sf_field(codec, bs, node, &sffield); } else { assert(list); e = gf_bifs_enc_node(codec, list->node, field->NDTtype, bs, node); /*activate QP*/ if (list->node->sgprivate->tag == TAG_MPEG4_QuantizationParameter) { qp_local = ((M_QuantizationParameter *)list->node)->isLocal; if (qp_on) gf_bifs_enc_qp_remove(codec, GF_FALSE); e = gf_bifs_enc_qp_set(codec, list->node); if (e) return e; qp_on = GF_TRUE; if (qp_local) qp_local = 2; } list = list->next; } if (e) return e; if (qp_on && qp_local) { if (qp_local == 2) qp_local -= 1; else { gf_bifs_enc_qp_remove(codec, initial_qp); qp_local = qp_on = GF_FALSE; } } } if (use_list) GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL); if (qp_on) gf_bifs_enc_qp_remove(codec, initial_qp); /*for QP14*/ gf_bifs_enc_qp14_set_length(codec, nbF); return GF_OK; }
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; i<numProtos; i++) { proto = (GF_Proto*)gf_list_get(protoList, i); useQuant = useAnim = 0; /*set current proto state*/ codec->encoding_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->UseName) gf_bifs_enc_name(codec, bs, proto->Name); numFields = gf_list_count(proto->proto_fields); for (j=0; j<numFields; j++) { proto_field = (GF_ProtoFieldInterface*)gf_list_get(proto->proto_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->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); /*BIFS cannot encode empty protos ! We therefore encode a NULL node instead*/ if (!count) { gf_bifs_enc_node(codec, NULL, NDT_SFWorldNode, bs); GF_BIFS_WRITE_INT(codec, bs, 0, 1, "moreNodes", NULL); } else { for (j=0; j<count; j++) { /*parse all nodes in SFWorldNode table*/ node = (GF_Node*)gf_list_get(proto->node_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; j<count; j++) { r = (GF_Route*)gf_list_get(proto->sub_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; j<count; j++) { r = (GF_Route*)gf_list_get(proto->sub_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; j<count; j++) { r = (GF_Route*)gf_list_get(proto->sub_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; j<count; j++) { proto_field = gf_sg_proto_field_find(proto, j); gf_sg_proto_field_get_field(proto_field, &field); /*quant*/ if (useQuant && ( (field.eventType == GF_SG_EVENT_FIELD) || (field.eventType == GF_SG_EVENT_EXPOSED_FIELD) )) { GF_BIFS_WRITE_INT(codec, bs, proto_field->QP_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; }