1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2000-2020
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / BIFS codec sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 
27 
28 #include <gpac/internal/bifs_dev.h>
29 #include <gpac/internal/bifs_tables.h>
30 #include <gpac/network.h>
31 #include "quant.h"
32 #include "script.h"
33 
34 #ifndef GPAC_DISABLE_BIFS_ENC
35 
gf_bifs_field_index_by_mode(GF_Node * node,u32 all_ind,u8 indexMode,u32 * outField)36 GF_Err gf_bifs_field_index_by_mode(GF_Node *node, u32 all_ind, u8 indexMode, u32 *outField)
37 {
38 	GF_Err e;
39 	u32 i, count, temp;
40 	count = gf_node_get_num_fields_in_mode(node, indexMode);
41 	for (i=0; i<count; i++) {
42 		e = gf_bifs_get_field_index(node, i, indexMode, &temp);
43 		if (e) return e;
44 		if (temp==all_ind) {
45 			*outField = i;
46 			return GF_OK;
47 		}
48 	}
49 	return GF_BAD_PARAM;
50 }
51 
52 
BE_WriteSFFloat(GF_BifsEncoder * codec,Fixed val,GF_BitStream * bs,char * com)53 void BE_WriteSFFloat(GF_BifsEncoder *codec, Fixed val, GF_BitStream *bs, char *com)
54 {
55 	if (codec->ActiveQP && codec->ActiveQP->useEfficientCoding) {
56 		gf_bifs_enc_mantissa_float(codec, val, bs);
57 	} else {
58 		gf_bs_write_float(bs, FIX2FLT(val));
59 		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] SFFloat\t\t32\t\t%g\t\t%s\n", FIX2FLT(val), com ? com : "") );
60 	}
61 }
62 
63 
gf_bifs_enc_sf_field(GF_BifsEncoder * codec,GF_BitStream * bs,GF_Node * node,GF_FieldInfo * field)64 GF_Err gf_bifs_enc_sf_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field)
65 {
66 	GF_Err e;
67 
68 	if (node) {
69 		e = gf_bifs_enc_quant_field(codec, bs, node, field);
70 		if (e != GF_EOS) return e;
71 	}
72 	switch (field->fieldType) {
73 	case GF_SG_VRML_SFBOOL:
74 		GF_BIFS_WRITE_INT(codec, bs, * ((SFBool *)field->far_ptr), 1, "SFBool", NULL);
75 		break;
76 	case GF_SG_VRML_SFCOLOR:
77 		BE_WriteSFFloat(codec, ((SFColor *)field->far_ptr)->red, bs, "color.red");
78 		BE_WriteSFFloat(codec, ((SFColor *)field->far_ptr)->green, bs, "color.green");
79 		BE_WriteSFFloat(codec, ((SFColor *)field->far_ptr)->blue, bs, "color.blue");
80 		break;
81 	case GF_SG_VRML_SFFLOAT:
82 		BE_WriteSFFloat(codec, * ((SFFloat *)field->far_ptr), bs, NULL);
83 		break;
84 	case GF_SG_VRML_SFINT32:
85 		GF_BIFS_WRITE_INT(codec, bs, * ((SFInt32 *)field->far_ptr), 32, "SFInt32", NULL);
86 		break;
87 	case GF_SG_VRML_SFROTATION:
88 		BE_WriteSFFloat(codec, ((SFRotation  *)field->far_ptr)->x, bs, "rot.x");
89 		BE_WriteSFFloat(codec, ((SFRotation  *)field->far_ptr)->y, bs, "rot.y");
90 		BE_WriteSFFloat(codec, ((SFRotation  *)field->far_ptr)->z, bs, "rot.z");
91 		BE_WriteSFFloat(codec, ((SFRotation  *)field->far_ptr)->q, bs, "rot.theta");
92 		break;
93 
94 	case GF_SG_VRML_SFSTRING:
95 		if (node && (node->sgprivate->tag==TAG_MPEG4_CacheTexture) && (field->fieldIndex<=2)) {
96 			u32 size, val;
97 			char buf[4096];
98 			char *res_src = NULL;
99 			const char *src = ((SFString*)field->far_ptr)->buffer;
100 			FILE *f;
101 			if (codec->src_url) res_src = gf_url_concatenate(codec->src_url, src);
102 
103 			f = gf_fopen(res_src ? res_src : src, "rb");
104 			if (!f) {
105 				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[BIFS] Cannot open source file %s for encoding CacheTexture\n", res_src ? res_src : src));
106 				return GF_URL_ERROR;
107 			}
108 			if (res_src) gf_free(res_src);
109 			size = (u32) gf_fsize(f);
110 			val = gf_get_bit_size(size);
111 			GF_BIFS_WRITE_INT(codec, bs, val, 5, "nbBits", NULL);
112 			GF_BIFS_WRITE_INT(codec, bs, size, val, "length", NULL);
113 
114 			while (size) {
115 				u32 read = (u32) gf_fread(buf, 4096, f);
116 				gf_bs_write_data(bs, buf, read);
117 				size -= read;
118 			}
119 			gf_fclose(f);
120 		} else {
121 			u32 i, val, len;
122 			char *dump_str = NULL;
123 			char *str = (char *) ((SFString*)field->far_ptr)->buffer;
124 			if (node && (node->sgprivate->tag==TAG_MPEG4_BitWrapper) ) {
125 				len = ((M_BitWrapper*)node)->buffer_len;
126 			} else {
127 				len = str ? (u32) strlen(str) : 0;
128 				dump_str = str;
129 			}
130 			val = gf_get_bit_size(len);
131 			GF_BIFS_WRITE_INT(codec, bs, val, 5, "nbBits", NULL);
132 			GF_BIFS_WRITE_INT(codec, bs, len, val, "length", NULL);
133 			for (i=0; i<len; i++) gf_bs_write_int(bs, str[i], 8);
134 			if (dump_str) {
135 				GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] string\t\t%d\t\t%s\n", 8*len, str) );
136 			} else {
137 				GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] string\t\t%d\n", 8*len) );
138 			}
139 		}
140 		break;
141 
142 	case GF_SG_VRML_SFTIME:
143 		gf_bs_write_double(bs, *((SFTime *)field->far_ptr));
144 		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] SFTime\t\t%d\t\t%g\n", 64, *((SFTime *)field->far_ptr)));
145 		break;
146 
147 	case GF_SG_VRML_SFVEC2F:
148 		BE_WriteSFFloat(codec, ((SFVec2f *)field->far_ptr)->x, bs, "vec2f.x");
149 		BE_WriteSFFloat(codec, ((SFVec2f *)field->far_ptr)->y, bs, "vec2f.y");
150 		break;
151 
152 	case GF_SG_VRML_SFVEC3F:
153 		BE_WriteSFFloat(codec, ((SFVec3f *)field->far_ptr)->x, bs, "vec3f.x");
154 		BE_WriteSFFloat(codec, ((SFVec3f *)field->far_ptr)->y, bs, "vec3f.y");
155 		BE_WriteSFFloat(codec, ((SFVec3f *)field->far_ptr)->z, bs, "vec3f.z");
156 		break;
157 
158 	case GF_SG_VRML_SFURL:
159 	{
160 		SFURL *url = (SFURL *) field->far_ptr;
161 		GF_BIFS_WRITE_INT(codec, bs, (url->OD_ID>0) ? 1 : 0, 1, "hasODID", "SFURL");
162 		if (url->OD_ID>0) {
163 			GF_BIFS_WRITE_INT(codec, bs, url->OD_ID, 10, "ODID", "SFURL");
164 		} else {
165 			u32 i, len = url->url ? (u32) strlen(url->url) : 0;
166 			u32 val = gf_get_bit_size(len);
167 			GF_BIFS_WRITE_INT(codec, bs, val, 5, "nbBits", NULL);
168 			GF_BIFS_WRITE_INT(codec, bs, len, val, "length", NULL);
169 			for (i=0; i<len; i++) gf_bs_write_int(bs, url->url[i], 8);
170 			GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] string\t\t%d\t\t%s\t\t//SFURL\n", 8*len, url->url));
171 		}
172 	}
173 	break;
174 	case GF_SG_VRML_SFIMAGE:
175 	{
176 		u32 size, i;
177 		SFImage *img = (SFImage *)field->far_ptr;
178 		GF_BIFS_WRITE_INT(codec, bs, img->width, 12, "width", "SFImage");
179 		GF_BIFS_WRITE_INT(codec, bs, img->height, 12, "height", "SFImage");
180 		GF_BIFS_WRITE_INT(codec, bs, img->numComponents - 1, 2, "nbComp", "SFImage");
181 		size = img->width * img->height * img->numComponents;
182 		for (i=0; i<size; i++) gf_bs_write_int(bs, img->pixels[i], 8);
183 		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] pixels\t\t%d\t\tnot dumped\t\t//SFImage\n", 8*size));
184 	}
185 	break;
186 
187 	case GF_SG_VRML_SFCOMMANDBUFFER:
188 	{
189 		SFCommandBuffer *cb = (SFCommandBuffer *) field->far_ptr;
190 		if (cb->buffer) gf_free(cb->buffer);
191 		cb->buffer = NULL;
192 		cb->bufferSize = 0;
193 		if (gf_list_count(cb->commandList)) {
194 			u32 i, nbBits;
195 			GF_BitStream *bs_cond = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
196 			GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] /*SFCommandBuffer*/\n" ));
197 			e = gf_bifs_enc_commands(codec, cb->commandList, bs_cond);
198 			if (!e) gf_bs_get_content(bs_cond, &cb->buffer, &cb->bufferSize);
199 			gf_bs_del(bs_cond);
200 			if (e) return e;
201 			GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[BIFS] /*End SFCommandBuffer*/\n"));
202 			nbBits = gf_get_bit_size(cb->bufferSize);
203 			GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "NbBits", NULL);
204 			GF_BIFS_WRITE_INT(codec, bs, cb->bufferSize, nbBits, "BufferSize", NULL);
205 			for (i=0; i<cb->bufferSize; i++) GF_BIFS_WRITE_INT(codec, bs, cb->buffer[i], 8, "buffer byte", NULL);
206 		}
207 		/*empty command buffer*/
208 		else {
209 			GF_BIFS_WRITE_INT(codec, bs, 0, 5, "NbBits", NULL);
210 		}
211 	}
212 	break;
213 
214 	case GF_SG_VRML_SFNODE:
215 		return gf_bifs_enc_node(codec, *((GF_Node **)field->far_ptr), field->NDTtype, bs, node);
216 
217 	case GF_SG_VRML_SFSCRIPT:
218 #ifdef GPAC_HAS_QJS
219 		codec->LastError = SFScript_Encode(codec, (SFScript *)field->far_ptr, bs, node);
220 #else
221 		return GF_NOT_SUPPORTED;
222 #endif
223 		break;
224 	case GF_SG_VRML_SFATTRREF:
225 	{
226 		u32 idx=0;
227 		SFAttrRef *ar = (SFAttrRef *)field->far_ptr;
228 		u32 nbBitsDEF = gf_get_bit_size(gf_node_get_num_fields_in_mode(ar->node, GF_SG_FIELD_CODING_DEF) - 1);
229 		GF_BIFS_WRITE_INT(codec, bs, gf_node_get_id(ar->node) - 1, codec->info->config.NodeIDBits, "NodeID", NULL);
230 
231 		gf_bifs_field_index_by_mode(ar->node, ar->fieldIndex, GF_SG_FIELD_CODING_DEF, &idx);
232 		GF_BIFS_WRITE_INT(codec, bs, idx, nbBitsDEF, "field", NULL);
233 	}
234 	break;
235 	default:
236 		return GF_NOT_SUPPORTED;
237 	}
238 	return codec->LastError;
239 }
240 
241 
gf_bifs_enc_mf_field(GF_BifsEncoder * codec,GF_BitStream * bs,GF_Node * node,GF_FieldInfo * field)242 GF_Err gf_bifs_enc_mf_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field)
243 {
244 	GF_ChildNodeItem *list = NULL;
245 	GF_Err e;
246 	u32 nbBits, qp_local;
247 	Bool use_list, qp_on, initial_qp;
248 	u32 nbF, i;
249 	GF_FieldInfo sffield;
250 
251 	nbF = 0;
252 	if (field->fieldType != GF_SG_VRML_MFNODE) {
253 		nbF = field->far_ptr ? ((GenMFField *)field->far_ptr)->count : 0;
254 		if (!nbF && (field->fieldType == GF_SG_VRML_MFSCRIPT))
255 			nbF = 1;
256 	} else if (field->far_ptr) {
257 		list = *((GF_ChildNodeItem **)field->far_ptr);
258 		nbF = gf_node_list_get_count(list);
259 	}
260 	/*reserved*/
261 	GF_BIFS_WRITE_INT(codec, bs, 0, 1, "reserved", NULL);
262 	if (!nbF) {
263 		/*is list*/
264 		GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isList", NULL);
265 		/*end flag*/
266 		GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL);
267 		return GF_OK;
268 	}
269 
270 	/*do we work in list or vector*/
271 	use_list = GF_FALSE;
272 	nbBits = gf_get_bit_size(nbF);
273 	if (nbBits + 5 > nbF + 1) use_list = GF_TRUE;
274 
275 	GF_BIFS_WRITE_INT(codec, bs, use_list, 1, "isList", NULL);
276 	if (!use_list) {
277 		GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "nbBits", NULL);
278 		GF_BIFS_WRITE_INT(codec, bs, nbF, nbBits, "length", NULL);
279 	}
280 
281 	memset(&sffield, 0, sizeof(GF_FieldInfo));
282 	sffield.fieldIndex = field->fieldIndex;
283 	sffield.fieldType = gf_sg_vrml_get_sf_type(field->fieldType);
284 	sffield.NDTtype = field->NDTtype;
285 
286 	qp_on = GF_FALSE;
287 	qp_local = 0;
288 	initial_qp = codec->ActiveQP ? GF_TRUE : GF_FALSE;
289 	for (i=0; i<nbF; i++) {
290 
291 		if (use_list) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "end", NULL);
292 
293 		if (field->fieldType != GF_SG_VRML_MFNODE) {
294 			gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &sffield.far_ptr, i);
295 			e = gf_bifs_enc_sf_field(codec, bs, node, &sffield);
296 		} else {
297 			assert(list);
298 			e = gf_bifs_enc_node(codec, list->node, field->NDTtype, bs, node);
299 
300 			/*activate QP*/
301 			if (list->node->sgprivate->tag == TAG_MPEG4_QuantizationParameter) {
302 				qp_local = ((M_QuantizationParameter *)list->node)->isLocal;
303 				if (qp_on) gf_bifs_enc_qp_remove(codec, GF_FALSE);
304 				e = gf_bifs_enc_qp_set(codec, list->node);
305 				if (e) return e;
306 				qp_on = GF_TRUE;
307 				if (qp_local) qp_local = 2;
308 			}
309 			list = list->next;
310 		}
311 
312 		if (e) return e;
313 
314 		if (qp_on && qp_local) {
315 			if (qp_local == 2) qp_local -= 1;
316 			else {
317 				gf_bifs_enc_qp_remove(codec, initial_qp);
318 				qp_local = qp_on = GF_FALSE;
319 			}
320 		}
321 	}
322 
323 	if (use_list) GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL);
324 	if (qp_on) gf_bifs_enc_qp_remove(codec, initial_qp);
325 	/*for QP14*/
326 	gf_bifs_enc_qp14_set_length(codec, nbF);
327 	return GF_OK;
328 }
329 
330 
gf_bifs_enc_field(GF_BifsEncoder * codec,GF_BitStream * bs,GF_Node * node,GF_FieldInfo * field)331 GF_Err gf_bifs_enc_field(GF_BifsEncoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field)
332 {
333 	assert(node);
334 	if (field->fieldType == GF_SG_VRML_UNKNOWN)
335 		return GF_NON_COMPLIANT_BITSTREAM;
336 
337 	if (gf_sg_vrml_is_sf_field(field->fieldType)) {
338 		return gf_bifs_enc_sf_field(codec, bs, node, field);
339 	}
340 
341 	/*TO DO : PMF support*/
342 
343 	if (codec->info->config.UsePredictiveMFField) {
344 		GF_BIFS_WRITE_INT(codec, bs, 0, 1, "usePredictive", NULL);
345 	}
346 	return gf_bifs_enc_mf_field(codec, bs, node, field);
347 }
348 
349 /*we assume a node field is not ISed several times (that's stated as "undefined behaviour" in VRML*/
gf_bifs_enc_is_field_ised(GF_BifsEncoder * codec,GF_Node * node,u32 fieldIndex)350 GF_Route *gf_bifs_enc_is_field_ised(GF_BifsEncoder *codec, GF_Node *node, u32 fieldIndex)
351 {
352 	GF_Route *r;
353 	u32 i;
354 	if (!codec->encoding_proto) return NULL;
355 
356 	if (node->sgprivate->interact && node->sgprivate->interact->routes) {
357 		i=0;
358 		while ((r = (GF_Route*)gf_list_enum(node->sgprivate->interact->routes, &i))) {
359 			if (!r->IS_route) continue;
360 			if ((r->ToNode == node) && (r->ToField.fieldIndex==fieldIndex)) return r;
361 			else if ((r->FromNode == node) && (r->FromField.fieldIndex==fieldIndex)) return r;
362 		}
363 	}
364 
365 	i=0;
366 	while ((r = (GF_Route*)gf_list_enum(codec->encoding_proto->sub_graph->Routes, &i))) {
367 		if (!r->IS_route) continue;
368 		if ((r->ToNode == node) && (r->ToField.fieldIndex==fieldIndex)) return r;
369 		else if ((r->FromNode == node) && (r->FromField.fieldIndex==fieldIndex)) return r;
370 	}
371 	return NULL;
372 }
373 
374 /**/
EncNodeFields(GF_BifsEncoder * codec,GF_BitStream * bs,GF_Node * node)375 GF_Err EncNodeFields(GF_BifsEncoder * codec, GF_BitStream *bs, GF_Node *node)
376 {
377 	u8 mode;
378 	GF_Route *isedField;
379 	GF_Node *clone;
380 	GF_Err e;
381 	s32 *enc_fields;
382 	u32 numBitsALL, numBitsDEF, allInd, count, i, nbBitsProto, nbFinal;
383 	Bool use_list, nodeIsFDP = GF_FALSE;
384 	GF_FieldInfo field, clone_field;
385 
386 	e = GF_OK;
387 
388 	if (codec->encoding_proto) {
389 		mode = GF_SG_FIELD_CODING_ALL;
390 		nbBitsProto = gf_get_bit_size(gf_sg_proto_get_field_count(codec->encoding_proto) - 1);
391 		numBitsALL = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_ALL) - 1);
392 	} else {
393 		mode = GF_SG_FIELD_CODING_DEF;
394 		nbBitsProto = 0;
395 		numBitsALL = 0;
396 	}
397 	count = gf_node_get_num_fields_in_mode(node, mode);
398 	if (node->sgprivate->tag==TAG_MPEG4_Script) count = 3;
399 
400 	if (!count) {
401 		GF_BIFS_WRITE_INT(codec, bs, 0, 1, "isMask", NULL);
402 		GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL);
403 		return GF_OK;
404 	}
405 
406 	if (node->sgprivate->tag == TAG_ProtoNode) {
407 		clone = gf_sg_proto_create_instance(node->sgprivate->scenegraph, ((GF_ProtoInstance *)node)->proto_interface);
408 	} else {
409 		clone = gf_node_new(node->sgprivate->scenegraph, node->sgprivate->tag);
410 	}
411 	if (clone) gf_node_register(clone, NULL);
412 
413 	numBitsDEF = gf_get_bit_size(gf_node_get_num_fields_in_mode(node, GF_SG_FIELD_CODING_DEF) - 1);
414 
415 	enc_fields = (s32*)gf_malloc(sizeof(s32) * count);
416 	nbFinal = 0;
417 	for (i=0; i<count; i++) {
418 		enc_fields[i] = -1;
419 		/*get field in ALL mode*/
420 		if (mode == GF_SG_FIELD_CODING_ALL) {
421 			allInd = i;
422 		} else {
423 			gf_bifs_get_field_index(node, i, GF_SG_FIELD_CODING_DEF, &allInd);
424 		}
425 
426 		/*encode proto code*/
427 		if (codec->encoding_proto) {
428 			isedField = gf_bifs_enc_is_field_ised(codec, node, allInd);
429 			if (isedField) {
430 				enc_fields[i] = allInd;
431 				nbFinal ++;
432 				continue;
433 			}
434 		}
435 		/*common case*/
436 		gf_node_get_field(node, allInd, &field);
437 		/*if event don't encode (happens when encoding protos)*/
438 		if ((field.eventType == GF_SG_EVENT_IN) || (field.eventType == GF_SG_EVENT_OUT)) continue;
439 		/*if field is default skip*/
440 		switch (field.fieldType) {
441 		case GF_SG_VRML_SFNODE:
442 			if (* (GF_Node **) field.far_ptr) {
443 				enc_fields[i] = allInd;
444 				nbFinal++;
445 			}
446 			break;
447 		case GF_SG_VRML_MFNODE:
448 			if (* (GF_ChildNodeItem **) field.far_ptr) {
449 				enc_fields[i] = allInd;
450 				nbFinal++;
451 			}
452 			break;
453 		case GF_SG_VRML_SFCOMMANDBUFFER:
454 		{
455 			SFCommandBuffer *cb = (SFCommandBuffer *)field.far_ptr;
456 			if (gf_list_count(cb->commandList)) {
457 				enc_fields[i] = allInd;
458 				nbFinal++;
459 			}
460 		}
461 		break;
462 		case GF_SG_VRML_MFSCRIPT:
463 			enc_fields[i] = allInd;
464 			nbFinal++;
465 			break;
466 		default:
467 			gf_node_get_field(clone, allInd, &clone_field);
468 			if (!gf_sg_vrml_field_equal(clone_field.far_ptr, field.far_ptr, field.fieldType)) {
469 				enc_fields[i] = allInd;
470 				nbFinal++;
471 			}
472 			break;
473 		}
474 	}
475 	if (clone) gf_node_unregister(clone, NULL);
476 
477 	use_list = GF_TRUE;
478 	/* patch for FDP node : */
479 	/* cannot use default field sorting due to spec "mistake", so use list to imply inversion between field 2 and field 3 of FDP*/
480 	if (node->sgprivate->tag == TAG_MPEG4_FDP) {
481 		s32 s4SwapValue = enc_fields[2];
482 		enc_fields[2] = enc_fields[3];
483 		enc_fields[3] = s4SwapValue;
484 		nodeIsFDP = GF_TRUE;
485 		use_list = GF_TRUE;
486 	}
487 	/*number of bits in mask node is count*1, in list node is 1+nbFinal*(1+numBitsDEF) */
488 	else if (count < 1+nbFinal*(1+numBitsDEF))
489 		use_list = GF_FALSE;
490 
491 	GF_BIFS_WRITE_INT(codec, bs, use_list ? 0 : 1, 1, "isMask", NULL);
492 
493 	for (i=0; i<count; i++) {
494 		if (enc_fields[i] == -1) {
495 			if (!use_list) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "Mask", NULL);
496 			continue;
497 		}
498 		allInd = (u32) enc_fields[i];
499 
500 		/*encode proto code*/
501 		if (codec->encoding_proto) {
502 			isedField = gf_bifs_enc_is_field_ised(codec, node, allInd);
503 			if (isedField) {
504 				if (use_list) {
505 					GF_BIFS_WRITE_INT(codec, bs, 0, 1, "end", NULL);
506 				} else {
507 					GF_BIFS_WRITE_INT(codec, bs, 1, 1, "Mask", NULL);
508 				}
509 				GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isedField", NULL);
510 				if (use_list) GF_BIFS_WRITE_INT(codec, bs, allInd, numBitsALL, "nodeField", NULL);
511 
512 				if (isedField->ToNode == node) {
513 					GF_BIFS_WRITE_INT(codec, bs, isedField->FromField.fieldIndex, nbBitsProto, "protoField", NULL);
514 				} else {
515 					GF_BIFS_WRITE_INT(codec, bs, isedField->ToField.fieldIndex, nbBitsProto, "protoField", NULL);
516 				}
517 				continue;
518 			}
519 		}
520 		/*common case*/
521 		gf_node_get_field(node, allInd, &field);
522 		if (use_list) {
523 			/*not end flag*/
524 			GF_BIFS_WRITE_INT(codec, bs, 0, 1, "end", NULL);
525 		} else {
526 			/*mask flag*/
527 			GF_BIFS_WRITE_INT(codec, bs, 1, 1, "Mask", NULL);
528 		}
529 		/*not ISed field*/
530 		if (codec->encoding_proto) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "isedField", NULL);
531 		if (use_list) {
532 			if (codec->encoding_proto || nodeIsFDP) {
533 				u32 ind=0;
534 				/*for proto, we're in ALL mode and we need DEF mode*/
535 				/*for FDP, encoding requires to get def id from all id as fields 2 and 3 are reversed*/
536 				gf_bifs_field_index_by_mode(node, allInd, GF_SG_FIELD_CODING_DEF, &ind);
537 				GF_BIFS_WRITE_INT(codec, bs, ind, numBitsDEF, "field", (char*)field.name);
538 			} else {
539 				GF_BIFS_WRITE_INT(codec, bs, i, numBitsDEF, "field", (char*)field.name);
540 			}
541 		}
542 		e = gf_bifs_enc_field(codec, bs, node, &field);
543 		if (e) goto exit;
544 	}
545 	/*end flag*/
546 	if (use_list) GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL);
547 exit:
548 	gf_free(enc_fields);
549 	return e;
550 }
551 
BE_NodeIsUSE(GF_BifsEncoder * codec,GF_Node * node)552 Bool BE_NodeIsUSE(GF_BifsEncoder * codec, GF_Node *node)
553 {
554 	u32 i, count;
555 	if (!node || !gf_node_get_id(node) ) return GF_FALSE;
556 	count = gf_list_count(codec->encoded_nodes);
557 	for (i=0; i<count; i++) {
558 		if (gf_list_get(codec->encoded_nodes, i) == node) return GF_TRUE;
559 	}
560 	gf_list_add(codec->encoded_nodes, node);
561 	return GF_FALSE;
562 }
563 
gf_bifs_enc_node(GF_BifsEncoder * codec,GF_Node * node,u32 NDT_Tag,GF_BitStream * bs,GF_Node * parent_node)564 GF_Err gf_bifs_enc_node(GF_BifsEncoder * codec, GF_Node *node, u32 NDT_Tag, GF_BitStream *bs, GF_Node *parent_node)
565 {
566 	u32 NDTBits, node_type, node_tag, BVersion, node_id;
567 	const char *node_name;
568 	Bool flag, reset_qp14;
569 	GF_Err e;
570 
571 	assert(codec->info);
572 	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[BIFS] Encode node %s\n", gf_node_get_class_name(node) ));
573 
574 	/*NULL node is a USE of maxID*/
575 	if (!node) {
576 		GF_BIFS_WRITE_INT(codec, bs, 1, 1, "USE", NULL);
577 		GF_BIFS_WRITE_INT(codec, bs, (1<<codec->info->config.NodeIDBits) - 1 , codec->info->config.NodeIDBits, "NodeID", "NULL");
578 		return GF_OK;
579 	}
580 
581 	flag = BE_NodeIsUSE(codec, node);
582 	GF_BIFS_WRITE_INT(codec, bs, flag ? 1 : 0, 1, "USE", (char*)gf_node_get_class_name(node));
583 
584 	if (flag) {
585 		GF_Node *new_node;
586 		gf_bs_write_int(bs, gf_node_get_id(node) - 1, codec->info->config.NodeIDBits);
587 		new_node = gf_bifs_enc_find_node(codec, gf_node_get_id(node) );
588 		if (!new_node)
589 			return codec->LastError = GF_SG_UNKNOWN_NODE;
590 
591 		/*restore QP14 length*/
592 		switch (gf_node_get_tag(new_node)) {
593 		case TAG_MPEG4_Coordinate:
594 		{
595 			u32 nbCoord = ((M_Coordinate *)new_node)->point.count;
596 			gf_bifs_enc_qp14_enter(codec, GF_TRUE);
597 			gf_bifs_enc_qp14_set_length(codec, nbCoord);
598 			gf_bifs_enc_qp14_enter(codec, GF_FALSE);
599 		}
600 		break;
601 		case TAG_MPEG4_Coordinate2D:
602 		{
603 			u32 nbCoord = ((M_Coordinate2D *)new_node)->point.count;
604 			gf_bifs_enc_qp14_enter(codec, GF_TRUE);
605 			gf_bifs_enc_qp14_set_length(codec, nbCoord);
606 			gf_bifs_enc_qp14_enter(codec, GF_FALSE);
607 		}
608 		break;
609 		}
610 		return GF_OK;
611 	}
612 
613 	BVersion = GF_BIFS_V1;
614 	node_tag = node->sgprivate->tag;
615 	while (1) {
616 		node_type = gf_bifs_get_node_type(NDT_Tag, node_tag, BVersion);
617 		NDTBits = gf_bifs_get_ndt_bits(NDT_Tag, BVersion);
618 		if (BVersion==2 && (node_tag==TAG_ProtoNode)) node_type = 1;
619 		GF_BIFS_WRITE_INT(codec, bs, node_type, NDTBits, "ndt", NULL);
620 		if (node_type) break;
621 
622 		BVersion += 1;
623 		if (BVersion > GF_BIFS_NUM_VERSION) {
624 			if (parent_node) {
625 				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[BIFS] Cannot encode node %s as a child of %s\n", gf_node_get_class_name(node), gf_node_get_class_name(parent_node) ));
626 			} else {
627 				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[BIFS] Cannot encode node %s in the SFWorldNode context\n", gf_node_get_class_name(node) ));
628 			}
629 			return codec->LastError = GF_BIFS_UNKNOWN_VERSION;
630 		}
631 	}
632 	if (BVersion==2 && node_type==1) {
633 		GF_Proto *proto = ((GF_ProtoInstance *)node)->proto_interface;
634 		GF_BIFS_WRITE_INT(codec, bs, proto->ID, codec->info->config.ProtoIDBits, "protoID", NULL);
635 	}
636 
637 	/*special handling of 3D mesh*/
638 
639 	/*DEF'd node*/
640 	node_name = gf_node_get_name_and_id(node, &node_id);
641 	GF_BIFS_WRITE_INT(codec, bs, node_id ? 1 : 0, 1, "DEF", NULL);
642 	if (node_id) {
643 		GF_BIFS_WRITE_INT(codec, bs, node_id - 1, codec->info->config.NodeIDBits, "NodeID", NULL);
644 		if (codec->UseName) gf_bifs_enc_name(codec, bs, (char*) node_name );
645 	}
646 
647 	/*no updates of time fields for now - NEEDED FOR A LIVE ENCODER*/
648 
649 	/*if coords were not stored for QP14 before coding this node, reset QP14 it when leaving*/
650 	reset_qp14 = !codec->coord_stored;
651 
652 	/*QP14 case*/
653 	switch (node_tag) {
654 	case TAG_MPEG4_Coordinate:
655 	case TAG_MPEG4_Coordinate2D:
656 		gf_bifs_enc_qp14_enter(codec, GF_TRUE);
657 	}
658 
659 	e = EncNodeFields(codec, bs, node);
660 	if (e) return e;
661 
662 	if (codec->coord_stored && reset_qp14)
663 		gf_bifs_enc_qp14_reset(codec);
664 
665 	switch (node_tag) {
666 	case TAG_MPEG4_Coordinate:
667 	case TAG_MPEG4_Coordinate2D:
668 		gf_bifs_enc_qp14_enter(codec, GF_FALSE);
669 		break;
670 	}
671 	return GF_OK;
672 }
673 
674 
675 #endif /*GPAC_DISABLE_BIFS_ENC*/
676