/src/gpac/src/bifs/unquantize.c
Line | Count | Source |
1 | | /* |
2 | | * GPAC - Multimedia Framework C SDK |
3 | | * |
4 | | * Authors: Jean Le Feuvre |
5 | | * Copyright (c) Telecom ParisTech 2000-2023 |
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 | | #include "quant.h" |
27 | | |
28 | | #ifndef GPAC_DISABLE_BIFS |
29 | | |
30 | | #include <math.h> |
31 | | |
32 | | u32 gf_bifs_dec_qp14_get_bits(GF_BifsDecoder *codec) |
33 | 0 | { |
34 | 0 | if (!codec->ActiveQP || !codec->coord_stored) return 0; |
35 | 0 | return (u32) ceil(log1p(codec->NumCoord) / log(2) ); |
36 | 0 | } |
37 | | |
38 | | void gf_bifs_dec_qp14_enter(GF_BifsDecoder * codec, Bool Enter) |
39 | 0 | { |
40 | 0 | if (!codec->ActiveQP) return; |
41 | 0 | if (Enter) codec->storing_coord = GF_TRUE; |
42 | 0 | else { |
43 | 0 | if (codec->storing_coord) codec->coord_stored = GF_TRUE; |
44 | 0 | codec->storing_coord = GF_FALSE; |
45 | 0 | } |
46 | 0 | } |
47 | | |
48 | | void gf_bifs_dec_qp14_reset(GF_BifsDecoder * codec) |
49 | 0 | { |
50 | 0 | codec->coord_stored = GF_FALSE; |
51 | 0 | codec->storing_coord = GF_FALSE; |
52 | 0 | codec->NumCoord = 0; |
53 | 0 | } |
54 | | |
55 | | void gf_bifs_dec_qp14_set_length(GF_BifsDecoder * codec, u32 NbElements) |
56 | 0 | { |
57 | 0 | if (!codec->ActiveQP || !codec->storing_coord || codec->coord_stored) return; |
58 | 0 | codec->NumCoord = NbElements; |
59 | 0 | } |
60 | | |
61 | | GF_Err gf_bifs_dec_qp_set(GF_BifsDecoder *codec, GF_Node *qp) |
62 | 0 | { |
63 | 0 | gf_assert(gf_node_get_tag(qp) == TAG_MPEG4_QuantizationParameter); |
64 | | |
65 | | /*if we have an active QP, push it into the stack*/ |
66 | 0 | if (codec->ActiveQP && ((GF_Node*)codec->ActiveQP != codec->scenegraph->global_qp) ) |
67 | 0 | gf_list_insert(codec->QPs, codec->ActiveQP, 0); |
68 | |
|
69 | 0 | codec->ActiveQP = (M_QuantizationParameter *)qp; |
70 | 0 | return GF_OK; |
71 | 0 | } |
72 | | |
73 | | GF_Err gf_bifs_dec_qp_remove(GF_BifsDecoder *codec, Bool ActivatePrev) |
74 | 0 | { |
75 | 0 | if (!codec->force_keep_qp && codec->ActiveQP && ((GF_Node*)codec->ActiveQP != codec->scenegraph->global_qp) ) { |
76 | 0 | gf_node_unregister((GF_Node *) codec->ActiveQP, NULL); |
77 | 0 | } |
78 | 0 | codec->ActiveQP = NULL; |
79 | 0 | if (!ActivatePrev) return GF_OK; |
80 | | |
81 | 0 | if (gf_list_count(codec->QPs)) { |
82 | 0 | codec->ActiveQP = (M_QuantizationParameter*)gf_list_get(codec->QPs, 0); |
83 | 0 | gf_list_rem(codec->QPs, 0); |
84 | 0 | } else if (codec->scenegraph->global_qp) { |
85 | 0 | codec->ActiveQP = (M_QuantizationParameter *)codec->scenegraph->global_qp; |
86 | 0 | } |
87 | 0 | return GF_OK; |
88 | 0 | } |
89 | | |
90 | | //parses efficient float |
91 | | Fixed gf_bifs_dec_mantissa_float(GF_BifsDecoder *codec, GF_BitStream *bs) |
92 | 0 | { |
93 | 0 | u32 mantLength, expLength, mantSign, mantissa; |
94 | 0 | unsigned char exp; |
95 | |
|
96 | 0 | union { |
97 | 0 | Float f; |
98 | 0 | long l; |
99 | 0 | } ft_value; |
100 | |
|
101 | 0 | mantLength = gf_bs_read_int(bs, 4); |
102 | 0 | if (!mantLength) return 0; |
103 | | |
104 | 0 | expLength = gf_bs_read_int(bs, 3); |
105 | 0 | mantSign = gf_bs_read_int(bs, 1); |
106 | 0 | mantissa = gf_bs_read_int(bs, mantLength - 1); |
107 | |
|
108 | 0 | exp = 127; |
109 | 0 | if (expLength) { |
110 | 0 | u32 expSign = gf_bs_read_int(bs, 1); |
111 | 0 | u32 exponent = gf_bs_read_int(bs, expLength-1); |
112 | 0 | exp += (1-2*expSign)*( (1 << (expLength-1) ) + exponent); |
113 | 0 | } |
114 | |
|
115 | 0 | ft_value.l = mantSign << 31; |
116 | 0 | ft_value.l |= (exp & 0xff) << 23; |
117 | 0 | ft_value.l |= mantissa << 9; |
118 | 0 | return FLT2FIX(ft_value.f); |
119 | 0 | } |
120 | | |
121 | | //check if the quant type is on in the QP, and if so retrieves NbBits and Min Max |
122 | | //specified for the field |
123 | | Bool Q_IsTypeOn(M_QuantizationParameter *qp, u32 q_type, u32 *NbBits, SFVec3f *b_min, SFVec3f *b_max) |
124 | 0 | { |
125 | 0 | switch (q_type) { |
126 | 0 | case QC_3DPOS: |
127 | 0 | if (!qp->position3DQuant) return GF_FALSE; |
128 | 0 | *NbBits = qp->position3DNbBits; |
129 | 0 | b_min->x = MAX(b_min->x, qp->position3DMin.x); |
130 | 0 | b_min->y = MAX(b_min->y, qp->position3DMin.y); |
131 | 0 | b_min->z = MAX(b_min->z, qp->position3DMin.z); |
132 | 0 | b_max->x = MIN(b_max->x, qp->position3DMax.x); |
133 | 0 | b_max->y = MIN(b_max->y, qp->position3DMax.y); |
134 | 0 | b_max->z = MIN(b_max->z, qp->position3DMax.z); |
135 | 0 | return GF_TRUE; |
136 | 0 | case QC_2DPOS: |
137 | 0 | if (!qp->position2DQuant) return GF_FALSE; |
138 | 0 | *NbBits = qp->position2DNbBits; |
139 | 0 | b_min->x = MAX(b_min->x, qp->position2DMin.x); |
140 | 0 | b_min->y = MAX(b_min->y, qp->position2DMin.y); |
141 | 0 | b_max->x = MIN(b_max->x, qp->position2DMax.x); |
142 | 0 | b_max->y = MIN(b_max->y, qp->position2DMax.y); |
143 | 0 | return GF_TRUE; |
144 | 0 | case QC_ORDER: |
145 | 0 | if (!qp->drawOrderQuant) return GF_FALSE; |
146 | 0 | *NbBits = qp->drawOrderNbBits; |
147 | 0 | b_min->x = MAX(b_min->x, qp->drawOrderMin); |
148 | 0 | b_max->x = MIN(b_max->x, qp->drawOrderMax); |
149 | 0 | return GF_TRUE; |
150 | 0 | case QC_COLOR: |
151 | 0 | if (!qp->colorQuant) return GF_FALSE; |
152 | 0 | *NbBits = qp->colorNbBits; |
153 | 0 | b_min->x = b_min->y = b_min->z = MAX(b_min->x, qp->colorMin); |
154 | 0 | b_max->x = b_max->y = b_max->z = MIN(b_max->x, qp->colorMax); |
155 | 0 | return GF_TRUE; |
156 | 0 | case QC_TEXTURE_COORD: |
157 | 0 | if (!qp->textureCoordinateQuant) return GF_FALSE; |
158 | 0 | *NbBits = qp->textureCoordinateNbBits; |
159 | 0 | b_min->x = b_min->y = b_min->z = MAX(b_min->x, qp->textureCoordinateMin); |
160 | 0 | b_max->x = b_max->y = b_max->z = MIN(b_max->x, qp->textureCoordinateMax); |
161 | 0 | return GF_TRUE; |
162 | 0 | case QC_ANGLE: |
163 | 0 | if (!qp->angleQuant) return GF_FALSE; |
164 | 0 | *NbBits = qp->angleNbBits; |
165 | 0 | b_min->x = b_min->y = b_min->z = MAX(b_min->x, qp->angleMin); |
166 | 0 | b_max->x = b_max->y = b_max->z = MIN(b_max->x, qp->angleMax); |
167 | 0 | return GF_TRUE; |
168 | 0 | case QC_SCALE: |
169 | 0 | if (!qp->scaleQuant) return GF_FALSE; |
170 | 0 | *NbBits = qp->scaleNbBits; |
171 | 0 | b_min->x = b_min->y = b_min->z = MAX(b_min->x, qp->scaleMin); |
172 | 0 | b_max->x = b_max->y = b_max->z = MIN(b_max->x, qp->scaleMax); |
173 | 0 | return GF_TRUE; |
174 | 0 | case QC_INTERPOL_KEYS: |
175 | 0 | if (!qp->keyQuant) return GF_FALSE; |
176 | 0 | *NbBits = qp->keyNbBits; |
177 | 0 | b_min->x = MAX(b_min->x, qp->keyMin); |
178 | 0 | b_min->y = MAX(b_min->y, qp->keyMin); |
179 | 0 | b_min->z = MAX(b_min->z, qp->keyMin); |
180 | 0 | b_max->x = MIN(b_max->x, qp->keyMax); |
181 | 0 | b_max->y = MIN(b_max->y, qp->keyMax); |
182 | 0 | b_max->z = MIN(b_max->z, qp->keyMax); |
183 | 0 | return GF_TRUE; |
184 | 0 | case QC_NORMALS: |
185 | 0 | if (!qp->normalQuant) return GF_FALSE; |
186 | 0 | *NbBits = qp->normalNbBits; |
187 | 0 | b_min->x = b_min->y = b_min->z = 0; |
188 | 0 | b_max->x = b_max->y = b_max->z = FIX_ONE; |
189 | 0 | return GF_TRUE; |
190 | 0 | case QC_ROTATION: |
191 | 0 | if (!qp->normalQuant) return GF_FALSE; |
192 | 0 | *NbBits = qp->normalNbBits; |
193 | 0 | b_min->x = b_min->y = b_min->z = 0; |
194 | 0 | b_max->x = b_max->y = b_max->z = FIX_ONE; |
195 | 0 | return GF_TRUE; |
196 | 0 | case QC_SIZE_3D: |
197 | 0 | if (!qp->sizeQuant) return GF_FALSE; |
198 | 0 | *NbBits = qp->sizeNbBits; |
199 | 0 | b_min->x = b_min->y = b_min->z = MAX(b_min->x, qp->sizeMin); |
200 | 0 | b_max->x = b_max->y = b_max->z = MIN(b_max->x, qp->sizeMax); |
201 | 0 | return GF_TRUE; |
202 | 0 | case QC_SIZE_2D: |
203 | 0 | if (!qp->sizeQuant) return GF_FALSE; |
204 | 0 | *NbBits = qp->sizeNbBits; |
205 | 0 | b_min->x = b_min->y = b_min->z = MAX(b_min->x, qp->sizeMin); |
206 | 0 | b_max->x = b_max->y = b_max->z = MIN(b_max->x, qp->sizeMax); |
207 | 0 | return GF_TRUE; |
208 | | |
209 | | //cf specs, from here ALWAYS ON |
210 | 0 | case QC_LINEAR_SCALAR: |
211 | | //nbBits is the one from the FCT - DO NOT CHANGE IT |
212 | 0 | return GF_TRUE; |
213 | 0 | case QC_COORD_INDEX: |
214 | | //nbBits has to be recomputed on the fly |
215 | 0 | return GF_TRUE; |
216 | 0 | case QC_RESERVED: |
217 | 0 | *NbBits = 0; |
218 | 0 | return GF_TRUE; |
219 | 0 | default: |
220 | 0 | return GF_FALSE; |
221 | 0 | } |
222 | 0 | } |
223 | | |
224 | | |
225 | | //Linear inverse Quantization for floats |
226 | | Fixed Q_InverseQuantize(Fixed Min, Fixed Max, u32 NbBits, u32 value) |
227 | 0 | { |
228 | 0 | if (!value) return Min; |
229 | 0 | if (NbBits>=sizeof(value)*8) return Max; |
230 | 0 | if (value == (u32) ((1 << NbBits) - 1) ) return Max; |
231 | 0 | return Min + gf_muldiv(Max - Min, INT2FIX(value), INT2FIX( (1 << NbBits) - 1) ); |
232 | 0 | } |
233 | | |
234 | | |
235 | | GF_Err Q_DecFloat(GF_BifsDecoder *codec, GF_BitStream *bs, u32 FieldType, SFVec3f BMin, SFVec3f BMax, u32 NbBits, void *field_ptr) |
236 | 0 | { |
237 | 0 | switch (FieldType) { |
238 | 0 | case GF_SG_VRML_SFINT32: |
239 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
240 | 0 | case GF_SG_VRML_SFFLOAT: |
241 | 0 | *((SFFloat *)field_ptr) = Q_InverseQuantize(BMin.x, BMax.x, NbBits, gf_bs_read_int(bs, NbBits)); |
242 | 0 | return GF_OK; |
243 | 0 | case GF_SG_VRML_SFVEC2F: |
244 | 0 | ((SFVec2f *)field_ptr)->x = Q_InverseQuantize(BMin.x, BMax.x, NbBits, gf_bs_read_int(bs, NbBits)); |
245 | 0 | ((SFVec2f *)field_ptr)->y = Q_InverseQuantize(BMin.y, BMax.y, NbBits, gf_bs_read_int(bs, NbBits)); |
246 | 0 | return GF_OK; |
247 | 0 | case GF_SG_VRML_SFVEC3F: |
248 | 0 | ((SFVec3f *)field_ptr)->x = Q_InverseQuantize(BMin.x, BMax.x, NbBits, gf_bs_read_int(bs, NbBits)); |
249 | 0 | ((SFVec3f *)field_ptr)->y = Q_InverseQuantize(BMin.y, BMax.y, NbBits, gf_bs_read_int(bs, NbBits)); |
250 | 0 | ((SFVec3f *)field_ptr)->z = Q_InverseQuantize(BMin.z, BMax.z, NbBits, gf_bs_read_int(bs, NbBits)); |
251 | 0 | return GF_OK; |
252 | 0 | case GF_SG_VRML_SFCOLOR: |
253 | 0 | ((SFColor *)field_ptr)->red = Q_InverseQuantize(BMin.x, BMax.x, NbBits, gf_bs_read_int(bs, NbBits)); |
254 | 0 | ((SFColor *)field_ptr)->green = Q_InverseQuantize(BMin.y, BMax.y, NbBits, gf_bs_read_int(bs, NbBits)); |
255 | 0 | ((SFColor *)field_ptr)->blue = Q_InverseQuantize(BMin.z, BMax.z, NbBits, gf_bs_read_int(bs, NbBits)); |
256 | 0 | return GF_OK; |
257 | | |
258 | 0 | case GF_SG_VRML_SFROTATION: |
259 | | //forbidden in this Q mode |
260 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
261 | 0 | } |
262 | 0 | return GF_OK; |
263 | 0 | } |
264 | | |
265 | | //int in quant are either Linear Scalar fields or CoordIndex |
266 | | //the quant is just a bitshifting into [0, 2^NbBits-1] |
267 | | //so IntMin + ReadBit(NbBits) = value |
268 | | GF_Err Q_DecInt(GF_BifsDecoder *codec, GF_BitStream *bs, u32 QType, SFInt32 b_min, u32 NbBits, void *field_ptr) |
269 | 0 | { |
270 | 0 | switch (QType) { |
271 | 0 | case QC_LINEAR_SCALAR: |
272 | 0 | case QC_COORD_INDEX: |
273 | 0 | *((SFInt32 *)field_ptr) = gf_bs_read_int(bs, NbBits) + b_min; |
274 | 0 | return GF_OK; |
275 | 0 | default: |
276 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
277 | 0 | } |
278 | 0 | } |
279 | | |
280 | | //SFRotation and SFVec3f are quantized as normalized vectors ,mapped on a cube |
281 | | //in the UnitSphere (R=1.0) |
282 | | GF_Err Q_DecCoordOnUnitSphere(GF_BifsDecoder *codec, GF_BitStream *bs, u32 NbBits, u32 NbComp, Fixed *m_ft) |
283 | 0 | { |
284 | 0 | u32 i, orient, sign; |
285 | 0 | s32 value; |
286 | 0 | Fixed tang[4], delta; |
287 | 0 | s32 dir; |
288 | 0 | if (!NbBits || NbBits>32) return GF_NON_COMPLIANT_BITSTREAM; |
289 | 0 | if (NbComp != 2 && NbComp != 3) return GF_BAD_PARAM; |
290 | | |
291 | | //only 2 or 3 comp in the quantized version |
292 | 0 | dir = 1; |
293 | 0 | if(NbComp == 2) dir -= 2 * gf_bs_read_int(bs, 1); |
294 | |
|
295 | 0 | orient = gf_bs_read_int(bs, 2); |
296 | 0 | if ((orient==3) && (NbComp==2)) return GF_NON_COMPLIANT_BITSTREAM; |
297 | | |
298 | 0 | for(i=0; i<NbComp; i++) { |
299 | 0 | value = gf_bs_read_int(bs, NbBits) - (1 << (NbBits-1) ); |
300 | 0 | sign = (value >= 0) ? 1 : -1; |
301 | 0 | m_ft[i] = sign * Q_InverseQuantize(0, 1, NbBits-1, sign*value); |
302 | 0 | } |
303 | 0 | delta = 1; |
304 | 0 | for (i=0; i<NbComp; i++) { |
305 | 0 | tang[i] = gf_tan(gf_mulfix(GF_PI/4, m_ft[i]) ); |
306 | 0 | delta += gf_mulfix(tang[i], tang[i]); |
307 | 0 | } |
308 | 0 | delta = gf_divfix(INT2FIX(dir), gf_sqrt(delta) ); |
309 | 0 | m_ft[orient] = delta; |
310 | |
|
311 | 0 | for (i=0; i<NbComp; i++) { |
312 | 0 | m_ft[ (orient + i+1) % (NbComp+1) ] = gf_mulfix(tang[i], delta); |
313 | 0 | } |
314 | 0 | return GF_OK; |
315 | 0 | } |
316 | | |
317 | | //parses a rotation |
318 | | GF_Err Q_DecRotation(GF_BifsDecoder *codec, GF_BitStream *bs, u32 NbBits, void *field_ptr) |
319 | 0 | { |
320 | 0 | u32 i; |
321 | 0 | Fixed q, sin2, comp[4]; |
322 | 0 | GF_Err e; |
323 | |
|
324 | 0 | e = Q_DecCoordOnUnitSphere(codec, bs, NbBits, 3, comp); |
325 | 0 | if (e) return e; |
326 | | |
327 | 0 | q = 2 * gf_acos(comp[0]); |
328 | 0 | sin2 = gf_sin(q / 2); |
329 | |
|
330 | 0 | if (ABS(sin2) <= FIX_EPSILON) { |
331 | 0 | for (i=1; i<4; i++) comp[i] = 0; |
332 | 0 | comp[3] = FIX_ONE; |
333 | 0 | } else { |
334 | 0 | for (i=1; i<4; i++) comp[i] = gf_divfix(comp[i], sin2); |
335 | 0 | } |
336 | 0 | ((SFRotation *)field_ptr)->x = comp[1]; |
337 | 0 | ((SFRotation *)field_ptr)->y = comp[2]; |
338 | 0 | ((SFRotation *)field_ptr)->z = comp[3]; |
339 | 0 | ((SFRotation *)field_ptr)->q = q; |
340 | 0 | return GF_OK; |
341 | 0 | } |
342 | | |
343 | | //parses a Normal vec |
344 | | GF_Err Q_DecNormal(GF_BifsDecoder *codec, GF_BitStream *bs, u32 NbBits, void *field_ptr) |
345 | 0 | { |
346 | 0 | Fixed comp[4]; |
347 | 0 | SFVec3f v; |
348 | 0 | GF_Err e; |
349 | 0 | e = Q_DecCoordOnUnitSphere(codec, bs, NbBits, 2, comp); |
350 | 0 | if (e) return e; |
351 | 0 | v.x = comp[0]; |
352 | 0 | v.y = comp[1]; |
353 | 0 | v.z = comp[2]; |
354 | 0 | gf_vec_norm(&v); |
355 | 0 | *((SFVec3f *)field_ptr) = v; |
356 | 0 | return GF_OK; |
357 | 0 | } |
358 | | |
359 | | GF_Err gf_bifs_dec_unquant_field(GF_BifsDecoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field) |
360 | 0 | { |
361 | 0 | Bool HasQ; |
362 | 0 | u8 QType, AType; |
363 | 0 | u32 NbBits; |
364 | 0 | Fixed b_min, b_max; |
365 | 0 | SFVec3f BMin, BMax; |
366 | 0 | GF_Err e; |
367 | | |
368 | | /*check QP*/ |
369 | 0 | if (!codec->ActiveQP) return GF_EOS; |
370 | | /*check FieldType*/ |
371 | 0 | switch (field->fieldType) { |
372 | 0 | case GF_SG_VRML_SFINT32: |
373 | 0 | case GF_SG_VRML_SFFLOAT: |
374 | 0 | case GF_SG_VRML_SFROTATION: |
375 | 0 | case GF_SG_VRML_SFVEC2F: |
376 | 0 | case GF_SG_VRML_SFVEC3F: |
377 | 0 | break; |
378 | 0 | case GF_SG_VRML_SFCOLOR: |
379 | 0 | break; |
380 | 0 | default: |
381 | 0 | return GF_EOS; |
382 | 0 | } |
383 | | |
384 | | /*check NDT*/ |
385 | 0 | HasQ = gf_bifs_get_aq_info(node, field->fieldIndex, &QType, &AType, &b_min, &b_max, &NbBits); |
386 | 0 | if (!HasQ || !QType) return GF_EOS; |
387 | | |
388 | | /*get NbBits for QP14 (QC_COORD_INDEX)*/ |
389 | 0 | if (QType == QC_COORD_INDEX) { |
390 | 0 | NbBits = gf_bifs_dec_qp14_get_bits(codec); |
391 | | /*QP14 is always on, not having NbBits set means the coord field is set after the index field, hence not decodable*/ |
392 | 0 | if (!NbBits) return GF_NON_COMPLIANT_BITSTREAM; |
393 | 0 | } |
394 | | |
395 | 0 | BMin.x = BMin.y = BMin.z = b_min; |
396 | 0 | BMax.x = BMax.y = BMax.z = b_max; |
397 | | |
398 | | /*check is the QP is on and retrieves the bounds*/ |
399 | 0 | if (!Q_IsTypeOn(codec->ActiveQP, QType, &NbBits, &BMin, &BMax)) return GF_EOS; |
400 | | |
401 | 0 | if (NbBits / 8 > gf_bs_available(bs)) |
402 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
403 | | |
404 | | /*ok the field is Quantized, dequantize*/ |
405 | 0 | switch (QType) { |
406 | | //these are all SFFloat quantized on n fields |
407 | 0 | case QC_3DPOS: |
408 | 0 | case QC_2DPOS: |
409 | 0 | case QC_ORDER: |
410 | 0 | case QC_COLOR: |
411 | 0 | case QC_TEXTURE_COORD: |
412 | 0 | case QC_ANGLE: |
413 | 0 | case QC_SCALE: |
414 | 0 | case QC_INTERPOL_KEYS: |
415 | 0 | case QC_SIZE_3D: |
416 | 0 | case QC_SIZE_2D: |
417 | 0 | e = Q_DecFloat(codec, bs, field->fieldType, BMin, BMax, NbBits, field->far_ptr); |
418 | 0 | break; |
419 | | //SFInt types |
420 | 0 | case QC_LINEAR_SCALAR: |
421 | 0 | case QC_COORD_INDEX: |
422 | 0 | e = Q_DecInt(codec, bs, QType, (SFInt32) b_min, NbBits, field->far_ptr); |
423 | 0 | break; |
424 | | //normalized fields (normals and vectors) |
425 | 0 | case QC_NORMALS: |
426 | | //normal quant is only for SFVec3F |
427 | 0 | if (field->fieldType != GF_SG_VRML_SFVEC3F) return GF_NON_COMPLIANT_BITSTREAM; |
428 | 0 | e = Q_DecNormal(codec, bs, NbBits, field->far_ptr); |
429 | 0 | break; |
430 | 0 | case QC_ROTATION: |
431 | | //normal quant is only for SFRotation |
432 | 0 | if (field->fieldType != GF_SG_VRML_SFROTATION) return GF_NON_COMPLIANT_BITSTREAM; |
433 | 0 | e = Q_DecRotation(codec, bs, NbBits, field->far_ptr); |
434 | 0 | break; |
435 | 0 | default: |
436 | 0 | return GF_BAD_PARAM; |
437 | 0 | } |
438 | | |
439 | 0 | if (e) return e; |
440 | 0 | return GF_OK; |
441 | 0 | } |
442 | | |
443 | | #endif /*GPAC_DISABLE_BIFS*/ |