LCOV - code coverage report
Current view: top level - bifs - unquantize.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 192 227 84.6 %
Date: 2021-04-29 23:48:07 Functions: 13 15 86.7 %

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

Generated by: LCOV version 1.13