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