/src/gpac/src/bifs/quantize.c
Line | Count | Source |
1 | | /* |
2 | | * GPAC - Multimedia Framework C SDK |
3 | | * |
4 | | * Authors: Jean Le Feuvre |
5 | | * Copyright (c) Telecom ParisTech 2000-2012 |
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 "math.h" |
27 | | #include "quant.h" |
28 | | |
29 | | #ifndef GPAC_DISABLE_BIFS_ENC |
30 | | |
31 | | GF_Err gf_bifs_enc_qp_set(GF_BifsEncoder *codec, GF_Node *qp) |
32 | 0 | { |
33 | 0 | if (gf_node_get_tag(qp) != TAG_MPEG4_QuantizationParameter) return GF_BAD_PARAM; |
34 | | |
35 | | /*if we have an active QP, push it into the stack*/ |
36 | 0 | if (codec->ActiveQP && ((GF_Node*)codec->ActiveQP != codec->scene_graph->global_qp) ) |
37 | 0 | gf_list_insert(codec->QPs, codec->ActiveQP, 0); |
38 | |
|
39 | 0 | codec->ActiveQP = (M_QuantizationParameter *)qp; |
40 | 0 | return GF_OK; |
41 | 0 | } |
42 | | |
43 | | GF_Err gf_bifs_enc_qp_remove(GF_BifsEncoder *codec, Bool ActivatePrev) |
44 | 0 | { |
45 | 0 | codec->ActiveQP = NULL; |
46 | 0 | if (!ActivatePrev) return GF_OK; |
47 | | |
48 | 0 | if (gf_list_count(codec->QPs)) { |
49 | 0 | codec->ActiveQP = (M_QuantizationParameter*)gf_list_get(codec->QPs, 0); |
50 | 0 | gf_list_rem(codec->QPs, 0); |
51 | 0 | } else if (codec->scene_graph->global_qp) { |
52 | 0 | codec->ActiveQP = (M_QuantizationParameter *)codec->scene_graph->global_qp; |
53 | 0 | } |
54 | 0 | return GF_OK; |
55 | 0 | } |
56 | | |
57 | | |
58 | | u32 gf_bifs_enc_qp14_get_bits(GF_BifsEncoder *codec) |
59 | 0 | { |
60 | 0 | if (!codec->ActiveQP || !codec->coord_stored) return 0; |
61 | 0 | return (u32) ceil(log1p(codec->NumCoord) / log(2) ); |
62 | 0 | } |
63 | | |
64 | | void gf_bifs_enc_qp14_enter(GF_BifsEncoder *codec, Bool Enter) |
65 | 0 | { |
66 | 0 | if (!codec->ActiveQP) return; |
67 | 0 | if (Enter) codec->storing_coord = GF_TRUE; |
68 | 0 | else { |
69 | 0 | if (codec->storing_coord) codec->coord_stored = GF_TRUE; |
70 | 0 | codec->storing_coord = GF_FALSE; |
71 | 0 | } |
72 | 0 | } |
73 | | |
74 | | void gf_bifs_enc_qp14_reset(GF_BifsEncoder *codec) |
75 | 0 | { |
76 | 0 | codec->coord_stored = GF_FALSE; |
77 | 0 | codec->storing_coord = GF_FALSE; |
78 | 0 | codec->NumCoord = 0; |
79 | 0 | } |
80 | | |
81 | | void gf_bifs_enc_qp14_set_length(GF_BifsEncoder *codec, u32 NbElements) |
82 | 0 | { |
83 | 0 | if (!codec->ActiveQP || !codec->storing_coord || codec->coord_stored) return; |
84 | 0 | codec->NumCoord = NbElements; |
85 | 0 | } |
86 | | |
87 | | void gf_bifs_enc_mantissa_float(GF_BifsEncoder *codec, Fixed ft, GF_BitStream *bs) |
88 | 0 | { |
89 | 0 | u32 mantLength, expLength, mantSign, mantissa, expSign, i, nbBits; |
90 | 0 | s32 exp; |
91 | |
|
92 | 0 | union |
93 | 0 | { |
94 | 0 | Float f; |
95 | 0 | s32 l; |
96 | 0 | } ft_val; |
97 | |
|
98 | 0 | if (ft == 0) { |
99 | 0 | gf_bs_write_int(bs, 0, 4); |
100 | 0 | return; |
101 | 0 | } |
102 | 0 | ft_val.f = FIX2FLT(ft); |
103 | |
|
104 | 0 | mantSign = ((ft_val.l & 0x80000000) >> 31) & 0x1; |
105 | 0 | mantissa = (ft_val.l & 0x007FFFFF) >> 9; |
106 | 0 | mantLength = 15; |
107 | 0 | expSign=0; |
108 | 0 | exp =(((ft_val.l & 0x7F800000) >> 23)-127); |
109 | 0 | expLength = 8; |
110 | |
|
111 | 0 | if (mantissa == 0) mantLength = 1; |
112 | | |
113 | |
|
114 | 0 | if (exp) { |
115 | 0 | if (exp< 0) { |
116 | 0 | expSign = 1; |
117 | 0 | exp = -exp; |
118 | 0 | } |
119 | 0 | while ((exp & (1<<(--expLength)))==0) { } |
120 | 0 | exp &= ~(1<<expLength); |
121 | 0 | expLength++; |
122 | 0 | } else { |
123 | 0 | expLength=0; |
124 | 0 | } |
125 | |
|
126 | 0 | nbBits=0; |
127 | 0 | for(i = mantissa; i>0; ++nbBits) i >>= 1; |
128 | |
|
129 | 0 | gf_bs_write_int(bs, nbBits+1, 4); |
130 | 0 | if (mantLength) { |
131 | 0 | gf_bs_write_int(bs, expLength, 3); |
132 | 0 | gf_bs_write_int(bs, mantSign, 1); |
133 | 0 | gf_bs_write_int(bs, mantissa, nbBits); |
134 | 0 | if(expLength) { |
135 | 0 | gf_bs_write_int(bs, expSign, 1); |
136 | 0 | gf_bs_write_int(bs, exp, expLength - 1); |
137 | 0 | } |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | | |
142 | | //Linear Quantization for floats - go back to float to avoid overflow if nbBits more than 15... |
143 | | s32 Q_Quantize(Fixed Min, Fixed Max, u32 NbBits, Fixed value) |
144 | 0 | { |
145 | 0 | Float _v; |
146 | 0 | if (value <= Min) return 0; |
147 | 0 | if (value >= Max) return (1<<NbBits)-1; |
148 | 0 | _v = FIX2FLT(value - Min); |
149 | 0 | _v *= (1 << NbBits) - 1; |
150 | 0 | _v /= FIX2FLT(Max - Min); |
151 | 0 | return FIX2INT(gf_floor( FLT2FIX(_v+0.5) ) ); |
152 | 0 | } |
153 | | |
154 | | |
155 | | GF_Err Q_EncFloat(GF_BifsEncoder *codec, GF_BitStream *bs, u32 FieldType, SFVec3f BMin, SFVec3f BMax, u32 NbBits, void *field_ptr) |
156 | 0 | { |
157 | 0 | s32 newVal; |
158 | 0 | switch (FieldType) { |
159 | 0 | case GF_SG_VRML_SFINT32: |
160 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
161 | 0 | case GF_SG_VRML_SFFLOAT: |
162 | 0 | newVal = Q_Quantize(BMin.x, BMax.x, NbBits, *((SFFloat *)field_ptr)); |
163 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
164 | 0 | return GF_OK; |
165 | 0 | case GF_SG_VRML_SFVEC2F: |
166 | 0 | newVal = Q_Quantize(BMin.x, BMax.x, NbBits, ((SFVec2f *)field_ptr)->x); |
167 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
168 | 0 | newVal = Q_Quantize(BMin.y, BMax.y, NbBits, ((SFVec2f *)field_ptr)->y); |
169 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
170 | 0 | return GF_OK; |
171 | 0 | case GF_SG_VRML_SFVEC3F: |
172 | 0 | newVal = Q_Quantize(BMin.x, BMax.x, NbBits, ((SFVec3f *)field_ptr)->x); |
173 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
174 | 0 | newVal = Q_Quantize(BMin.y, BMax.y, NbBits, ((SFVec3f *)field_ptr)->y); |
175 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
176 | 0 | newVal = Q_Quantize(BMin.z, BMax.z, NbBits, ((SFVec3f *)field_ptr)->z); |
177 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
178 | 0 | return GF_OK; |
179 | 0 | case GF_SG_VRML_SFCOLOR: |
180 | 0 | newVal = Q_Quantize(BMin.x, BMax.x, NbBits, ((SFColor *)field_ptr)->red); |
181 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
182 | 0 | newVal = Q_Quantize(BMin.y, BMax.y, NbBits, ((SFColor *)field_ptr)->green); |
183 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
184 | 0 | newVal = Q_Quantize(BMin.z, BMax.z, NbBits, ((SFColor *)field_ptr)->blue); |
185 | 0 | gf_bs_write_int(bs, newVal, NbBits); |
186 | 0 | return GF_OK; |
187 | | |
188 | 0 | case GF_SG_VRML_SFROTATION: |
189 | | //forbidden in this Q mode |
190 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
191 | 0 | } |
192 | 0 | return GF_OK; |
193 | 0 | } |
194 | | |
195 | | //int in quant are either Linear Scalar fields or CoordIndex |
196 | | //the quant is just a bitshifting into [0, 2^NbBits-1] |
197 | | //so v = value - b_min |
198 | | GF_Err Q_EncInt(GF_BifsEncoder *codec, GF_BitStream *bs, u32 QType, SFInt32 b_min, u32 NbBits, void *field_ptr) |
199 | 0 | { |
200 | 0 | switch (QType) { |
201 | 0 | case QC_LINEAR_SCALAR: |
202 | 0 | case QC_COORD_INDEX: |
203 | 0 | gf_bs_write_int(bs, *((SFInt32 *)field_ptr) - b_min, NbBits); |
204 | 0 | return GF_OK; |
205 | 0 | default: |
206 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | | GF_Err Q_EncCoordOnUnitSphere(GF_BifsEncoder *codec, GF_BitStream *bs, u32 NbBits, u32 NbComp, Fixed *m_ft) |
211 | 0 | { |
212 | 0 | u32 i; |
213 | 0 | u32 len = NbComp+1; |
214 | 0 | u32 orientation=0; |
215 | 0 | Fixed maxTmp = - FIX_MAX; |
216 | 0 | for (i=0; i<len; i++) { |
217 | 0 | if (ABS(m_ft[i]) > maxTmp) { |
218 | 0 | maxTmp = ABS(m_ft[i]); |
219 | 0 | orientation = i; |
220 | 0 | } |
221 | 0 | } |
222 | 0 | if(NbComp==2) gf_bs_write_int(bs, ((m_ft[orientation]>0) ? 0 : 1), 1); |
223 | 0 | gf_bs_write_int(bs, orientation, 2); |
224 | 0 | for (i=0; i<NbComp; i++) { |
225 | 0 | Fixed v = gf_mulfix(gf_divfix(INT2FIX(4), GF_PI) , gf_atan2(m_ft[orientation], m_ft[(orientation+i+1) % len])); |
226 | 0 | s32 qdt = Q_Quantize(0, 1, NbBits-1, (v>=0 ? v : -v)); |
227 | 0 | s32 qv = (1<<(NbBits-1)) + (v>=0 ? 1 : -1) * qdt; |
228 | 0 | gf_bs_write_int(bs, qv, NbBits); |
229 | 0 | } |
230 | 0 | return GF_OK; |
231 | 0 | } |
232 | | |
233 | | GF_Err Q_EncNormal(GF_BifsEncoder *codec, GF_BitStream *bs, u32 NbBits, void *field_ptr) |
234 | 0 | { |
235 | 0 | Fixed comp[3]; |
236 | 0 | SFVec3f v = * (SFVec3f *)field_ptr; |
237 | 0 | gf_vec_norm(&v); |
238 | 0 | comp[0] = v.x; |
239 | 0 | comp[1] = v.y; |
240 | 0 | comp[2] = v.z; |
241 | 0 | return Q_EncCoordOnUnitSphere(codec, bs, NbBits, 2, comp); |
242 | 0 | } |
243 | | |
244 | | GF_Err Q_EncRotation(GF_BifsEncoder *codec, GF_BitStream *bs, u32 NbBits, void *field_ptr) |
245 | 0 | { |
246 | 0 | GF_Vec4 quat; |
247 | 0 | Fixed comp[4]; |
248 | | |
249 | | /*get quaternion*/ |
250 | 0 | quat = gf_quat_from_rotation(*(SFRotation *)field_ptr); |
251 | 0 | comp[0] = quat.q; |
252 | 0 | comp[1] = quat.x; |
253 | 0 | comp[2] = quat.y; |
254 | 0 | comp[3] = quat.z; |
255 | 0 | return Q_EncCoordOnUnitSphere(codec, bs, NbBits, 3, comp); |
256 | 0 | } |
257 | | |
258 | | GF_Err gf_bifs_enc_quant_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field) |
259 | 0 | { |
260 | 0 | Bool HasQ; |
261 | 0 | u8 QType, AType; |
262 | 0 | u32 NbBits; |
263 | 0 | Fixed b_min, b_max; |
264 | 0 | SFVec3f BMin, BMax; |
265 | 0 | GF_Err e; |
266 | | |
267 | | /*check QP*/ |
268 | 0 | if (!codec->ActiveQP) return GF_EOS; |
269 | | /*check FieldType*/ |
270 | 0 | switch (field->fieldType) { |
271 | 0 | case GF_SG_VRML_SFINT32: |
272 | 0 | case GF_SG_VRML_SFFLOAT: |
273 | 0 | case GF_SG_VRML_SFROTATION: |
274 | 0 | case GF_SG_VRML_SFVEC2F: |
275 | 0 | case GF_SG_VRML_SFVEC3F: |
276 | 0 | break; |
277 | 0 | case GF_SG_VRML_SFCOLOR: |
278 | 0 | break; |
279 | 0 | default: |
280 | 0 | return GF_EOS; |
281 | 0 | } |
282 | | |
283 | | /*check NDT*/ |
284 | 0 | HasQ = gf_bifs_get_aq_info(node, field->fieldIndex, &QType, &AType, &b_min, &b_max, &NbBits); |
285 | 0 | if (!HasQ || !QType) return GF_EOS; |
286 | | |
287 | | /*get NbBits for QP14 (QC_COORD_INDEX)*/ |
288 | 0 | if (QType == QC_COORD_INDEX) { |
289 | 0 | NbBits = gf_bifs_enc_qp14_get_bits(codec); |
290 | | /*QP14 is always on, not having NbBits set means the coord field is set after the index field, hence not decodable*/ |
291 | 0 | if (!NbBits) |
292 | 0 | return GF_NON_COMPLIANT_BITSTREAM; |
293 | 0 | } |
294 | | |
295 | 0 | BMin.x = BMin.y = BMin.z = b_min; |
296 | 0 | BMax.x = BMax.y = BMax.z = b_max; |
297 | | |
298 | | /*check is the QP is on and retrieves the bounds*/ |
299 | 0 | if (!Q_IsTypeOn(codec->ActiveQP, QType, &NbBits, &BMin, &BMax)) return GF_EOS; |
300 | | |
301 | | /*ok the field is Quantized, dequantize*/ |
302 | 0 | switch (QType) { |
303 | | //these are all SFFloat quantized on n fields |
304 | 0 | case QC_3DPOS: |
305 | 0 | case QC_2DPOS: |
306 | 0 | case QC_ORDER: |
307 | 0 | case QC_COLOR: |
308 | 0 | case QC_TEXTURE_COORD: |
309 | 0 | case QC_ANGLE: |
310 | 0 | case QC_SCALE: |
311 | 0 | case QC_INTERPOL_KEYS: |
312 | 0 | case QC_SIZE_3D: |
313 | 0 | case QC_SIZE_2D: |
314 | 0 | e = Q_EncFloat(codec, bs, field->fieldType, BMin, BMax, NbBits, field->far_ptr); |
315 | 0 | break; |
316 | | //SFInt types |
317 | 0 | case QC_LINEAR_SCALAR: |
318 | 0 | case QC_COORD_INDEX: |
319 | 0 | e = Q_EncInt(codec, bs, QType, (SFInt32) b_min, NbBits, field->far_ptr); |
320 | 0 | break; |
321 | | //normalized fields (normals and vectors) |
322 | 0 | case QC_NORMALS: |
323 | | //normal quant is only for SFVec3F |
324 | 0 | if (field->fieldType != GF_SG_VRML_SFVEC3F) return GF_NON_COMPLIANT_BITSTREAM; |
325 | 0 | e = Q_EncNormal(codec, bs, NbBits, field->far_ptr); |
326 | 0 | break; |
327 | 0 | case QC_ROTATION: |
328 | | //normal quant is only for SFVec3F |
329 | 0 | if (field->fieldType != GF_SG_VRML_SFROTATION) return GF_NON_COMPLIANT_BITSTREAM; |
330 | 0 | e = Q_EncRotation(codec, bs, NbBits, field->far_ptr); |
331 | 0 | break; |
332 | 0 | default: |
333 | 0 | return GF_BAD_PARAM; |
334 | 0 | } |
335 | 0 | return e; |
336 | 0 | } |
337 | | |
338 | | #endif /*GPAC_DISABLE_BIFS_ENC*/ |