Home | History | Annotate | Download | only in src
      1 /*
      2  ** Copyright 2003-2010, VisualOn, Inc.
      3  **
      4  ** Licensed under the Apache License, Version 2.0 (the "License");
      5  ** you may not use this file except in compliance with the License.
      6  ** You may obtain a copy of the License at
      7  **
      8  **     http://www.apache.org/licenses/LICENSE-2.0
      9  **
     10  ** Unless required by applicable law or agreed to in writing, software
     11  ** distributed under the License is distributed on an "AS IS" BASIS,
     12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  ** See the License for the specific language governing permissions and
     14  ** limitations under the License.
     15  */
     16 /*******************************************************************************
     17 	File:		bitenc.c
     18 
     19 	Content:	Bitstream encoder functions
     20 
     21 *******************************************************************************/
     22 
     23 #include "bitenc.h"
     24 #include "bit_cnt.h"
     25 #include "dyn_bits.h"
     26 #include "qc_data.h"
     27 #include "interface.h"
     28 
     29 #define UNUSED(x) (void)(x)
     30 
     31 static const  Word16 globalGainOffset = 100;
     32 static const  Word16 icsReservedBit   = 0;
     33 
     34 
     35 /*****************************************************************************
     36 *
     37 * function name: encodeSpectralData
     38 * description:  encode spectral data
     39 * returns:      spectral bits used
     40 *
     41 *****************************************************************************/
     42 static Word32 encodeSpectralData(Word16             *sfbOffset,
     43                                  SECTION_DATA       *sectionData,
     44                                  Word16             *quantSpectrum,
     45                                  HANDLE_BIT_BUF      hBitStream)
     46 {
     47   Word16 i,sfb;
     48   Word16 dbgVal;
     49   SECTION_INFO* psectioninfo;
     50   dbgVal = GetBitsAvail(hBitStream);
     51 
     52   for(i=0; i<sectionData->noOfSections; i++) {
     53     psectioninfo = &(sectionData->sectionInfo[i]);
     54 	/*
     55        huffencode spectral data for this section
     56     */
     57     for(sfb=psectioninfo->sfbStart;
     58         sfb<psectioninfo->sfbStart+psectioninfo->sfbCnt;
     59         sfb++) {
     60       codeValues(quantSpectrum+sfbOffset[sfb],
     61                  sfbOffset[sfb+1] - sfbOffset[sfb],
     62                  psectioninfo->codeBook,
     63                  hBitStream);
     64     }
     65   }
     66 
     67   return(GetBitsAvail(hBitStream)-dbgVal);
     68 }
     69 
     70 /*****************************************************************************
     71 *
     72 * function name:encodeGlobalGain
     73 * description: encodes Global Gain (common scale factor)
     74 * returns:     none
     75 *
     76 *****************************************************************************/
     77 static void encodeGlobalGain(Word16 globalGain,
     78                              Word16 logNorm,
     79                              Word16 scalefac,
     80                              HANDLE_BIT_BUF hBitStream)
     81 {
     82   WriteBits(hBitStream, ((globalGain - scalefac) + globalGainOffset-(logNorm << 2)), 8);
     83 }
     84 
     85 
     86 /*****************************************************************************
     87 *
     88 * function name:encodeIcsInfo
     89 * description: encodes Ics Info
     90 * returns:     none
     91 *
     92 *****************************************************************************/
     93 
     94 static void encodeIcsInfo(Word16 blockType,
     95                           Word16 windowShape,
     96                           Word16 groupingMask,
     97                           SECTION_DATA *sectionData,
     98                           HANDLE_BIT_BUF  hBitStream)
     99 {
    100   WriteBits(hBitStream,icsReservedBit,1);
    101   WriteBits(hBitStream,blockType,2);
    102   WriteBits(hBitStream,windowShape,1);
    103 
    104 
    105   switch(blockType){
    106     case LONG_WINDOW:
    107     case START_WINDOW:
    108     case STOP_WINDOW:
    109       WriteBits(hBitStream,sectionData->maxSfbPerGroup,6);
    110 
    111       /* No predictor data present */
    112       WriteBits(hBitStream, 0, 1);
    113       break;
    114 
    115     case SHORT_WINDOW:
    116       WriteBits(hBitStream,sectionData->maxSfbPerGroup,4);
    117 
    118       /*
    119       Write grouping bits
    120       */
    121       WriteBits(hBitStream,groupingMask,TRANS_FAC-1);
    122       break;
    123   }
    124 }
    125 
    126 /*****************************************************************************
    127 *
    128 * function name: encodeSectionData
    129 * description:  encode section data (common Huffman codebooks for adjacent
    130 *               SFB's)
    131 * returns:      none
    132 *
    133 *****************************************************************************/
    134 static Word32 encodeSectionData(SECTION_DATA *sectionData,
    135                                 HANDLE_BIT_BUF hBitStream)
    136 {
    137   Word16 sectEscapeVal=0,sectLenBits=0;
    138   Word16 sectLen;
    139   Word16 i;
    140   Word16 dbgVal=GetBitsAvail(hBitStream);
    141 
    142 
    143 
    144   switch(sectionData->blockType)
    145   {
    146     case LONG_WINDOW:
    147     case START_WINDOW:
    148     case STOP_WINDOW:
    149       sectEscapeVal = SECT_ESC_VAL_LONG;
    150       sectLenBits   = SECT_BITS_LONG;
    151       break;
    152 
    153     case SHORT_WINDOW:
    154       sectEscapeVal = SECT_ESC_VAL_SHORT;
    155       sectLenBits   = SECT_BITS_SHORT;
    156       break;
    157   }
    158 
    159   for(i=0;i<sectionData->noOfSections;i++) {
    160     WriteBits(hBitStream,sectionData->sectionInfo[i].codeBook,4);
    161     sectLen = sectionData->sectionInfo[i].sfbCnt;
    162 
    163     while(sectLen >= sectEscapeVal) {
    164 
    165       WriteBits(hBitStream,sectEscapeVal,sectLenBits);
    166       sectLen = sectLen - sectEscapeVal;
    167     }
    168     WriteBits(hBitStream,sectLen,sectLenBits);
    169   }
    170   return(GetBitsAvail(hBitStream)-dbgVal);
    171 }
    172 
    173 /*****************************************************************************
    174 *
    175 * function name: encodeScaleFactorData
    176 * description:  encode DPCM coded scale factors
    177 * returns:      none
    178 *
    179 *****************************************************************************/
    180 static Word32 encodeScaleFactorData(UWord16        *maxValueInSfb,
    181                                     SECTION_DATA   *sectionData,
    182                                     Word16         *scalefac,
    183                                     HANDLE_BIT_BUF  hBitStream)
    184 {
    185   Word16 i,j,lastValScf,deltaScf;
    186   Word16 dbgVal = GetBitsAvail(hBitStream);
    187   SECTION_INFO* psectioninfo;
    188 
    189   lastValScf=scalefac[sectionData->firstScf];
    190 
    191   for(i=0;i<sectionData->noOfSections;i++){
    192     psectioninfo = &(sectionData->sectionInfo[i]);
    193     if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){
    194       for (j=psectioninfo->sfbStart;
    195            j<psectioninfo->sfbStart+psectioninfo->sfbCnt; j++){
    196 
    197         if(maxValueInSfb[j] == 0) {
    198           deltaScf = 0;
    199         }
    200         else {
    201           deltaScf = lastValScf - scalefac[j];
    202           lastValScf = scalefac[j];
    203         }
    204 
    205         if(codeScalefactorDelta(deltaScf,hBitStream)){
    206           return(1);
    207         }
    208       }
    209     }
    210 
    211   }
    212   return(GetBitsAvail(hBitStream)-dbgVal);
    213 }
    214 
    215 /*****************************************************************************
    216 *
    217 * function name:encodeMsInfo
    218 * description: encodes MS-Stereo Info
    219 * returns:     none
    220 *
    221 *****************************************************************************/
    222 static void encodeMSInfo(Word16          sfbCnt,
    223                          Word16          grpSfb,
    224                          Word16          maxSfb,
    225                          Word16          msDigest,
    226                          Word16         *jsFlags,
    227                          HANDLE_BIT_BUF  hBitStream)
    228 {
    229   Word16 sfb, sfbOff;
    230 
    231 
    232   switch(msDigest)
    233   {
    234     case MS_NONE:
    235       WriteBits(hBitStream,SI_MS_MASK_NONE,2);
    236       break;
    237 
    238     case MS_ALL:
    239       WriteBits(hBitStream,SI_MS_MASK_ALL,2);
    240       break;
    241 
    242     case MS_SOME:
    243       WriteBits(hBitStream,SI_MS_MASK_SOME,2);
    244       for(sfbOff = 0; sfbOff < sfbCnt; sfbOff+=grpSfb) {
    245         for(sfb=0; sfb<maxSfb; sfb++) {
    246 
    247           if(jsFlags[sfbOff+sfb] & MS_ON) {
    248             WriteBits(hBitStream,1,1);
    249           }
    250           else{
    251             WriteBits(hBitStream,0,1);
    252           }
    253         }
    254       }
    255       break;
    256   }
    257 
    258 }
    259 
    260 /*****************************************************************************
    261 *
    262 * function name: encodeTnsData
    263 * description:  encode TNS data (filter order, coeffs, ..)
    264 * returns:      none
    265 *
    266 *****************************************************************************/
    267 static void encodeTnsData(TNS_INFO tnsInfo,
    268                           Word16 blockType,
    269                           HANDLE_BIT_BUF hBitStream) {
    270   Word16 i,k;
    271   Flag tnsPresent;
    272   Word16 numOfWindows;
    273   Word16 coefBits;
    274   Flag isShort;
    275 
    276 
    277   if (blockType==2) {
    278     isShort = 1;
    279     numOfWindows = TRANS_FAC;
    280   }
    281   else {
    282     isShort = 0;
    283     numOfWindows = 1;
    284   }
    285 
    286   tnsPresent=0;
    287   for (i=0; i<numOfWindows; i++) {
    288 
    289     if (tnsInfo.tnsActive[i]) {
    290       tnsPresent=1;
    291     }
    292   }
    293 
    294   if (tnsPresent==0) {
    295     WriteBits(hBitStream,0,1);
    296   }
    297   else{ /* there is data to be written*/
    298     WriteBits(hBitStream,1,1); /*data_present */
    299     for (i=0; i<numOfWindows; i++) {
    300 
    301       WriteBits(hBitStream,tnsInfo.tnsActive[i],(isShort?1:2));
    302 
    303       if (tnsInfo.tnsActive[i]) {
    304 
    305         WriteBits(hBitStream,((tnsInfo.coefRes[i] - 4)==0?1:0),1);
    306 
    307         WriteBits(hBitStream,tnsInfo.length[i],(isShort?4:6));
    308 
    309         WriteBits(hBitStream,tnsInfo.order[i],(isShort?3:5));
    310 
    311         if (tnsInfo.order[i]){
    312           WriteBits(hBitStream, FILTER_DIRECTION, 1);
    313 
    314           if(tnsInfo.coefRes[i] == 4) {
    315             coefBits = 3;
    316             for(k=0; k<tnsInfo.order[i]; k++) {
    317 
    318               if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 3 ||
    319                   tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) {
    320                 coefBits = 4;
    321                 break;
    322               }
    323             }
    324           }
    325           else {
    326             coefBits = 2;
    327             for(k=0; k<tnsInfo.order[i]; k++) {
    328 
    329               if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 1 ||
    330                   tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -2) {
    331                 coefBits = 3;
    332                 break;
    333               }
    334             }
    335           }
    336           WriteBits(hBitStream, tnsInfo.coefRes[i] - coefBits, 1); /*coef_compres*/
    337           for (k=0; k<tnsInfo.order[i]; k++ ) {
    338             static const Word16 rmask[] = {0,1,3,7,15};
    339 
    340             WriteBits(hBitStream,tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] & rmask[coefBits],coefBits);
    341           }
    342         }
    343       }
    344     }
    345   }
    346 
    347 }
    348 
    349 /*****************************************************************************
    350 *
    351 * function name: encodeGainControlData
    352 * description:  unsupported
    353 * returns:      none
    354 *
    355 *****************************************************************************/
    356 static void encodeGainControlData(HANDLE_BIT_BUF hBitStream)
    357 {
    358   WriteBits(hBitStream,0,1);
    359 }
    360 
    361 /*****************************************************************************
    362 *
    363 * function name: encodePulseData
    364 * description:  not supported yet (dummy)
    365 * returns:      none
    366 *
    367 *****************************************************************************/
    368 static void encodePulseData(HANDLE_BIT_BUF hBitStream)
    369 {
    370   WriteBits(hBitStream,0,1);
    371 }
    372 
    373 
    374 /*****************************************************************************
    375 *
    376 * function name: WriteIndividualChannelStream
    377 * description:  management of write process of individual channel stream
    378 * returns:      none
    379 *
    380 *****************************************************************************/
    381 static void
    382 writeIndividualChannelStream(Flag   commonWindow,
    383                              Word16 mdctScale,
    384                              Word16 windowShape,
    385                              Word16 groupingMask,
    386                              Word16 *sfbOffset,
    387                              Word16 scf[],
    388                              UWord16 *maxValueInSfb,
    389                              Word16 globalGain,
    390                              Word16 quantSpec[],
    391                              SECTION_DATA *sectionData,
    392                              HANDLE_BIT_BUF hBitStream,
    393                              TNS_INFO tnsInfo)
    394 {
    395   Word16 logNorm;
    396 
    397   logNorm = LOG_NORM_PCM - (mdctScale + 1);
    398 
    399   encodeGlobalGain(globalGain, logNorm,scf[sectionData->firstScf], hBitStream);
    400 
    401 
    402   if(!commonWindow) {
    403     encodeIcsInfo(sectionData->blockType, windowShape, groupingMask, sectionData, hBitStream);
    404   }
    405 
    406   encodeSectionData(sectionData, hBitStream);
    407 
    408   encodeScaleFactorData(maxValueInSfb,
    409                         sectionData,
    410                         scf,
    411                         hBitStream);
    412 
    413   encodePulseData(hBitStream);
    414 
    415   encodeTnsData(tnsInfo, sectionData->blockType, hBitStream);
    416 
    417   encodeGainControlData(hBitStream);
    418 
    419   encodeSpectralData(sfbOffset,
    420                      sectionData,
    421                      quantSpec,
    422                      hBitStream);
    423 
    424 }
    425 
    426 /*****************************************************************************
    427 *
    428 * function name: writeSingleChannelElement
    429 * description:  write single channel element to bitstream
    430 * returns:      none
    431 *
    432 *****************************************************************************/
    433 static Word16 writeSingleChannelElement(Word16 instanceTag,
    434                                         Word16 *sfbOffset,
    435                                         QC_OUT_CHANNEL* qcOutChannel,
    436                                         HANDLE_BIT_BUF hBitStream,
    437                                         TNS_INFO tnsInfo)
    438 {
    439   WriteBits(hBitStream,ID_SCE,3);
    440   WriteBits(hBitStream,instanceTag,4);
    441   writeIndividualChannelStream(0,
    442                                qcOutChannel->mdctScale,
    443                                qcOutChannel->windowShape,
    444                                qcOutChannel->groupingMask,
    445                                sfbOffset,
    446                                qcOutChannel->scf,
    447                                qcOutChannel->maxValueInSfb,
    448                                qcOutChannel->globalGain,
    449                                qcOutChannel->quantSpec,
    450                                &(qcOutChannel->sectionData),
    451                                hBitStream,
    452                                tnsInfo
    453                                );
    454   return(0);
    455 }
    456 
    457 
    458 
    459 /*****************************************************************************
    460 *
    461 * function name: writeChannelPairElement
    462 * description:
    463 * returns:      none
    464 *
    465 *****************************************************************************/
    466 static Word16 writeChannelPairElement(Word16 instanceTag,
    467                                       Word16 msDigest,
    468                                       Word16 msFlags[MAX_GROUPED_SFB],
    469                                       Word16 *sfbOffset[2],
    470                                       QC_OUT_CHANNEL qcOutChannel[2],
    471                                       HANDLE_BIT_BUF hBitStream,
    472                                       TNS_INFO tnsInfo[2])
    473 {
    474   WriteBits(hBitStream,ID_CPE,3);
    475   WriteBits(hBitStream,instanceTag,4);
    476   WriteBits(hBitStream,1,1); /* common window */
    477 
    478   encodeIcsInfo(qcOutChannel[0].sectionData.blockType,
    479                 qcOutChannel[0].windowShape,
    480                 qcOutChannel[0].groupingMask,
    481                 &(qcOutChannel[0].sectionData),
    482                 hBitStream);
    483 
    484   encodeMSInfo(qcOutChannel[0].sectionData.sfbCnt,
    485                qcOutChannel[0].sectionData.sfbPerGroup,
    486                qcOutChannel[0].sectionData.maxSfbPerGroup,
    487                msDigest,
    488                msFlags,
    489                hBitStream);
    490 
    491   writeIndividualChannelStream(1,
    492                                qcOutChannel[0].mdctScale,
    493                                qcOutChannel[0].windowShape,
    494                                qcOutChannel[0].groupingMask,
    495                                sfbOffset[0],
    496                                qcOutChannel[0].scf,
    497                                qcOutChannel[0].maxValueInSfb,
    498                                qcOutChannel[0].globalGain,
    499                                qcOutChannel[0].quantSpec,
    500                                &(qcOutChannel[0].sectionData),
    501                                hBitStream,
    502                                tnsInfo[0]);
    503 
    504   writeIndividualChannelStream(1,
    505                                qcOutChannel[1].mdctScale,
    506                                qcOutChannel[1].windowShape,
    507                                qcOutChannel[1].groupingMask,
    508                                sfbOffset[1],
    509                                qcOutChannel[1].scf,
    510                                qcOutChannel[1].maxValueInSfb,
    511                                qcOutChannel[1].globalGain,
    512                                qcOutChannel[1].quantSpec,
    513                                &(qcOutChannel[1].sectionData),
    514                                hBitStream,
    515                                tnsInfo[1]);
    516 
    517   return(0);
    518 }
    519 
    520 
    521 
    522 /*****************************************************************************
    523 *
    524 * function name: writeFillElement
    525 * description:  write fill elements to bitstream
    526 * returns:      none
    527 *
    528 *****************************************************************************/
    529 static void writeFillElement( const UWord8 *ancBytes,
    530                               Word16 totFillBits,
    531                               HANDLE_BIT_BUF hBitStream)
    532 {
    533   Word16 i;
    534   Word16 cnt,esc_count;
    535 
    536   /*
    537     Write fill Element(s):
    538     amount of a fill element can be 7+X*8 Bits, X element of [0..270]
    539   */
    540 
    541   while(totFillBits >= (3+4)) {
    542     cnt = min(((totFillBits - (3+4)) >> 3), ((1<<4)-1));
    543 
    544     WriteBits(hBitStream,ID_FIL,3);
    545     WriteBits(hBitStream,cnt,4);
    546 
    547     totFillBits = totFillBits - (3+4);
    548 
    549 
    550     if (cnt == (1<<4)-1) {
    551 
    552       esc_count = min( ((totFillBits >> 3) - ((1<<4)-1)), (1<<8)-1);
    553       WriteBits(hBitStream,esc_count,8);
    554       totFillBits = (totFillBits - 8);
    555       cnt = cnt + (esc_count - 1);
    556     }
    557 
    558     for(i=0;i<cnt;i++) {
    559 
    560       if(ancBytes)
    561         WriteBits(hBitStream, *ancBytes++,8);
    562       else
    563         WriteBits(hBitStream,0,8);
    564       totFillBits = totFillBits - 8;
    565     }
    566   }
    567 }
    568 
    569 /*****************************************************************************
    570 *
    571 * function name: WriteBitStream
    572 * description:  main function of write bitsteam process
    573 * returns:      0 if success
    574 *
    575 *****************************************************************************/
    576 Word16 WriteBitstream (HANDLE_BIT_BUF hBitStream,
    577                        ELEMENT_INFO elInfo,
    578                        QC_OUT *qcOut,
    579                        PSY_OUT *psyOut,
    580                        Word16 *globUsedBits,
    581                        const UWord8 *ancBytes,
    582 					   Word16 sampindex
    583                        ) /* returns error code */
    584 {
    585   Word16 bitMarkUp;
    586   Word16 elementUsedBits;
    587   Word16 frameBits=0;
    588 
    589   UNUSED(ancBytes);
    590 
    591   /*   struct bitbuffer bsWriteCopy; */
    592   bitMarkUp = GetBitsAvail(hBitStream);
    593   if(qcOut->qcElement.adtsUsed)  /*  write adts header*/
    594   {
    595 	  WriteBits(hBitStream, 0xFFF, 12); /* 12 bit Syncword */
    596 	  WriteBits(hBitStream, 1, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */
    597 	  WriteBits(hBitStream, 0, 2); /* layer == 0 */
    598 	  WriteBits(hBitStream, 1, 1); /* protection absent */
    599 	  WriteBits(hBitStream, 1, 2); /* profile */
    600 	  WriteBits(hBitStream, sampindex, 4); /* sampling rate */
    601 	  WriteBits(hBitStream, 0, 1); /* private bit */
    602 	  WriteBits(hBitStream, elInfo.nChannelsInEl, 3); /* ch. config (must be > 0) */
    603 								   /* simply using numChannels only works for
    604 									6 channels or less, else a channel
    605 									configuration should be written */
    606 	  WriteBits(hBitStream, 0, 1); /* original/copy */
    607 	  WriteBits(hBitStream, 0, 1); /* home */
    608 
    609 	  /* Variable ADTS header */
    610 	  WriteBits(hBitStream, 0, 1); /* copyr. id. bit */
    611 	  WriteBits(hBitStream, 0, 1); /* copyr. id. start */
    612 	  WriteBits(hBitStream, *globUsedBits >> 3, 13);
    613 	  WriteBits(hBitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */
    614 	  WriteBits(hBitStream, 0, 2); /* raw data blocks (0+1=1) */
    615   }
    616 
    617   *globUsedBits=0;
    618 
    619   {
    620 
    621     Word16 *sfbOffset[2];
    622     TNS_INFO tnsInfo[2];
    623     elementUsedBits = 0;
    624 
    625     switch (elInfo.elType) {
    626 
    627       case ID_SCE:      /* single channel */
    628         sfbOffset[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
    629         tnsInfo[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
    630 
    631         writeSingleChannelElement(elInfo.instanceTag,
    632                                   sfbOffset[0],
    633                                   &qcOut->qcChannel[elInfo.ChannelIndex[0]],
    634                                   hBitStream,
    635                                   tnsInfo[0]);
    636         break;
    637 
    638       case ID_CPE:     /* channel pair */
    639         {
    640           Word16 msDigest;
    641           Word16 *msFlags = psyOut->psyOutElement.toolsInfo.msMask;
    642           msDigest = psyOut->psyOutElement.toolsInfo.msDigest;
    643           sfbOffset[0] =
    644             psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
    645           sfbOffset[1] =
    646             psyOut->psyOutChannel[elInfo.ChannelIndex[1]].sfbOffsets;
    647 
    648           tnsInfo[0]=
    649             psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
    650           tnsInfo[1]=
    651             psyOut->psyOutChannel[elInfo.ChannelIndex[1]].tnsInfo;
    652           writeChannelPairElement(elInfo.instanceTag,
    653                                   msDigest,
    654                                   msFlags,
    655                                   sfbOffset,
    656                                   &qcOut->qcChannel[elInfo.ChannelIndex[0]],
    657                                   hBitStream,
    658                                   tnsInfo);
    659         }
    660         break;
    661 
    662       default:
    663         return(1);
    664 
    665       }   /* switch */
    666 
    667     elementUsedBits = elementUsedBits - bitMarkUp;
    668     bitMarkUp = GetBitsAvail(hBitStream);
    669     frameBits = frameBits + elementUsedBits + bitMarkUp;
    670 
    671   }
    672 
    673   writeFillElement(NULL,
    674                    qcOut->totFillBits,
    675                    hBitStream);
    676 
    677   WriteBits(hBitStream,ID_END,3);
    678 
    679   /* byte alignement */
    680   WriteBits(hBitStream,0, (8 - (hBitStream->cntBits & 7)) & 7);
    681 
    682   *globUsedBits = *globUsedBits- bitMarkUp;
    683   bitMarkUp = GetBitsAvail(hBitStream);
    684   *globUsedBits = *globUsedBits + bitMarkUp;
    685   frameBits = frameBits + *globUsedBits;
    686 
    687 
    688   if (frameBits !=  (qcOut->totStaticBitsUsed+qcOut->totDynBitsUsed + qcOut->totAncBitsUsed +
    689                      qcOut->totFillBits + qcOut->alignBits)) {
    690     return(-1);
    691   }
    692   return(0);
    693 }
    694