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 *****************************************************************************/
encodeSpectralData(Word16 * sfbOffset,SECTION_DATA * sectionData,Word16 * quantSpectrum,HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
encodeGlobalGain(Word16 globalGain,Word16 logNorm,Word16 scalefac,HANDLE_BIT_BUF hBitStream)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
encodeIcsInfo(Word16 blockType,Word16 windowShape,Word16 groupingMask,SECTION_DATA * sectionData,HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
encodeSectionData(SECTION_DATA * sectionData,HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
encodeScaleFactorData(UWord16 * maxValueInSfb,SECTION_DATA * sectionData,Word16 * scalefac,HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
encodeMSInfo(Word16 sfbCnt,Word16 grpSfb,Word16 maxSfb,Word16 msDigest,Word16 * jsFlags,HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
encodeTnsData(TNS_INFO tnsInfo,Word16 blockType,HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
encodeGainControlData(HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
encodePulseData(HANDLE_BIT_BUF hBitStream)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
writeIndividualChannelStream(Flag commonWindow,Word16 mdctScale,Word16 windowShape,Word16 groupingMask,Word16 * sfbOffset,Word16 scf[],UWord16 * maxValueInSfb,Word16 globalGain,Word16 quantSpec[],SECTION_DATA * sectionData,HANDLE_BIT_BUF hBitStream,TNS_INFO tnsInfo)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 *****************************************************************************/
writeSingleChannelElement(Word16 instanceTag,Word16 * sfbOffset,QC_OUT_CHANNEL * qcOutChannel,HANDLE_BIT_BUF hBitStream,TNS_INFO tnsInfo)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 *****************************************************************************/
writeChannelPairElement(Word16 instanceTag,Word16 msDigest,Word16 msFlags[MAX_GROUPED_SFB],Word16 * sfbOffset[2],QC_OUT_CHANNEL qcOutChannel[2],HANDLE_BIT_BUF hBitStream,TNS_INFO tnsInfo[2])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 *****************************************************************************/
writeFillElement(const UWord8 * ancBytes,Word16 totFillBits,HANDLE_BIT_BUF hBitStream)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 *****************************************************************************/
WriteBitstream(HANDLE_BIT_BUF hBitStream,ELEMENT_INFO elInfo,QC_OUT * qcOut,PSY_OUT * psyOut,Word16 * globUsedBits,const UWord8 * ancBytes,Word16 sampindex)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