• 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       case EXT_DYNAMIC_RANGE:
647       case EXT_SBR_DATA:
648       case EXT_SBR_DATA_CRC:
649         if (hBitStream != NULL) {
650           int i, writeBits = extPayloadBits;
651           for (i = 0; writeBits >= 8; i++) {
652             FDKwriteBits(hBitStream, *extPayloadData++, 8);
653             writeBits -= 8;
654           }
655           if (writeBits > 0) {
656             FDKwriteBits(hBitStream, (*extPayloadData) >> (8 - writeBits),
657                          writeBits);
658           }
659         }
660         extBitsUsed += extPayloadBits;
661         break;
662 
663       case EXT_DATA_ELEMENT: {
664         INT dataElementLength = (extPayloadBits + 7) >> 3;
665         INT cnt = dataElementLength;
666         int loopCounter = 1;
667 
668         while (dataElementLength >= 255) {
669           loopCounter++;
670           dataElementLength -= 255;
671         }
672 
673         if (hBitStream != NULL) {
674           int i;
675           FDKwriteBits(
676               hBitStream, 0x00,
677               DATA_EL_VERSION_BITS); /* data_element_version = ANC_DATA */
678 
679           for (i = 1; i < loopCounter; i++) {
680             FDKwriteBits(hBitStream, 255, 8);
681           }
682           FDKwriteBits(hBitStream, dataElementLength, 8);
683 
684           for (i = 0; i < cnt; i++) {
685             FDKwriteBits(hBitStream, extPayloadData[i], 8);
686           }
687         }
688         extBitsUsed += DATA_EL_VERSION_BITS + (loopCounter * 8) + (cnt * 8);
689       } break;
690 
691       case EXT_FILL_DATA:
692         fillByte = 0xA5;
693       case EXT_FIL:
694       default:
695         if (hBitStream != NULL) {
696           int writeBits = extPayloadBits;
697           FDKwriteBits(hBitStream, 0x00, FILL_NIBBLE_BITS);
698           writeBits -=
699               8; /* acount for the extension type and the fill nibble */
700           while (writeBits >= 8) {
701             FDKwriteBits(hBitStream, fillByte, 8);
702             writeBits -= 8;
703           }
704         }
705         extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8;
706         break;
707     }
708   }
709 
710   return (extBitsUsed);
711 }
712 
713 /*****************************************************************************
714 
715     functionname: FDKaacEnc_writeDataStreamElement
716     description:  write data stream elements like ancillary data ...
717     returns:      the amount of used bits
718     input:
719     output:
720 
721 ******************************************************************************/
FDKaacEnc_writeDataStreamElement(HANDLE_TRANSPORTENC hTpEnc,INT elementInstanceTag,INT dataPayloadBytes,UCHAR * dataBuffer,UINT alignAnchor)722 static INT FDKaacEnc_writeDataStreamElement(HANDLE_TRANSPORTENC hTpEnc,
723                                             INT elementInstanceTag,
724                                             INT dataPayloadBytes,
725                                             UCHAR *dataBuffer,
726                                             UINT alignAnchor) {
727 #define DATA_BYTE_ALIGN_FLAG (0)
728 
729 #define EL_INSTANCE_TAG_BITS (4)
730 #define DATA_BYTE_ALIGN_FLAG_BITS (1)
731 #define DATA_LEN_COUNT_BITS (8)
732 #define DATA_LEN_ESC_COUNT_BITS (8)
733 
734 #define MAX_DATA_ALIGN_BITS (7)
735 #define MAX_DSE_DATA_BYTES (510)
736 
737   INT dseBitsUsed = 0;
738 
739   while (dataPayloadBytes > 0) {
740     int esc_count = -1;
741     int cnt = 0;
742     INT crcReg = -1;
743 
744     dseBitsUsed += EL_ID_BITS + EL_INSTANCE_TAG_BITS +
745                    DATA_BYTE_ALIGN_FLAG_BITS + DATA_LEN_COUNT_BITS;
746 
747     if (DATA_BYTE_ALIGN_FLAG) {
748       dseBitsUsed += MAX_DATA_ALIGN_BITS;
749     }
750 
751     cnt = fixMin(MAX_DSE_DATA_BYTES, dataPayloadBytes);
752     if (cnt >= 255) {
753       esc_count = cnt - 255;
754       dseBitsUsed += DATA_LEN_ESC_COUNT_BITS;
755     }
756 
757     dataPayloadBytes -= cnt;
758     dseBitsUsed += cnt * 8;
759 
760     if (hTpEnc != NULL) {
761       HANDLE_FDK_BITSTREAM hBitStream = transportEnc_GetBitstream(hTpEnc);
762       int i;
763 
764       FDKwriteBits(hBitStream, ID_DSE, EL_ID_BITS);
765 
766       crcReg = transportEnc_CrcStartReg(hTpEnc, 0);
767 
768       FDKwriteBits(hBitStream, elementInstanceTag, EL_INSTANCE_TAG_BITS);
769       FDKwriteBits(hBitStream, DATA_BYTE_ALIGN_FLAG, DATA_BYTE_ALIGN_FLAG_BITS);
770 
771       /* write length field(s) */
772       if (esc_count >= 0) {
773         FDKwriteBits(hBitStream, 255, DATA_LEN_COUNT_BITS);
774         FDKwriteBits(hBitStream, esc_count, DATA_LEN_ESC_COUNT_BITS);
775       } else {
776         FDKwriteBits(hBitStream, cnt, DATA_LEN_COUNT_BITS);
777       }
778 
779       if (DATA_BYTE_ALIGN_FLAG) {
780         INT tmp = (INT)FDKgetValidBits(hBitStream);
781         FDKbyteAlign(hBitStream, alignAnchor);
782         /* count actual bits */
783         dseBitsUsed +=
784             (INT)FDKgetValidBits(hBitStream) - tmp - MAX_DATA_ALIGN_BITS;
785       }
786 
787       /* write payload */
788       for (i = 0; i < cnt; i++) {
789         FDKwriteBits(hBitStream, dataBuffer[i], 8);
790       }
791       transportEnc_CrcEndReg(hTpEnc, crcReg);
792     }
793   }
794 
795   return (dseBitsUsed);
796 }
797 
798 /*****************************************************************************
799 
800     functionname: FDKaacEnc_writeExtensionData
801     description:  write extension payload to bitstream
802     returns:      number of written bits
803     input:
804     output:
805 
806 *****************************************************************************/
FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc,QC_OUT_EXTENSION * pExtension,INT elInstanceTag,UINT alignAnchor,UINT syntaxFlags,AUDIO_OBJECT_TYPE aot,SCHAR epConfig)807 INT FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc,
808                                  QC_OUT_EXTENSION *pExtension,
809                                  INT elInstanceTag, /* for DSE only */
810                                  UINT alignAnchor,  /* for DSE only */
811                                  UINT syntaxFlags, AUDIO_OBJECT_TYPE aot,
812                                  SCHAR epConfig) {
813 #define FILL_EL_COUNT_BITS (4)
814 #define FILL_EL_ESC_COUNT_BITS (8)
815 #define MAX_FILL_DATA_BYTES (269)
816 
817   HANDLE_FDK_BITSTREAM hBitStream = NULL;
818   INT payloadBits = pExtension->nPayloadBits;
819   INT extBitsUsed = 0;
820 
821   if (hTpEnc != NULL) {
822     hBitStream = transportEnc_GetBitstream(hTpEnc);
823   }
824 
825   if (syntaxFlags & (AC_SCALABLE | AC_ER)) {
826     {
827       if ((syntaxFlags & AC_ELD) && ((pExtension->type == EXT_SBR_DATA) ||
828                                      (pExtension->type == EXT_SBR_DATA_CRC))) {
829         if (hBitStream != NULL) {
830           int i, writeBits = payloadBits;
831           UCHAR *extPayloadData = pExtension->pPayload;
832 
833           for (i = 0; writeBits >= 8; i++) {
834             FDKwriteBits(hBitStream, extPayloadData[i], 8);
835             writeBits -= 8;
836           }
837           if (writeBits > 0) {
838             FDKwriteBits(hBitStream, extPayloadData[i] >> (8 - writeBits),
839                          writeBits);
840           }
841         }
842         extBitsUsed += payloadBits;
843       } else {
844         /* ER or scalable syntax -> write extension en bloc */
845         extBitsUsed += FDKaacEnc_writeExtensionPayload(
846             hBitStream, pExtension->type, pExtension->pPayload, payloadBits);
847       }
848     }
849   } else {
850     /* We have normal GA bitstream payload (AOT 2,5,29) so pack
851        the data into a fill elements or DSEs */
852 
853     if (pExtension->type == EXT_DATA_ELEMENT) {
854       extBitsUsed += FDKaacEnc_writeDataStreamElement(
855           hTpEnc, elInstanceTag, pExtension->nPayloadBits >> 3,
856           pExtension->pPayload, alignAnchor);
857     } else {
858       while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) {
859         INT cnt, esc_count = -1, alignBits = 7;
860 
861         if ((pExtension->type == EXT_FILL_DATA) ||
862             (pExtension->type == EXT_FIL)) {
863           payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS;
864           if (payloadBits >= 15 * 8) {
865             payloadBits -= FILL_EL_ESC_COUNT_BITS;
866             esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */
867           }
868           alignBits = 0;
869         }
870 
871         cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits + alignBits) >> 3);
872 
873         if (cnt >= 15) {
874           esc_count = cnt - 15 + 1;
875         }
876 
877         if (hBitStream != NULL) {
878           /* write bitstream */
879           FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS);
880           if (esc_count >= 0) {
881             FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS);
882             FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS);
883           } else {
884             FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS);
885           }
886         }
887 
888         extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS +
889                        ((esc_count >= 0) ? FILL_EL_ESC_COUNT_BITS : 0);
890 
891         cnt = fixMin(cnt * 8, payloadBits); /* convert back to bits */
892         extBitsUsed += FDKaacEnc_writeExtensionPayload(
893             hBitStream, pExtension->type, pExtension->pPayload, cnt);
894         payloadBits -= cnt;
895       }
896     }
897   }
898 
899   return (extBitsUsed);
900 }
901 
902 /*****************************************************************************
903 
904     functionname: FDKaacEnc_ByteAlignment
905     description:
906     returns:
907     input:
908     output:
909 
910 *****************************************************************************/
FDKaacEnc_ByteAlignment(HANDLE_FDK_BITSTREAM hBitStream,int alignBits)911 static void FDKaacEnc_ByteAlignment(HANDLE_FDK_BITSTREAM hBitStream,
912                                     int alignBits) {
913   FDKwriteBits(hBitStream, 0, alignBits);
914 }
915 
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)916 AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite(
917     HANDLE_TRANSPORTENC hTpEnc, ELEMENT_INFO *pElInfo,
918     QC_OUT_CHANNEL *qcOutChannel[(2)], PSY_OUT_ELEMENT *psyOutElement,
919     PSY_OUT_CHANNEL *psyOutChannel[(2)], UINT syntaxFlags,
920     AUDIO_OBJECT_TYPE aot, SCHAR epConfig, INT *pBitDemand, UCHAR minCnt) {
921   AAC_ENCODER_ERROR error = AAC_ENC_OK;
922   HANDLE_FDK_BITSTREAM hBitStream = NULL;
923   INT bitDemand = 0;
924   const element_list_t *list;
925   int i, ch, decision_bit;
926   INT crcReg1 = -1, crcReg2 = -1;
927   UCHAR numberOfChannels;
928 
929   if (hTpEnc != NULL) {
930     /* Get bitstream handle */
931     hBitStream = transportEnc_GetBitstream(hTpEnc);
932   }
933 
934   if ((pElInfo->elType == ID_SCE) || (pElInfo->elType == ID_LFE)) {
935     numberOfChannels = 1;
936   } else {
937     numberOfChannels = 2;
938   }
939 
940   /* Get channel element sequence table */
941   list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0, 0);
942   if (list == NULL) {
943     error = AAC_ENC_UNSUPPORTED_AOT;
944     goto bail;
945   }
946 
947   if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) {
948     if (hBitStream != NULL) {
949       FDKwriteBits(hBitStream, pElInfo->elType, EL_ID_BITS);
950     }
951     bitDemand += EL_ID_BITS;
952   }
953 
954   /* Iterate through sequence table */
955   i = 0;
956   ch = 0;
957   decision_bit = 0;
958   do {
959     /* some tmp values */
960     SECTION_DATA *pChSectionData = NULL;
961     INT *pChScf = NULL;
962     UINT *pChMaxValueInSfb = NULL;
963     TNS_INFO *pTnsInfo = NULL;
964     INT chGlobalGain = 0;
965     INT chBlockType = 0;
966     INT chMaxSfbPerGrp = 0;
967     INT chSfbPerGrp = 0;
968     INT chSfbCnt = 0;
969     INT chFirstScf = 0;
970 
971     if (minCnt == 0) {
972       if (qcOutChannel != NULL) {
973         pChSectionData = &(qcOutChannel[ch]->sectionData);
974         pChScf = qcOutChannel[ch]->scf;
975         chGlobalGain = qcOutChannel[ch]->globalGain;
976         pChMaxValueInSfb = qcOutChannel[ch]->maxValueInSfb;
977         chBlockType = pChSectionData->blockType;
978         chMaxSfbPerGrp = pChSectionData->maxSfbPerGroup;
979         chSfbPerGrp = pChSectionData->sfbPerGroup;
980         chSfbCnt = pChSectionData->sfbCnt;
981         chFirstScf = pChScf[pChSectionData->firstScf];
982       } else {
983         /* get values from PSY */
984         chSfbCnt = psyOutChannel[ch]->sfbCnt;
985         chSfbPerGrp = psyOutChannel[ch]->sfbPerGroup;
986         chMaxSfbPerGrp = psyOutChannel[ch]->maxSfbPerGroup;
987       }
988       pTnsInfo = &psyOutChannel[ch]->tnsInfo;
989     } /* minCnt==0 */
990 
991     if (qcOutChannel == NULL) {
992       chBlockType = psyOutChannel[ch]->lastWindowSequence;
993     }
994 
995     switch (list->id[i]) {
996       case element_instance_tag:
997         /* Write element instance tag */
998         if (hBitStream != NULL) {
999           FDKwriteBits(hBitStream, pElInfo->instanceTag, 4);
1000         }
1001         bitDemand += 4;
1002         break;
1003 
1004       case common_window:
1005         /* Write common window flag */
1006         decision_bit = psyOutElement->commonWindow;
1007         if (hBitStream != NULL) {
1008           FDKwriteBits(hBitStream, psyOutElement->commonWindow, 1);
1009         }
1010         bitDemand += 1;
1011         break;
1012 
1013       case ics_info:
1014         /* Write individual channel info */
1015         bitDemand +=
1016             FDKaacEnc_encodeIcsInfo(chBlockType, psyOutChannel[ch]->windowShape,
1017                                     psyOutChannel[ch]->groupingMask,
1018                                     chMaxSfbPerGrp, hBitStream, syntaxFlags);
1019         break;
1020 
1021       case ltp_data_present:
1022         /* Write LTP data present flag */
1023         if (hBitStream != NULL) {
1024           FDKwriteBits(hBitStream, 0, 1);
1025         }
1026         bitDemand += 1;
1027         break;
1028 
1029       case ltp_data:
1030         /* Predictor data not supported.
1031            Nothing to do here. */
1032         break;
1033 
1034       case ms:
1035         /* Write MS info */
1036         bitDemand += FDKaacEnc_encodeMSInfo(
1037             chSfbCnt, chSfbPerGrp, chMaxSfbPerGrp,
1038             (minCnt == 0) ? psyOutElement->toolsInfo.msDigest : MS_NONE,
1039             psyOutElement->toolsInfo.msMask, hBitStream);
1040         break;
1041 
1042       case global_gain:
1043         bitDemand += FDKaacEnc_encodeGlobalGain(
1044             chGlobalGain, chFirstScf, hBitStream, psyOutChannel[ch]->mdctScale);
1045         break;
1046 
1047       case section_data: {
1048         INT siBits = FDKaacEnc_encodeSectionData(
1049             pChSectionData, hBitStream, (syntaxFlags & AC_ER_VCB11) ? 1 : 0);
1050         if (hBitStream != NULL) {
1051           if (siBits != qcOutChannel[ch]->sectionData.sideInfoBits) {
1052             error = AAC_ENC_WRITE_SEC_ERROR;
1053           }
1054         }
1055         bitDemand += siBits;
1056       } break;
1057 
1058       case scale_factor_data: {
1059         INT sfDataBits = FDKaacEnc_encodeScaleFactorData(
1060             pChMaxValueInSfb, pChSectionData, pChScf, hBitStream,
1061             psyOutChannel[ch]->noiseNrg, psyOutChannel[ch]->isScale,
1062             chGlobalGain);
1063         if ((hBitStream != NULL) &&
1064             (sfDataBits != (qcOutChannel[ch]->sectionData.scalefacBits +
1065                             qcOutChannel[ch]->sectionData.noiseNrgBits))) {
1066           error = AAC_ENC_WRITE_SCAL_ERROR;
1067         }
1068         bitDemand += sfDataBits;
1069       } break;
1070 
1071       case esc2_rvlc:
1072         if (syntaxFlags & AC_ER_RVLC) {
1073           /* write RVLC data into bitstream (error sens. cat. 2) */
1074           error = AAC_ENC_UNSUPPORTED_AOT;
1075         }
1076         break;
1077 
1078       case pulse:
1079         /* Write pulse data */
1080         bitDemand += FDKaacEnc_encodePulseData(hBitStream);
1081         break;
1082 
1083       case tns_data_present:
1084         /* Write TNS data present flag */
1085         bitDemand +=
1086             FDKaacEnc_encodeTnsDataPresent(pTnsInfo, chBlockType, hBitStream);
1087         break;
1088       case tns_data:
1089         /* Write TNS data */
1090         bitDemand += FDKaacEnc_encodeTnsData(pTnsInfo, chBlockType, hBitStream);
1091         break;
1092 
1093       case gain_control_data:
1094         /* Nothing to do here */
1095         break;
1096 
1097       case gain_control_data_present:
1098         bitDemand += FDKaacEnc_encodeGainControlData(hBitStream);
1099         break;
1100 
1101       case esc1_hcr:
1102         if (syntaxFlags & AC_ER_HCR) {
1103           error = AAC_ENC_UNKNOWN;
1104         }
1105         break;
1106 
1107       case spectral_data:
1108         if (hBitStream != NULL) {
1109           INT spectralBits = 0;
1110 
1111           spectralBits = FDKaacEnc_encodeSpectralData(
1112               psyOutChannel[ch]->sfbOffsets, pChSectionData,
1113               qcOutChannel[ch]->quantSpec, hBitStream);
1114 
1115           if (spectralBits != qcOutChannel[ch]->sectionData.huffmanBits) {
1116             return AAC_ENC_WRITE_SPEC_ERROR;
1117           }
1118           bitDemand += spectralBits;
1119         }
1120         break;
1121 
1122         /* Non data cases */
1123       case adtscrc_start_reg1:
1124         if (hTpEnc != NULL) {
1125           crcReg1 = transportEnc_CrcStartReg(hTpEnc, 192);
1126         }
1127         break;
1128       case adtscrc_start_reg2:
1129         if (hTpEnc != NULL) {
1130           crcReg2 = transportEnc_CrcStartReg(hTpEnc, 128);
1131         }
1132         break;
1133       case adtscrc_end_reg1:
1134       case drmcrc_end_reg:
1135         if (hTpEnc != NULL) {
1136           transportEnc_CrcEndReg(hTpEnc, crcReg1);
1137         }
1138         break;
1139       case adtscrc_end_reg2:
1140         if (hTpEnc != NULL) {
1141           transportEnc_CrcEndReg(hTpEnc, crcReg2);
1142         }
1143         break;
1144       case drmcrc_start_reg:
1145         if (hTpEnc != NULL) {
1146           crcReg1 = transportEnc_CrcStartReg(hTpEnc, 0);
1147         }
1148         break;
1149       case next_channel:
1150         ch = (ch + 1) % numberOfChannels;
1151         break;
1152       case link_sequence:
1153         list = list->next[decision_bit];
1154         i = -1;
1155         break;
1156 
1157       default:
1158         error = AAC_ENC_UNKNOWN;
1159         break;
1160     }
1161 
1162     if (error != AAC_ENC_OK) {
1163       return error;
1164     }
1165 
1166     i++;
1167 
1168   } while (list->id[i] != end_of_sequence);
1169 
1170 bail:
1171   if (pBitDemand != NULL) {
1172     *pBitDemand = bitDemand;
1173   }
1174 
1175   return error;
1176 }
1177 
1178 //-----------------------------------------------------------------------------------------------
1179 
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)1180 AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc,
1181                                            CHANNEL_MAPPING *channelMapping,
1182                                            QC_OUT *qcOut, PSY_OUT *psyOut,
1183                                            QC_STATE *qcKernel,
1184                                            AUDIO_OBJECT_TYPE aot,
1185                                            UINT syntaxFlags, SCHAR epConfig) {
1186   HANDLE_FDK_BITSTREAM hBs = transportEnc_GetBitstream(hTpEnc);
1187   AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK;
1188   int i, n, doByteAlign = 1;
1189   INT bitMarkUp;
1190   INT frameBits;
1191   /* Get first bit of raw data block.
1192      In case of ADTS+PCE, AU would start at PCE.
1193      This is okay because PCE assures alignment. */
1194   UINT alignAnchor = FDKgetValidBits(hBs);
1195 
1196   frameBits = bitMarkUp = alignAnchor;
1197 
1198   /* Channel element loop */
1199   for (i = 0; i < channelMapping->nElements; i++) {
1200     ELEMENT_INFO elInfo = channelMapping->elInfo[i];
1201     INT elementUsedBits = 0;
1202 
1203     switch (elInfo.elType) {
1204       case ID_SCE: /* single channel */
1205       case ID_CPE: /* channel pair */
1206       case ID_LFE: /* low freq effects channel */
1207       {
1208         if (AAC_ENC_OK !=
1209             (ErrorStatus = FDKaacEnc_ChannelElementWrite(
1210                  hTpEnc, &elInfo, qcOut->qcElement[i]->qcOutChannel,
1211                  psyOut->psyOutElement[i],
1212                  psyOut->psyOutElement[i]->psyOutChannel,
1213                  syntaxFlags, /* syntaxFlags (ER tools ...) */
1214                  aot,         /* aot: AOT_AAC_LC, AOT_SBR, AOT_PS */
1215                  epConfig,    /* epConfig -1, 0, 1 */
1216                  NULL, 0))) {
1217           return ErrorStatus;
1218         }
1219 
1220         if (!(syntaxFlags & AC_ER)) {
1221           /* Write associated extension payload */
1222           for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) {
1223             FDKaacEnc_writeExtensionData(
1224                 hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor,
1225                 syntaxFlags, aot, epConfig);
1226           }
1227         }
1228       } break;
1229 
1230       /* In FDK, DSE signalling explicit done in elDSE. See channel_map.cpp */
1231       default:
1232         return AAC_ENC_INVALID_ELEMENTINFO_TYPE;
1233 
1234     } /* switch */
1235 
1236     if (elInfo.elType != ID_DSE) {
1237       elementUsedBits -= bitMarkUp;
1238       bitMarkUp = FDKgetValidBits(hBs);
1239       elementUsedBits += bitMarkUp;
1240       frameBits += elementUsedBits;
1241     }
1242 
1243   } /* for (i=0; i<channelMapping.nElements; i++) */
1244 
1245   if ((syntaxFlags & AC_ER) && !(syntaxFlags & AC_DRM)) {
1246     UCHAR channelElementExtensionWritten[((8))][(
1247         1)]; /* 0: extension not touched, 1: extension already written */
1248 
1249     FDKmemclear(channelElementExtensionWritten,
1250                 sizeof(channelElementExtensionWritten));
1251 
1252     if (syntaxFlags & AC_ELD) {
1253       for (i = 0; i < channelMapping->nElements; i++) {
1254         for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) {
1255           if ((qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA) ||
1256               (qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA_CRC)) {
1257             /* Write sbr extension payload */
1258             FDKaacEnc_writeExtensionData(
1259                 hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor,
1260                 syntaxFlags, aot, epConfig);
1261 
1262             channelElementExtensionWritten[i][n] = 1;
1263           } /* SBR */
1264         }   /* n */
1265       }     /* i */
1266     }       /* AC_ELD */
1267 
1268     for (i = 0; i < channelMapping->nElements; i++) {
1269       for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) {
1270         if (channelElementExtensionWritten[i][n] == 0) {
1271           /* Write all ramaining extension payloads in element */
1272           FDKaacEnc_writeExtensionData(hTpEnc,
1273                                        &qcOut->qcElement[i]->extension[n], 0,
1274                                        alignAnchor, syntaxFlags, aot, epConfig);
1275         }
1276       } /* n */
1277     }   /* i */
1278   }     /* if AC_ER */
1279 
1280   /* Extend global extension payload table with fill bits */
1281   n = qcOut->nExtensions;
1282 
1283   /* Add fill data / stuffing bits */
1284   qcOut->extension[n].type = EXT_FILL_DATA;
1285   qcOut->extension[n].nPayloadBits = qcOut->totFillBits;
1286   qcOut->nExtensions++;
1287 
1288   /* Write global extension payload and fill data */
1289   for (n = 0; (n < qcOut->nExtensions) && (n < (2 + 2)); n++) {
1290     FDKaacEnc_writeExtensionData(hTpEnc, &qcOut->extension[n], 0, alignAnchor,
1291                                  syntaxFlags, aot, epConfig);
1292 
1293     /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here
1294      */
1295   }
1296 
1297   if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) {
1298     FDKwriteBits(hBs, ID_END, EL_ID_BITS);
1299   }
1300 
1301   if (doByteAlign) {
1302     /* Assure byte alignment*/
1303     if (((FDKgetValidBits(hBs) - alignAnchor + qcOut->alignBits) & 0x7) != 0) {
1304       return AAC_ENC_WRITTEN_BITS_ERROR;
1305     }
1306 
1307     FDKaacEnc_ByteAlignment(hBs, qcOut->alignBits);
1308   }
1309 
1310   frameBits -= bitMarkUp;
1311   frameBits += FDKgetValidBits(hBs);
1312 
1313   transportEnc_EndAccessUnit(hTpEnc, &frameBits);
1314 
1315   if (frameBits != qcOut->totalBits + qcKernel->globHdrBits) {
1316     return AAC_ENC_WRITTEN_BITS_ERROR;
1317   }
1318 
1319   return ErrorStatus;
1320 }
1321