• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6 
7  1.    INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18 
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28 
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33 
34 2.    COPYRIGHT LICENSE
35 
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39 
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42 
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48 
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51 
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54 
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60 
61 3.    NO PATENT LICENSE
62 
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67 
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70 
71 4.    DISCLAIMER
72 
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83 
84 5.    CONTACT INFORMATION
85 
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90 
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94 
95 /**************************** AAC encoder library ******************************
96 
97    Author(s):   M. Werner
98 
99    Description: Bitstream encoder
100 
101 *******************************************************************************/
102 
103 #include "bitenc.h"
104 #include "bit_cnt.h"
105 #include "dyn_bits.h"
106 #include "qc_data.h"
107 #include "interface.h"
108 #include "aacEnc_ram.h"
109 
110 #include "tpenc_lib.h"
111 
112 #include "FDK_tools_rom.h" /* needed for the bitstream syntax tables */
113 
114 static const int globalGainOffset = 100;
115 static const int icsReservedBit = 0;
116 static const int noiseOffset = 90;
117 
118 /*****************************************************************************
119 
120     functionname: FDKaacEnc_encodeSpectralData
121     description:  encode spectral data
122     returns:      the number of written bits
123     input:
124     output:
125 
126 *****************************************************************************/
FDKaacEnc_encodeSpectralData(INT * sfbOffset,SECTION_DATA * sectionData,SHORT * quantSpectrum,HANDLE_FDK_BITSTREAM hBitStream)127 static INT FDKaacEnc_encodeSpectralData(INT *sfbOffset,
128                                         SECTION_DATA *sectionData,
129                                         SHORT *quantSpectrum,
130                                         HANDLE_FDK_BITSTREAM hBitStream) {
131   INT i, sfb;
132   INT dbgVal = FDKgetValidBits(hBitStream);
133 
134   for (i = 0; i < sectionData->noOfSections; i++) {
135     if (sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO) {
136       /* huffencode spectral data for this huffsection */
137       INT tmp = sectionData->huffsection[i].sfbStart +
138                 sectionData->huffsection[i].sfbCnt;
139       for (sfb = sectionData->huffsection[i].sfbStart; sfb < tmp; sfb++) {
140         FDKaacEnc_codeValues(quantSpectrum + sfbOffset[sfb],
141                              sfbOffset[sfb + 1] - sfbOffset[sfb],
142                              sectionData->huffsection[i].codeBook, hBitStream);
143       }
144     }
145   }
146   return (FDKgetValidBits(hBitStream) - dbgVal);
147 }
148 
149 /*****************************************************************************
150 
151     functionname:FDKaacEnc_encodeGlobalGain
152     description: encodes Global Gain (common scale factor)
153     returns:     the number of static bits
154     input:
155     output:
156 
157 *****************************************************************************/
FDKaacEnc_encodeGlobalGain(INT globalGain,INT scalefac,HANDLE_FDK_BITSTREAM hBitStream,INT mdctScale)158 static INT FDKaacEnc_encodeGlobalGain(INT globalGain, INT scalefac,
159                                       HANDLE_FDK_BITSTREAM hBitStream,
160                                       INT mdctScale) {
161   if (hBitStream != NULL) {
162     FDKwriteBits(hBitStream,
163                  globalGain - scalefac + globalGainOffset -
164                      4 * (LOG_NORM_PCM - mdctScale),
165                  8);
166   }
167   return (8);
168 }
169 
170 /*****************************************************************************
171 
172     functionname:FDKaacEnc_encodeIcsInfo
173     description: encodes Ics Info
174     returns:     the number of static bits
175     input:
176     output:
177 
178 *****************************************************************************/
179 
FDKaacEnc_encodeIcsInfo(INT blockType,INT windowShape,INT groupingMask,INT maxSfbPerGroup,HANDLE_FDK_BITSTREAM hBitStream,UINT syntaxFlags)180 static INT FDKaacEnc_encodeIcsInfo(INT blockType, INT windowShape,
181                                    INT groupingMask, INT maxSfbPerGroup,
182                                    HANDLE_FDK_BITSTREAM hBitStream,
183                                    UINT syntaxFlags) {
184   INT statBits;
185 
186   if (blockType == SHORT_WINDOW) {
187     statBits = 8 + TRANS_FAC - 1;
188   } else {
189     if (syntaxFlags & AC_ELD) {
190       statBits = 6;
191     } else {
192       statBits = (!(syntaxFlags & AC_SCALABLE)) ? 11 : 10;
193     }
194   }
195 
196   if (hBitStream != NULL) {
197     if (!(syntaxFlags & AC_ELD)) {
198       FDKwriteBits(hBitStream, icsReservedBit, 1);
199       FDKwriteBits(hBitStream, blockType, 2);
200       FDKwriteBits(hBitStream,
201                    (windowShape == LOL_WINDOW) ? KBD_WINDOW : windowShape, 1);
202     }
203 
204     switch (blockType) {
205       case LONG_WINDOW:
206       case START_WINDOW:
207       case STOP_WINDOW:
208         FDKwriteBits(hBitStream, maxSfbPerGroup, 6);
209 
210         if (!(syntaxFlags &
211               (AC_SCALABLE | AC_ELD))) { /* If not scalable syntax then ... */
212           /* No predictor data present */
213           FDKwriteBits(hBitStream, 0, 1);
214         }
215         break;
216 
217       case SHORT_WINDOW:
218         FDKwriteBits(hBitStream, maxSfbPerGroup, 4);
219 
220         /* Write grouping bits */
221         FDKwriteBits(hBitStream, groupingMask, TRANS_FAC - 1);
222         break;
223     }
224   }
225 
226   return (statBits);
227 }
228 
229 /*****************************************************************************
230 
231     functionname: FDKaacEnc_encodeSectionData
232     description:  encode section data (common Huffman codebooks for adjacent
233                   SFB's)
234     returns:      none
235     input:
236     output:
237 
238 *****************************************************************************/
FDKaacEnc_encodeSectionData(SECTION_DATA * sectionData,HANDLE_FDK_BITSTREAM hBitStream,UINT useVCB11)239 static INT FDKaacEnc_encodeSectionData(SECTION_DATA *sectionData,
240                                        HANDLE_FDK_BITSTREAM hBitStream,
241                                        UINT useVCB11) {
242   if (hBitStream != NULL) {
243     INT sectEscapeVal = 0, sectLenBits = 0;
244     INT sectLen;
245     INT i;
246     INT dbgVal = FDKgetValidBits(hBitStream);
247     INT sectCbBits = 4;
248 
249     switch (sectionData->blockType) {
250       case LONG_WINDOW:
251       case START_WINDOW:
252       case STOP_WINDOW:
253         sectEscapeVal = SECT_ESC_VAL_LONG;
254         sectLenBits = SECT_BITS_LONG;
255         break;
256 
257       case SHORT_WINDOW:
258         sectEscapeVal = SECT_ESC_VAL_SHORT;
259         sectLenBits = SECT_BITS_SHORT;
260         break;
261     }
262 
263     for (i = 0; i < sectionData->noOfSections; i++) {
264       INT codeBook = sectionData->huffsection[i].codeBook;
265 
266       FDKwriteBits(hBitStream, codeBook, sectCbBits);
267 
268       {
269         sectLen = sectionData->huffsection[i].sfbCnt;
270 
271         while (sectLen >= sectEscapeVal) {
272           FDKwriteBits(hBitStream, sectEscapeVal, sectLenBits);
273           sectLen -= sectEscapeVal;
274         }
275         FDKwriteBits(hBitStream, sectLen, sectLenBits);
276       }
277     }
278     return (FDKgetValidBits(hBitStream) - dbgVal);
279   }
280   return (0);
281 }
282 
283 /*****************************************************************************
284 
285     functionname: FDKaacEnc_encodeScaleFactorData
286     description:  encode DPCM coded scale factors
287     returns:      none
288     input:
289     output:
290 
291 *****************************************************************************/
FDKaacEnc_encodeScaleFactorData(UINT * maxValueInSfb,SECTION_DATA * sectionData,INT * scalefac,HANDLE_FDK_BITSTREAM hBitStream,INT * RESTRICT noiseNrg,const INT * isScale,INT globalGain)292 static INT FDKaacEnc_encodeScaleFactorData(UINT *maxValueInSfb,
293                                            SECTION_DATA *sectionData,
294                                            INT *scalefac,
295                                            HANDLE_FDK_BITSTREAM hBitStream,
296                                            INT *RESTRICT noiseNrg,
297                                            const INT *isScale, INT globalGain) {
298   if (hBitStream != NULL) {
299     INT i, j, lastValScf, deltaScf;
300     INT deltaPns;
301     INT lastValPns = 0;
302     INT noisePCMFlag = TRUE;
303     INT lastValIs;
304 
305     INT dbgVal = FDKgetValidBits(hBitStream);
306 
307     lastValScf = scalefac[sectionData->firstScf];
308     lastValPns = globalGain - scalefac[sectionData->firstScf] +
309                  globalGainOffset - 4 * LOG_NORM_PCM - noiseOffset;
310     lastValIs = 0;
311 
312     for (i = 0; i < sectionData->noOfSections; i++) {
313       if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) {
314         if ((sectionData->huffsection[i].codeBook ==
315              CODE_BOOK_IS_OUT_OF_PHASE_NO) ||
316             (sectionData->huffsection[i].codeBook ==
317              CODE_BOOK_IS_IN_PHASE_NO)) {
318           INT sfbStart = sectionData->huffsection[i].sfbStart;
319           INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt;
320           for (j = sfbStart; j < tmp; j++) {
321             INT deltaIs = isScale[j] - lastValIs;
322             lastValIs = isScale[j];
323             if (FDKaacEnc_codeScalefactorDelta(deltaIs, hBitStream)) {
324               return (1);
325             }
326           } /* sfb */
327         } else if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) {
328           INT sfbStart = sectionData->huffsection[i].sfbStart;
329           INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt;
330           for (j = sfbStart; j < tmp; j++) {
331             deltaPns = noiseNrg[j] - lastValPns;
332             lastValPns = noiseNrg[j];
333 
334             if (noisePCMFlag) {
335               FDKwriteBits(hBitStream, deltaPns + (1 << (PNS_PCM_BITS - 1)),
336                            PNS_PCM_BITS);
337               noisePCMFlag = FALSE;
338             } else {
339               if (FDKaacEnc_codeScalefactorDelta(deltaPns, hBitStream)) {
340                 return (1);
341               }
342             }
343           } /* sfb */
344         } else {
345           INT tmp = sectionData->huffsection[i].sfbStart +
346                     sectionData->huffsection[i].sfbCnt;
347           for (j = sectionData->huffsection[i].sfbStart; j < tmp; j++) {
348             /*
349               check if we can repeat the last value to save bits
350             */
351             if (maxValueInSfb[j] == 0)
352               deltaScf = 0;
353             else {
354               deltaScf = -(scalefac[j] - lastValScf);
355               lastValScf = scalefac[j];
356             }
357             if (FDKaacEnc_codeScalefactorDelta(deltaScf, hBitStream)) {
358               return (1);
359             }
360           } /* sfb */
361         }   /* code scalefactor */
362       }     /* sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO */
363     }       /* section loop */
364 
365     return (FDKgetValidBits(hBitStream) - dbgVal);
366   } /* if (hBitStream != NULL) */
367 
368   return (0);
369 }
370 
371 /*****************************************************************************
372 
373     functionname:encodeMsInfo
374     description: encodes MS-Stereo Info
375     returns:     the number of static bits
376     input:
377     output:
378 
379 *****************************************************************************/
FDKaacEnc_encodeMSInfo(INT sfbCnt,INT grpSfb,INT maxSfb,INT msDigest,INT * jsFlags,HANDLE_FDK_BITSTREAM hBitStream)380 static INT FDKaacEnc_encodeMSInfo(INT sfbCnt, INT grpSfb, INT maxSfb,
381                                   INT msDigest, INT *jsFlags,
382                                   HANDLE_FDK_BITSTREAM hBitStream) {
383   INT sfb, sfbOff, msBits = 0;
384 
385   if (hBitStream != NULL) {
386     switch (msDigest) {
387       case MS_NONE:
388         FDKwriteBits(hBitStream, SI_MS_MASK_NONE, 2);
389         msBits += 2;
390         break;
391 
392       case MS_ALL:
393         FDKwriteBits(hBitStream, SI_MS_MASK_ALL, 2);
394         msBits += 2;
395         break;
396 
397       case MS_SOME:
398         FDKwriteBits(hBitStream, SI_MS_MASK_SOME, 2);
399         msBits += 2;
400         for (sfbOff = 0; sfbOff < sfbCnt; sfbOff += grpSfb) {
401           for (sfb = 0; sfb < maxSfb; sfb++) {
402             if (jsFlags[sfbOff + sfb] & MS_ON) {
403               FDKwriteBits(hBitStream, 1, 1);
404             } else {
405               FDKwriteBits(hBitStream, 0, 1);
406             }
407             msBits += 1;
408           }
409         }
410         break;
411     }
412   } else {
413     msBits += 2;
414     if (msDigest == MS_SOME) {
415       for (sfbOff = 0; sfbOff < sfbCnt; sfbOff += grpSfb) {
416         for (sfb = 0; sfb < maxSfb; sfb++) {
417           msBits += 1;
418         }
419       }
420     }
421   }
422   return (msBits);
423 }
424 
425 /*****************************************************************************
426 
427     functionname: FDKaacEnc_encodeTnsDataPresent
428     description:  encode TNS data (filter order, coeffs, ..)
429     returns:      the number of static bits
430     input:
431     output:
432 
433 *****************************************************************************/
FDKaacEnc_encodeTnsDataPresent(TNS_INFO * tnsInfo,INT blockType,HANDLE_FDK_BITSTREAM hBitStream)434 static INT FDKaacEnc_encodeTnsDataPresent(TNS_INFO *tnsInfo, INT blockType,
435                                           HANDLE_FDK_BITSTREAM hBitStream) {
436   if ((hBitStream != NULL) && (tnsInfo != NULL)) {
437     INT i, tnsPresent = 0;
438     INT numOfWindows = (blockType == SHORT_WINDOW ? TRANS_FAC : 1);
439 
440     for (i = 0; i < numOfWindows; i++) {
441       if (tnsInfo->numOfFilters[i] != 0) {
442         tnsPresent = 1;
443         break;
444       }
445     }
446 
447     if (tnsPresent == 0) {
448       FDKwriteBits(hBitStream, 0, 1);
449     } else {
450       FDKwriteBits(hBitStream, 1, 1);
451     }
452   }
453   return (1);
454 }
455 
456 /*****************************************************************************
457 
458     functionname: FDKaacEnc_encodeTnsData
459     description:  encode TNS data (filter order, coeffs, ..)
460     returns:      the number of static bits
461     input:
462     output:
463 
464 *****************************************************************************/
FDKaacEnc_encodeTnsData(TNS_INFO * tnsInfo,INT blockType,HANDLE_FDK_BITSTREAM hBitStream)465 static INT FDKaacEnc_encodeTnsData(TNS_INFO *tnsInfo, INT blockType,
466                                    HANDLE_FDK_BITSTREAM hBitStream) {
467   INT tnsBits = 0;
468 
469   if (tnsInfo != NULL) {
470     INT i, j, k;
471     INT tnsPresent = 0;
472     INT coefBits;
473     INT numOfWindows = (blockType == SHORT_WINDOW ? TRANS_FAC : 1);
474 
475     for (i = 0; i < numOfWindows; i++) {
476       if (tnsInfo->numOfFilters[i] != 0) {
477         tnsPresent = 1;
478       }
479     }
480 
481     if (hBitStream != NULL) {
482       if (tnsPresent == 1) { /* there is data to be written*/
483         for (i = 0; i < numOfWindows; i++) {
484           FDKwriteBits(hBitStream, tnsInfo->numOfFilters[i],
485                        (blockType == SHORT_WINDOW ? 1 : 2));
486           tnsBits += (blockType == SHORT_WINDOW ? 1 : 2);
487           if (tnsInfo->numOfFilters[i]) {
488             FDKwriteBits(hBitStream, (tnsInfo->coefRes[i] == 4 ? 1 : 0), 1);
489             tnsBits += 1;
490           }
491           for (j = 0; j < tnsInfo->numOfFilters[i]; j++) {
492             FDKwriteBits(hBitStream, tnsInfo->length[i][j],
493                          (blockType == SHORT_WINDOW ? 4 : 6));
494             tnsBits += (blockType == SHORT_WINDOW ? 4 : 6);
495             FDK_ASSERT(tnsInfo->order[i][j] <= 12);
496             FDKwriteBits(hBitStream, tnsInfo->order[i][j],
497                          (blockType == SHORT_WINDOW ? 3 : 5));
498             tnsBits += (blockType == SHORT_WINDOW ? 3 : 5);
499             if (tnsInfo->order[i][j]) {
500               FDKwriteBits(hBitStream, tnsInfo->direction[i][j], 1);
501               tnsBits += 1; /*direction*/
502               if (tnsInfo->coefRes[i] == 4) {
503                 coefBits = 3;
504                 for (k = 0; k < tnsInfo->order[i][j]; k++) {
505                   if (tnsInfo->coef[i][j][k] > 3 ||
506                       tnsInfo->coef[i][j][k] < -4) {
507                     coefBits = 4;
508                     break;
509                   }
510                 }
511               } else {
512                 coefBits = 2;
513                 for (k = 0; k < tnsInfo->order[i][j]; k++) {
514                   if (tnsInfo->coef[i][j][k] > 1 ||
515                       tnsInfo->coef[i][j][k] < -2) {
516                     coefBits = 3;
517                     break;
518                   }
519                 }
520               }
521               FDKwriteBits(hBitStream, -(coefBits - tnsInfo->coefRes[i]),
522                            1); /*coef_compres*/
523               tnsBits += 1;    /*coef_compression */
524               for (k = 0; k < tnsInfo->order[i][j]; k++) {
525                 static const INT rmask[] = {0, 1, 3, 7, 15};
526                 FDKwriteBits(hBitStream,
527                              tnsInfo->coef[i][j][k] & rmask[coefBits],
528                              coefBits);
529                 tnsBits += coefBits;
530               }
531             }
532           }
533         }
534       }
535     } else {
536       if (tnsPresent != 0) {
537         for (i = 0; i < numOfWindows; i++) {
538           tnsBits += (blockType == SHORT_WINDOW ? 1 : 2);
539           if (tnsInfo->numOfFilters[i]) {
540             tnsBits += 1;
541             for (j = 0; j < tnsInfo->numOfFilters[i]; j++) {
542               tnsBits += (blockType == SHORT_WINDOW ? 4 : 6);
543               tnsBits += (blockType == SHORT_WINDOW ? 3 : 5);
544               if (tnsInfo->order[i][j]) {
545                 tnsBits += 1; /*direction*/
546                 tnsBits += 1; /*coef_compression */
547                 if (tnsInfo->coefRes[i] == 4) {
548                   coefBits = 3;
549                   for (k = 0; k < tnsInfo->order[i][j]; k++) {
550                     if (tnsInfo->coef[i][j][k] > 3 ||
551                         tnsInfo->coef[i][j][k] < -4) {
552                       coefBits = 4;
553                       break;
554                     }
555                   }
556                 } else {
557                   coefBits = 2;
558                   for (k = 0; k < tnsInfo->order[i][j]; k++) {
559                     if (tnsInfo->coef[i][j][k] > 1 ||
560                         tnsInfo->coef[i][j][k] < -2) {
561                       coefBits = 3;
562                       break;
563                     }
564                   }
565                 }
566                 for (k = 0; k < tnsInfo->order[i][j]; k++) {
567                   tnsBits += coefBits;
568                 }
569               }
570             }
571           }
572         }
573       }
574     }
575   } /* (tnsInfo!=NULL) */
576 
577   return (tnsBits);
578 }
579 
580 /*****************************************************************************
581 
582     functionname: FDKaacEnc_encodeGainControlData
583     description:  unsupported
584     returns:      none
585     input:
586     output:
587 
588 *****************************************************************************/
FDKaacEnc_encodeGainControlData(HANDLE_FDK_BITSTREAM hBitStream)589 static INT FDKaacEnc_encodeGainControlData(HANDLE_FDK_BITSTREAM hBitStream) {
590   if (hBitStream != NULL) {
591     FDKwriteBits(hBitStream, 0, 1);
592   }
593   return (1);
594 }
595 
596 /*****************************************************************************
597 
598     functionname: FDKaacEnc_encodePulseData
599     description:  not supported yet (dummy)
600     returns:      none
601     input:
602     output:
603 
604 *****************************************************************************/
FDKaacEnc_encodePulseData(HANDLE_FDK_BITSTREAM hBitStream)605 static INT FDKaacEnc_encodePulseData(HANDLE_FDK_BITSTREAM hBitStream) {
606   if (hBitStream != NULL) {
607     FDKwriteBits(hBitStream, 0, 1);
608   }
609   return (1);
610 }
611 
612 /*****************************************************************************
613 
614     functionname: FDKaacEnc_writeExtensionPayload
615     description:  write extension payload to bitstream
616     returns:      number of written bits
617     input:
618     output:
619 
620 *****************************************************************************/
FDKaacEnc_writeExtensionPayload(HANDLE_FDK_BITSTREAM hBitStream,EXT_PAYLOAD_TYPE extPayloadType,const UCHAR * extPayloadData,INT extPayloadBits)621 static INT FDKaacEnc_writeExtensionPayload(HANDLE_FDK_BITSTREAM hBitStream,
622                                            EXT_PAYLOAD_TYPE extPayloadType,
623                                            const UCHAR *extPayloadData,
624                                            INT extPayloadBits) {
625 #define EXT_TYPE_BITS (4)
626 #define DATA_EL_VERSION_BITS (4)
627 #define FILL_NIBBLE_BITS (4)
628 
629   INT extBitsUsed = 0;
630 
631   if (extPayloadBits >= EXT_TYPE_BITS) {
632     UCHAR fillByte = 0x00; /* for EXT_FIL and EXT_FILL_DATA */
633 
634     if (hBitStream != NULL) {
635       FDKwriteBits(hBitStream, extPayloadType, EXT_TYPE_BITS);
636     }
637     extBitsUsed += EXT_TYPE_BITS;
638 
639     switch (extPayloadType) {
640       /* case EXT_SAC_DATA: */
641       case EXT_LDSAC_DATA:
642         if (hBitStream != NULL) {
643           FDKwriteBits(hBitStream, *extPayloadData++, 4); /* nibble */
644         }
645         extBitsUsed += 4;
646         FDK_FALLTHROUGH;
647       case EXT_DYNAMIC_RANGE:
648       case EXT_SBR_DATA:
649       case EXT_SBR_DATA_CRC:
650         if (hBitStream != NULL) {
651           int i, writeBits = extPayloadBits;
652           for (i = 0; writeBits >= 8; i++) {
653             FDKwriteBits(hBitStream, *extPayloadData++, 8);
654             writeBits -= 8;
655           }
656           if (writeBits > 0) {
657             FDKwriteBits(hBitStream, (*extPayloadData) >> (8 - writeBits),
658                          writeBits);
659           }
660         }
661         extBitsUsed += extPayloadBits;
662         break;
663 
664       case EXT_DATA_ELEMENT: {
665         INT dataElementLength = (extPayloadBits + 7) >> 3;
666         INT cnt = dataElementLength;
667         int loopCounter = 1;
668 
669         while (dataElementLength >= 255) {
670           loopCounter++;
671           dataElementLength -= 255;
672         }
673 
674         if (hBitStream != NULL) {
675           int i;
676           FDKwriteBits(
677               hBitStream, 0x00,
678               DATA_EL_VERSION_BITS); /* data_element_version = ANC_DATA */
679 
680           for (i = 1; i < loopCounter; i++) {
681             FDKwriteBits(hBitStream, 255, 8);
682           }
683           FDKwriteBits(hBitStream, dataElementLength, 8);
684 
685           for (i = 0; i < cnt; i++) {
686             FDKwriteBits(hBitStream, extPayloadData[i], 8);
687           }
688         }
689         extBitsUsed += DATA_EL_VERSION_BITS + (loopCounter * 8) + (cnt * 8);
690       } break;
691 
692       case EXT_FILL_DATA:
693         fillByte = 0xA5;
694         FDK_FALLTHROUGH;
695       case EXT_FIL:
696       default:
697         if (hBitStream != NULL) {
698           int writeBits = extPayloadBits;
699           FDKwriteBits(hBitStream, 0x00, FILL_NIBBLE_BITS);
700           writeBits -=
701               8; /* acount for the extension type and the fill nibble */
702           while (writeBits >= 8) {
703             FDKwriteBits(hBitStream, fillByte, 8);
704             writeBits -= 8;
705           }
706         }
707         extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8;
708         break;
709     }
710   }
711 
712   return (extBitsUsed);
713 }
714 
715 /*****************************************************************************
716 
717     functionname: FDKaacEnc_writeDataStreamElement
718     description:  write data stream elements like ancillary data ...
719     returns:      the amount of used bits
720     input:
721     output:
722 
723 ******************************************************************************/
FDKaacEnc_writeDataStreamElement(HANDLE_TRANSPORTENC hTpEnc,INT elementInstanceTag,INT dataPayloadBytes,UCHAR * dataBuffer,UINT alignAnchor)724 static INT FDKaacEnc_writeDataStreamElement(HANDLE_TRANSPORTENC hTpEnc,
725                                             INT elementInstanceTag,
726                                             INT dataPayloadBytes,
727                                             UCHAR *dataBuffer,
728                                             UINT alignAnchor) {
729 #define DATA_BYTE_ALIGN_FLAG (0)
730 
731 #define EL_INSTANCE_TAG_BITS (4)
732 #define DATA_BYTE_ALIGN_FLAG_BITS (1)
733 #define DATA_LEN_COUNT_BITS (8)
734 #define DATA_LEN_ESC_COUNT_BITS (8)
735 
736 #define MAX_DATA_ALIGN_BITS (7)
737 #define MAX_DSE_DATA_BYTES (510)
738 
739   INT dseBitsUsed = 0;
740 
741   while (dataPayloadBytes > 0) {
742     int esc_count = -1;
743     int cnt = 0;
744     INT crcReg = -1;
745 
746     dseBitsUsed += EL_ID_BITS + EL_INSTANCE_TAG_BITS +
747                    DATA_BYTE_ALIGN_FLAG_BITS + DATA_LEN_COUNT_BITS;
748 
749     if (DATA_BYTE_ALIGN_FLAG) {
750       dseBitsUsed += MAX_DATA_ALIGN_BITS;
751     }
752 
753     cnt = fixMin(MAX_DSE_DATA_BYTES, dataPayloadBytes);
754     if (cnt >= 255) {
755       esc_count = cnt - 255;
756       dseBitsUsed += DATA_LEN_ESC_COUNT_BITS;
757     }
758 
759     dataPayloadBytes -= cnt;
760     dseBitsUsed += cnt * 8;
761 
762     if (hTpEnc != NULL) {
763       HANDLE_FDK_BITSTREAM hBitStream = transportEnc_GetBitstream(hTpEnc);
764       int i;
765 
766       FDKwriteBits(hBitStream, ID_DSE, EL_ID_BITS);
767 
768       crcReg = transportEnc_CrcStartReg(hTpEnc, 0);
769 
770       FDKwriteBits(hBitStream, elementInstanceTag, EL_INSTANCE_TAG_BITS);
771       FDKwriteBits(hBitStream, DATA_BYTE_ALIGN_FLAG, DATA_BYTE_ALIGN_FLAG_BITS);
772 
773       /* write length field(s) */
774       if (esc_count >= 0) {
775         FDKwriteBits(hBitStream, 255, DATA_LEN_COUNT_BITS);
776         FDKwriteBits(hBitStream, esc_count, DATA_LEN_ESC_COUNT_BITS);
777       } else {
778         FDKwriteBits(hBitStream, cnt, DATA_LEN_COUNT_BITS);
779       }
780 
781       if (DATA_BYTE_ALIGN_FLAG) {
782         INT tmp = (INT)FDKgetValidBits(hBitStream);
783         FDKbyteAlign(hBitStream, alignAnchor);
784         /* count actual bits */
785         dseBitsUsed +=
786             (INT)FDKgetValidBits(hBitStream) - tmp - MAX_DATA_ALIGN_BITS;
787       }
788 
789       /* write payload */
790       for (i = 0; i < cnt; i++) {
791         FDKwriteBits(hBitStream, dataBuffer[i], 8);
792       }
793       transportEnc_CrcEndReg(hTpEnc, crcReg);
794     }
795   }
796 
797   return (dseBitsUsed);
798 }
799 
800 /*****************************************************************************
801 
802     functionname: FDKaacEnc_writeExtensionData
803     description:  write extension payload to bitstream
804     returns:      number of written bits
805     input:
806     output:
807 
808 *****************************************************************************/
FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc,QC_OUT_EXTENSION * pExtension,INT elInstanceTag,UINT alignAnchor,UINT syntaxFlags,AUDIO_OBJECT_TYPE aot,SCHAR epConfig)809 INT FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc,
810                                  QC_OUT_EXTENSION *pExtension,
811                                  INT elInstanceTag, /* for DSE only */
812                                  UINT alignAnchor,  /* for DSE only */
813                                  UINT syntaxFlags, AUDIO_OBJECT_TYPE aot,
814                                  SCHAR epConfig) {
815 #define FILL_EL_COUNT_BITS (4)
816 #define FILL_EL_ESC_COUNT_BITS (8)
817 #define MAX_FILL_DATA_BYTES (269)
818 
819   HANDLE_FDK_BITSTREAM hBitStream = NULL;
820   INT payloadBits = pExtension->nPayloadBits;
821   INT extBitsUsed = 0;
822 
823   if (hTpEnc != NULL) {
824     hBitStream = transportEnc_GetBitstream(hTpEnc);
825   }
826 
827   if (syntaxFlags & (AC_SCALABLE | AC_ER)) {
828     {
829       if ((syntaxFlags & AC_ELD) && ((pExtension->type == EXT_SBR_DATA) ||
830                                      (pExtension->type == EXT_SBR_DATA_CRC))) {
831         if (hBitStream != NULL) {
832           int i, writeBits = payloadBits;
833           UCHAR *extPayloadData = pExtension->pPayload;
834 
835           for (i = 0; writeBits >= 8; i++) {
836             FDKwriteBits(hBitStream, extPayloadData[i], 8);
837             writeBits -= 8;
838           }
839           if (writeBits > 0) {
840             FDKwriteBits(hBitStream, extPayloadData[i] >> (8 - writeBits),
841                          writeBits);
842           }
843         }
844         extBitsUsed += payloadBits;
845       } else {
846         /* ER or scalable syntax -> write extension en bloc */
847         extBitsUsed += FDKaacEnc_writeExtensionPayload(
848             hBitStream, pExtension->type, pExtension->pPayload, payloadBits);
849       }
850     }
851   } else {
852     /* We have normal GA bitstream payload (AOT 2,5,29) so pack
853        the data into a fill elements or DSEs */
854 
855     if (pExtension->type == EXT_DATA_ELEMENT) {
856       extBitsUsed += FDKaacEnc_writeDataStreamElement(
857           hTpEnc, elInstanceTag, pExtension->nPayloadBits >> 3,
858           pExtension->pPayload, alignAnchor);
859     } else {
860       while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) {
861         INT cnt, esc_count = -1, alignBits = 7;
862 
863         if ((pExtension->type == EXT_FILL_DATA) ||
864             (pExtension->type == EXT_FIL)) {
865           payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS;
866           if (payloadBits >= 15 * 8) {
867             payloadBits -= FILL_EL_ESC_COUNT_BITS;
868             esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */
869           }
870           alignBits = 0;
871         }
872 
873         cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits + alignBits) >> 3);
874 
875         if (cnt >= 15) {
876           esc_count = cnt - 15 + 1;
877         }
878 
879         if (hBitStream != NULL) {
880           /* write bitstream */
881           FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS);
882           if (esc_count >= 0) {
883             FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS);
884             FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS);
885           } else {
886             FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS);
887           }
888         }
889 
890         extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS +
891                        ((esc_count >= 0) ? FILL_EL_ESC_COUNT_BITS : 0);
892 
893         cnt = fixMin(cnt * 8, payloadBits); /* convert back to bits */
894         extBitsUsed += FDKaacEnc_writeExtensionPayload(
895             hBitStream, pExtension->type, pExtension->pPayload, cnt);
896         payloadBits -= cnt;
897       }
898     }
899   }
900 
901   return (extBitsUsed);
902 }
903 
904 /*****************************************************************************
905 
906     functionname: FDKaacEnc_ByteAlignment
907     description:
908     returns:
909     input:
910     output:
911 
912 *****************************************************************************/
FDKaacEnc_ByteAlignment(HANDLE_FDK_BITSTREAM hBitStream,int alignBits)913 static void FDKaacEnc_ByteAlignment(HANDLE_FDK_BITSTREAM hBitStream,
914                                     int alignBits) {
915   FDKwriteBits(hBitStream, 0, alignBits);
916 }
917 
FDKaacEnc_ChannelElementWrite(HANDLE_TRANSPORTENC hTpEnc,ELEMENT_INFO * pElInfo,QC_OUT_CHANNEL * qcOutChannel[(2)],PSY_OUT_ELEMENT * psyOutElement,PSY_OUT_CHANNEL * psyOutChannel[(2)],UINT syntaxFlags,AUDIO_OBJECT_TYPE aot,SCHAR epConfig,INT * pBitDemand,UCHAR minCnt)918 AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite(
919     HANDLE_TRANSPORTENC hTpEnc, ELEMENT_INFO *pElInfo,
920     QC_OUT_CHANNEL *qcOutChannel[(2)], PSY_OUT_ELEMENT *psyOutElement,
921     PSY_OUT_CHANNEL *psyOutChannel[(2)], UINT syntaxFlags,
922     AUDIO_OBJECT_TYPE aot, SCHAR epConfig, INT *pBitDemand, UCHAR minCnt) {
923   AAC_ENCODER_ERROR error = AAC_ENC_OK;
924   HANDLE_FDK_BITSTREAM hBitStream = NULL;
925   INT bitDemand = 0;
926   const element_list_t *list;
927   int i, ch, decision_bit;
928   INT crcReg1 = -1, crcReg2 = -1;
929   UCHAR numberOfChannels;
930 
931   if (hTpEnc != NULL) {
932     /* Get bitstream handle */
933     hBitStream = transportEnc_GetBitstream(hTpEnc);
934   }
935 
936   if ((pElInfo->elType == ID_SCE) || (pElInfo->elType == ID_LFE)) {
937     numberOfChannels = 1;
938   } else {
939     numberOfChannels = 2;
940   }
941 
942   /* Get channel element sequence table */
943   list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0, 0);
944   if (list == NULL) {
945     error = AAC_ENC_UNSUPPORTED_AOT;
946     goto bail;
947   }
948 
949   if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) {
950     if (hBitStream != NULL) {
951       FDKwriteBits(hBitStream, pElInfo->elType, EL_ID_BITS);
952     }
953     bitDemand += EL_ID_BITS;
954   }
955 
956   /* Iterate through sequence table */
957   i = 0;
958   ch = 0;
959   decision_bit = 0;
960   do {
961     /* some tmp values */
962     SECTION_DATA *pChSectionData = NULL;
963     INT *pChScf = NULL;
964     UINT *pChMaxValueInSfb = NULL;
965     TNS_INFO *pTnsInfo = NULL;
966     INT chGlobalGain = 0;
967     INT chBlockType = 0;
968     INT chMaxSfbPerGrp = 0;
969     INT chSfbPerGrp = 0;
970     INT chSfbCnt = 0;
971     INT chFirstScf = 0;
972 
973     if (minCnt == 0) {
974       if (qcOutChannel != NULL) {
975         pChSectionData = &(qcOutChannel[ch]->sectionData);
976         pChScf = qcOutChannel[ch]->scf;
977         chGlobalGain = qcOutChannel[ch]->globalGain;
978         pChMaxValueInSfb = qcOutChannel[ch]->maxValueInSfb;
979         chBlockType = pChSectionData->blockType;
980         chMaxSfbPerGrp = pChSectionData->maxSfbPerGroup;
981         chSfbPerGrp = pChSectionData->sfbPerGroup;
982         chSfbCnt = pChSectionData->sfbCnt;
983         chFirstScf = pChScf[pChSectionData->firstScf];
984       } else {
985         /* get values from PSY */
986         chSfbCnt = psyOutChannel[ch]->sfbCnt;
987         chSfbPerGrp = psyOutChannel[ch]->sfbPerGroup;
988         chMaxSfbPerGrp = psyOutChannel[ch]->maxSfbPerGroup;
989       }
990       pTnsInfo = &psyOutChannel[ch]->tnsInfo;
991     } /* minCnt==0 */
992 
993     if (qcOutChannel == NULL) {
994       chBlockType = psyOutChannel[ch]->lastWindowSequence;
995     }
996 
997     switch (list->id[i]) {
998       case element_instance_tag:
999         /* Write element instance tag */
1000         if (hBitStream != NULL) {
1001           FDKwriteBits(hBitStream, pElInfo->instanceTag, 4);
1002         }
1003         bitDemand += 4;
1004         break;
1005 
1006       case common_window:
1007         /* Write common window flag */
1008         decision_bit = psyOutElement->commonWindow;
1009         if (hBitStream != NULL) {
1010           FDKwriteBits(hBitStream, psyOutElement->commonWindow, 1);
1011         }
1012         bitDemand += 1;
1013         break;
1014 
1015       case ics_info:
1016         /* Write individual channel info */
1017         bitDemand +=
1018             FDKaacEnc_encodeIcsInfo(chBlockType, psyOutChannel[ch]->windowShape,
1019                                     psyOutChannel[ch]->groupingMask,
1020                                     chMaxSfbPerGrp, hBitStream, syntaxFlags);
1021         break;
1022 
1023       case ltp_data_present:
1024         /* Write LTP data present flag */
1025         if (hBitStream != NULL) {
1026           FDKwriteBits(hBitStream, 0, 1);
1027         }
1028         bitDemand += 1;
1029         break;
1030 
1031       case ltp_data:
1032         /* Predictor data not supported.
1033            Nothing to do here. */
1034         break;
1035 
1036       case ms:
1037         /* Write MS info */
1038         bitDemand += FDKaacEnc_encodeMSInfo(
1039             chSfbCnt, chSfbPerGrp, chMaxSfbPerGrp,
1040             (minCnt == 0) ? psyOutElement->toolsInfo.msDigest : MS_NONE,
1041             psyOutElement->toolsInfo.msMask, hBitStream);
1042         break;
1043 
1044       case global_gain:
1045         bitDemand += FDKaacEnc_encodeGlobalGain(
1046             chGlobalGain, chFirstScf, hBitStream, psyOutChannel[ch]->mdctScale);
1047         break;
1048 
1049       case section_data: {
1050         INT siBits = FDKaacEnc_encodeSectionData(
1051             pChSectionData, hBitStream, (syntaxFlags & AC_ER_VCB11) ? 1 : 0);
1052         if (hBitStream != NULL) {
1053           if (siBits != qcOutChannel[ch]->sectionData.sideInfoBits) {
1054             error = AAC_ENC_WRITE_SEC_ERROR;
1055           }
1056         }
1057         bitDemand += siBits;
1058       } break;
1059 
1060       case scale_factor_data: {
1061         INT sfDataBits = FDKaacEnc_encodeScaleFactorData(
1062             pChMaxValueInSfb, pChSectionData, pChScf, hBitStream,
1063             psyOutChannel[ch]->noiseNrg, psyOutChannel[ch]->isScale,
1064             chGlobalGain);
1065         if ((hBitStream != NULL) &&
1066             (sfDataBits != (qcOutChannel[ch]->sectionData.scalefacBits +
1067                             qcOutChannel[ch]->sectionData.noiseNrgBits))) {
1068           error = AAC_ENC_WRITE_SCAL_ERROR;
1069         }
1070         bitDemand += sfDataBits;
1071       } break;
1072 
1073       case esc2_rvlc:
1074         if (syntaxFlags & AC_ER_RVLC) {
1075           /* write RVLC data into bitstream (error sens. cat. 2) */
1076           error = AAC_ENC_UNSUPPORTED_AOT;
1077         }
1078         break;
1079 
1080       case pulse:
1081         /* Write pulse data */
1082         bitDemand += FDKaacEnc_encodePulseData(hBitStream);
1083         break;
1084 
1085       case tns_data_present:
1086         /* Write TNS data present flag */
1087         bitDemand +=
1088             FDKaacEnc_encodeTnsDataPresent(pTnsInfo, chBlockType, hBitStream);
1089         break;
1090       case tns_data:
1091         /* Write TNS data */
1092         bitDemand += FDKaacEnc_encodeTnsData(pTnsInfo, chBlockType, hBitStream);
1093         break;
1094 
1095       case gain_control_data:
1096         /* Nothing to do here */
1097         break;
1098 
1099       case gain_control_data_present:
1100         bitDemand += FDKaacEnc_encodeGainControlData(hBitStream);
1101         break;
1102 
1103       case esc1_hcr:
1104         if (syntaxFlags & AC_ER_HCR) {
1105           error = AAC_ENC_UNKNOWN;
1106         }
1107         break;
1108 
1109       case spectral_data:
1110         if (hBitStream != NULL) {
1111           INT spectralBits = 0;
1112 
1113           spectralBits = FDKaacEnc_encodeSpectralData(
1114               psyOutChannel[ch]->sfbOffsets, pChSectionData,
1115               qcOutChannel[ch]->quantSpec, hBitStream);
1116 
1117           if (spectralBits != qcOutChannel[ch]->sectionData.huffmanBits) {
1118             return AAC_ENC_WRITE_SPEC_ERROR;
1119           }
1120           bitDemand += spectralBits;
1121         }
1122         break;
1123 
1124         /* Non data cases */
1125       case adtscrc_start_reg1:
1126         if (hTpEnc != NULL) {
1127           crcReg1 = transportEnc_CrcStartReg(hTpEnc, 192);
1128         }
1129         break;
1130       case adtscrc_start_reg2:
1131         if (hTpEnc != NULL) {
1132           crcReg2 = transportEnc_CrcStartReg(hTpEnc, 128);
1133         }
1134         break;
1135       case adtscrc_end_reg1:
1136       case drmcrc_end_reg:
1137         if (hTpEnc != NULL) {
1138           transportEnc_CrcEndReg(hTpEnc, crcReg1);
1139         }
1140         break;
1141       case adtscrc_end_reg2:
1142         if (hTpEnc != NULL) {
1143           transportEnc_CrcEndReg(hTpEnc, crcReg2);
1144         }
1145         break;
1146       case drmcrc_start_reg:
1147         if (hTpEnc != NULL) {
1148           crcReg1 = transportEnc_CrcStartReg(hTpEnc, 0);
1149         }
1150         break;
1151       case next_channel:
1152         ch = (ch + 1) % numberOfChannels;
1153         break;
1154       case link_sequence:
1155         list = list->next[decision_bit];
1156         i = -1;
1157         break;
1158 
1159       default:
1160         error = AAC_ENC_UNKNOWN;
1161         break;
1162     }
1163 
1164     if (error != AAC_ENC_OK) {
1165       return error;
1166     }
1167 
1168     i++;
1169 
1170   } while (list->id[i] != end_of_sequence);
1171 
1172 bail:
1173   if (pBitDemand != NULL) {
1174     *pBitDemand = bitDemand;
1175   }
1176 
1177   return error;
1178 }
1179 
1180 //-----------------------------------------------------------------------------------------------
1181 
FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc,CHANNEL_MAPPING * channelMapping,QC_OUT * qcOut,PSY_OUT * psyOut,QC_STATE * qcKernel,AUDIO_OBJECT_TYPE aot,UINT syntaxFlags,SCHAR epConfig)1182 AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc,
1183                                            CHANNEL_MAPPING *channelMapping,
1184                                            QC_OUT *qcOut, PSY_OUT *psyOut,
1185                                            QC_STATE *qcKernel,
1186                                            AUDIO_OBJECT_TYPE aot,
1187                                            UINT syntaxFlags, SCHAR epConfig) {
1188   HANDLE_FDK_BITSTREAM hBs = transportEnc_GetBitstream(hTpEnc);
1189   AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK;
1190   int i, n, doByteAlign = 1;
1191   INT bitMarkUp;
1192   INT frameBits;
1193   /* Get first bit of raw data block.
1194      In case of ADTS+PCE, AU would start at PCE.
1195      This is okay because PCE assures alignment. */
1196   UINT alignAnchor = FDKgetValidBits(hBs);
1197 
1198   frameBits = bitMarkUp = alignAnchor;
1199 
1200   /* Channel element loop */
1201   for (i = 0; i < channelMapping->nElements; i++) {
1202     ELEMENT_INFO elInfo = channelMapping->elInfo[i];
1203     INT elementUsedBits = 0;
1204 
1205     switch (elInfo.elType) {
1206       case ID_SCE: /* single channel */
1207       case ID_CPE: /* channel pair */
1208       case ID_LFE: /* low freq effects channel */
1209       {
1210         if (AAC_ENC_OK !=
1211             (ErrorStatus = FDKaacEnc_ChannelElementWrite(
1212                  hTpEnc, &elInfo, qcOut->qcElement[i]->qcOutChannel,
1213                  psyOut->psyOutElement[i],
1214                  psyOut->psyOutElement[i]->psyOutChannel,
1215                  syntaxFlags, /* syntaxFlags (ER tools ...) */
1216                  aot,         /* aot: AOT_AAC_LC, AOT_SBR, AOT_PS */
1217                  epConfig,    /* epConfig -1, 0, 1 */
1218                  NULL, 0))) {
1219           return ErrorStatus;
1220         }
1221 
1222         if (!(syntaxFlags & AC_ER)) {
1223           /* Write associated extension payload */
1224           for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) {
1225             FDKaacEnc_writeExtensionData(
1226                 hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor,
1227                 syntaxFlags, aot, epConfig);
1228           }
1229         }
1230       } break;
1231 
1232       /* In FDK, DSE signalling explicit done in elDSE. See channel_map.cpp */
1233       default:
1234         return AAC_ENC_INVALID_ELEMENTINFO_TYPE;
1235 
1236     } /* switch */
1237 
1238     if (elInfo.elType != ID_DSE) {
1239       elementUsedBits -= bitMarkUp;
1240       bitMarkUp = FDKgetValidBits(hBs);
1241       elementUsedBits += bitMarkUp;
1242       frameBits += elementUsedBits;
1243     }
1244 
1245   } /* for (i=0; i<channelMapping.nElements; i++) */
1246 
1247   if ((syntaxFlags & AC_ER) && !(syntaxFlags & AC_DRM)) {
1248     UCHAR channelElementExtensionWritten[((8))][(
1249         1)]; /* 0: extension not touched, 1: extension already written */
1250 
1251     FDKmemclear(channelElementExtensionWritten,
1252                 sizeof(channelElementExtensionWritten));
1253 
1254     if (syntaxFlags & AC_ELD) {
1255       for (i = 0; i < channelMapping->nElements; i++) {
1256         for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) {
1257           if ((qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA) ||
1258               (qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA_CRC)) {
1259             /* Write sbr extension payload */
1260             FDKaacEnc_writeExtensionData(
1261                 hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor,
1262                 syntaxFlags, aot, epConfig);
1263 
1264             channelElementExtensionWritten[i][n] = 1;
1265           } /* SBR */
1266         }   /* n */
1267       }     /* i */
1268     }       /* AC_ELD */
1269 
1270     for (i = 0; i < channelMapping->nElements; i++) {
1271       for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) {
1272         if (channelElementExtensionWritten[i][n] == 0) {
1273           /* Write all ramaining extension payloads in element */
1274           FDKaacEnc_writeExtensionData(hTpEnc,
1275                                        &qcOut->qcElement[i]->extension[n], 0,
1276                                        alignAnchor, syntaxFlags, aot, epConfig);
1277         }
1278       } /* n */
1279     }   /* i */
1280   }     /* if AC_ER */
1281 
1282   /* Extend global extension payload table with fill bits */
1283   n = qcOut->nExtensions;
1284 
1285   /* Add fill data / stuffing bits */
1286   qcOut->extension[n].type = EXT_FILL_DATA;
1287   qcOut->extension[n].nPayloadBits = qcOut->totFillBits;
1288   qcOut->nExtensions++;
1289 
1290   /* Write global extension payload and fill data */
1291   for (n = 0; (n < qcOut->nExtensions) && (n < (2 + 2)); n++) {
1292     FDKaacEnc_writeExtensionData(hTpEnc, &qcOut->extension[n], 0, alignAnchor,
1293                                  syntaxFlags, aot, epConfig);
1294 
1295     /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here
1296      */
1297   }
1298 
1299   if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) {
1300     FDKwriteBits(hBs, ID_END, EL_ID_BITS);
1301   }
1302 
1303   if (doByteAlign) {
1304     /* Assure byte alignment*/
1305     if (((FDKgetValidBits(hBs) - alignAnchor + qcOut->alignBits) & 0x7) != 0) {
1306       return AAC_ENC_WRITTEN_BITS_ERROR;
1307     }
1308 
1309     FDKaacEnc_ByteAlignment(hBs, qcOut->alignBits);
1310   }
1311 
1312   frameBits -= bitMarkUp;
1313   frameBits += FDKgetValidBits(hBs);
1314 
1315   transportEnc_EndAccessUnit(hTpEnc, &frameBits);
1316 
1317   if (frameBits != qcOut->totalBits + qcKernel->globHdrBits) {
1318     return AAC_ENC_WRITTEN_BITS_ERROR;
1319   }
1320 
1321   return ErrorStatus;
1322 }
1323