Ejemplo n.º 1
0
/*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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);
	}
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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;
}