1 
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4 
5 � Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6   All rights reserved.
7 
8  1.    INTRODUCTION
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
17 
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
24 
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
28 
29 2.    COPYRIGHT LICENSE
30 
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
33 
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
36 
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
41 
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44 
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
47 
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and the date of any change. For modified versions of the FDK AAC Codec, the term
50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52 
53 3.    NO PATENT LICENSE
54 
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
58 
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61 
62 4.    DISCLAIMER
63 
64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
72 
73 5.    CONTACT INFORMATION
74 
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79 
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
83 
84 /*****************************  MPEG-4 AAC Encoder  **************************
85 
86    Author(s):
87    Description:
88 
89 ******************************************************************************/
90 
91 #include "tp_data.h"
92 
93 #include "tpenc_lib.h"
94 #include "tpenc_asc.h"
95 #include "FDK_bitstream.h"
96 #include "genericStds.h"
97 
98 #define PCE_MAX_ELEMENTS 8
99 
100 /**
101  *  Describe a PCE based on placed channel elements and element type sequence.
102  */
103 typedef struct {
104 
105     UCHAR    num_front_channel_elements;     /*!< Number of front channel elements. */
106     UCHAR    num_side_channel_elements;      /*!< Number of side channel elements. */
107     UCHAR    num_back_channel_elements;      /*!< Number of back channel elements. */
108     UCHAR    num_lfe_channel_elements;       /*!< Number of lfe channel elements. */
109     MP4_ELEMENT_ID el_list[PCE_MAX_ELEMENTS];/*!< List contains sequence describing the elements
110                                                   in present channel mode. (MPEG order) */
111 } PCE_CONFIGURATION;
112 
113 
114 /**
115  *  Map an incoming channel mode to a existing PCE configuration entry.
116  */
117 typedef struct {
118 
119     CHANNEL_MODE        channel_mode;        /*!< Present channel mode. */
120     PCE_CONFIGURATION   pce_configuration;   /*!< Program config element description. */
121 
122 } CHANNEL_CONFIGURATION;
123 
124 
125 /**
126  * \brief Table contains all supported channel modes and according PCE configuration description.
127  *
128  * The number of channel element parameter describes the kind of consecutively elements.
129  * E.g. MODE_1_2_2_2_1 means:
130  *                          - First 3 elements (SCE,CPE,CPE) are front channel elements.
131  *                          - Next element (CPE) is a back channel element.
132  *                          - Last element (LFE) is a lfe channel element.
133  */
134 static const CHANNEL_CONFIGURATION pceConfigTab[] =
135 {
136   { MODE_1,                        {  1, 0, 0, 0, { ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
137   { MODE_2,                        {  1, 0, 0, 0, { ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
138   { MODE_1_2,                      {  2, 0, 0, 0, { ID_SCE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
139   { MODE_1_2_1,                    {  2, 0, 1, 0, { ID_SCE,  ID_CPE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
140   { MODE_1_2_2,                    {  2, 0, 1, 0, { ID_SCE,  ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
141   { MODE_1_2_2_1,                  {  2, 0, 1, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_LFE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
142   { MODE_1_2_2_2_1,                {  3, 0, 1, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_LFE,  ID_NONE, ID_NONE, ID_NONE } } },
143 
144 
145   { MODE_1_1,                      {  2, 0, 0, 0, { ID_SCE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
146   { MODE_1_1_1_1,                  {  2, 2, 0, 0, { ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
147   { MODE_1_1_1_1_1_1,              {  2, 2, 2, 0, { ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_NONE, ID_NONE } } },
148   { MODE_1_1_1_1_1_1_1_1,          {  3, 2, 3, 0, { ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE,  ID_SCE } } },
149 
150   { MODE_2_2,                      {  1, 0, 1, 0, { ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
151   { MODE_2_2_2,                    {  1, 1, 1, 0, { ID_CPE,  ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
152   { MODE_2_2_2_2,                  {  4, 0, 0, 0, { ID_CPE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
153 
154   { MODE_2_1,                      {  1, 0, 1, 0, { ID_CPE,  ID_SCE,  ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } },
155 
156   { MODE_7_1_REAR_SURROUND,        {  2, 0, 2, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_LFE,  ID_NONE, ID_NONE, ID_NONE } } },
157   { MODE_7_1_FRONT_CENTER,         {  3, 0, 1, 1, { ID_SCE,  ID_CPE,  ID_CPE,  ID_CPE,  ID_LFE,  ID_NONE, ID_NONE, ID_NONE } } },
158 
159 };
160 
161 
162 /**
163  * \brief  Get program config element description for existing channel mode.
164  *
165  * \param channel_mode          Current channel mode.
166  *
167  * \return
168  *          - Pointer to PCE_CONFIGURATION entry, on success.
169  *          - NULL, on failure.
170  */
getPceEntry(const CHANNEL_MODE channel_mode)171 static const PCE_CONFIGURATION* getPceEntry(
172         const CHANNEL_MODE channel_mode
173         )
174 {
175   UINT i;
176   const PCE_CONFIGURATION *pce_config = NULL;
177 
178   for (i=0; i < (sizeof(pceConfigTab)/sizeof(CHANNEL_CONFIGURATION)); i++) {
179     if (pceConfigTab[i].channel_mode == channel_mode) {
180       pce_config = &pceConfigTab[i].pce_configuration;
181     }
182   }
183 
184   return pce_config;
185 }
186 
getChannelConfig(CHANNEL_MODE channel_mode)187 int getChannelConfig( CHANNEL_MODE channel_mode )
188 {
189   INT chan_config = 0;
190 
191   switch(channel_mode) {
192     case MODE_1:         chan_config = 1; break;
193     case MODE_2:         chan_config = 2; break;
194     case MODE_1_2:       chan_config = 3; break;
195     case MODE_1_2_1:     chan_config = 4; break;
196     case MODE_1_2_2:     chan_config = 5; break;
197     case MODE_1_2_2_1:   chan_config = 6; break;
198     case MODE_1_2_2_2_1: chan_config = 7; break;
199 
200     default:             chan_config = 0;
201   }
202 
203   return chan_config;
204 }
205 
transportEnc_GetChannelMode(int noChannels)206 CHANNEL_MODE transportEnc_GetChannelMode( int noChannels )
207 {
208   CHANNEL_MODE chMode;
209 
210   if (noChannels <= 8 && noChannels > 0)
211     chMode = (CHANNEL_MODE)((noChannels == 8) ? 7 : noChannels); /* see : iso/mpeg4 v1 audio subpart1*/
212   else
213     chMode = MODE_UNKNOWN;
214 
215   return chMode;
216 }
217 
218 #ifdef TP_PCE_ENABLE
transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs,CHANNEL_MODE channelMode,INT sampleRate,int instanceTagPCE,int profile,int matrixMixdownA,int pseudoSurroundEnable,UINT alignAnchor)219 int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs,
220                           CHANNEL_MODE channelMode,
221                           INT sampleRate,
222                           int instanceTagPCE,
223                           int profile,
224                           int matrixMixdownA,
225                           int pseudoSurroundEnable,
226                           UINT alignAnchor)
227 {
228   int sampleRateIndex, i;
229   const PCE_CONFIGURATION* config = NULL;
230   const MP4_ELEMENT_ID* pEl_list = NULL;
231   UCHAR cpeCnt=0, sceCnt=0, lfeCnt=0;
232 
233   sampleRateIndex = getSamplingRateIndex(sampleRate);
234   if (sampleRateIndex == 15) {
235     return -1;
236   }
237 
238   if ((config=getPceEntry(channelMode))==NULL) {
239     return -1;
240   }
241 
242   /* Pointer to first element in element list. */
243   pEl_list = &config->el_list[0];
244 
245   FDKwriteBits(hBs, instanceTagPCE,  4);                        /* Element instance tag */
246   FDKwriteBits(hBs, profile,         2);                        /* Object type */
247   FDKwriteBits(hBs, sampleRateIndex, 4);                        /* Sample rate index*/
248 
249   FDKwriteBits(hBs, config->num_front_channel_elements, 4);     /* Front channel Elements */
250   FDKwriteBits(hBs, config->num_side_channel_elements , 4);     /* No Side Channel Elements */
251   FDKwriteBits(hBs, config->num_back_channel_elements , 4);     /* No Back channel Elements */
252   FDKwriteBits(hBs, config->num_lfe_channel_elements  , 2);     /* No Lfe channel elements */
253 
254   FDKwriteBits(hBs, 0, 3);                                      /* No assoc data elements */
255   FDKwriteBits(hBs, 0, 4);                                      /* No valid cc elements */
256   FDKwriteBits(hBs, 0, 1);                                      /* Mono mixdown present */
257   FDKwriteBits(hBs, 0, 1);                                      /* Stereo mixdown present */
258 
259   if ( matrixMixdownA!=0 && ((channelMode==MODE_1_2_2)||(channelMode==MODE_1_2_2_1)) ) {
260       FDKwriteBits(hBs, 1, 1);                                  /* Matrix mixdown present */
261       FDKwriteBits(hBs, (matrixMixdownA-1)&0x3, 2);             /* matrix_mixdown_idx */
262       FDKwriteBits(hBs, (pseudoSurroundEnable)?1:0, 1);         /* pseudo_surround_enable */
263   }
264   else {
265       FDKwriteBits(hBs, 0, 1);                                  /* Matrix mixdown not present */
266   }
267 
268   for(i=0; i<config->num_front_channel_elements; i++) {
269       UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
270       UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
271       FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
272       FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
273   }
274   for(i=0; i<config->num_side_channel_elements; i++) {
275       UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
276       UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
277       FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
278       FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
279   }
280   for(i=0; i<config->num_back_channel_elements; i++) {
281       UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0;
282       UCHAR tag   = (isCpe) ? cpeCnt++ : sceCnt++;
283       FDKwriteBits(hBs, isCpe, 1);                              /* Front channel Elements is CPE? */
284       FDKwriteBits(hBs, tag, 4);                                /* Front channel Instance Tag.*/
285   }
286   for(i=0; i<config->num_lfe_channel_elements; i++) {
287       FDKwriteBits(hBs, lfeCnt++, 4);                           /* LFE channel Instance Tag. */
288   }
289 
290   /* - num_valid_cc_elements always 0.
291      - num_assoc_data_elements always 0. */
292 
293   /* Byte alignment: relative to alignAnchor
294        ADTS: align with respect to the first bit of the raw_data_block()
295        ADIF: align with respect to the first bit of the header
296        LATM: align with respect to the first bit of the ASC */
297   FDKbyteAlign(hBs, alignAnchor);                               /* Alignment */
298 
299   FDKwriteBits(hBs, 0 ,8);                                      /* Do no write any comment. */
300 
301   /* - comment_field_bytes always 0. */
302 
303   return 0;
304 }
305 
transportEnc_GetPCEBits(CHANNEL_MODE channelMode,int matrixMixdownA,int bits)306 int transportEnc_GetPCEBits(CHANNEL_MODE channelMode,
307                             int matrixMixdownA,
308                             int bits)
309 {
310   const PCE_CONFIGURATION* config = NULL;
311 
312   if ((config=getPceEntry(channelMode))==NULL) {
313     return -1;  /* unsupported channelmapping */
314   }
315 
316   bits += 4 + 2 + 4;        /* Element instance tag  + Object type + Sample rate index */
317   bits += 4 + 4 + 4 + 2;    /* No (front + side + back + lfe channel) elements */
318   bits += 3 + 4;            /* No (assoc data + valid cc) elements */
319   bits += 1 + 1 + 1 ;       /* Mono + Stereo + Matrix mixdown present */
320 
321   if ( matrixMixdownA!=0 && ((channelMode==MODE_1_2_2)||(channelMode==MODE_1_2_2_1)) ) {
322     bits +=3;               /* matrix_mixdown_idx + pseudo_surround_enable */
323   }
324 
325   bits += (1+4) * (INT)config->num_front_channel_elements;
326   bits += (1+4) * (INT)config->num_side_channel_elements;
327   bits += (1+4) * (INT)config->num_back_channel_elements;
328   bits +=   (4) * (INT)config->num_lfe_channel_elements;
329 
330   /* - num_valid_cc_elements always 0.
331      - num_assoc_data_elements always 0. */
332 
333   if ((bits%8) != 0) {
334     bits += (8 - (bits%8)); /* Alignment */
335   }
336 
337   bits += 8;                /* Comment field  bytes */
338 
339   /* - comment_field_bytes alwys 0. */
340 
341   return bits;
342 }
343 #endif /* TP_PCE_ENABLE */
344 
writeAot(HANDLE_FDK_BITSTREAM hBitstreamBuffer,AUDIO_OBJECT_TYPE aot)345 static void writeAot(HANDLE_FDK_BITSTREAM hBitstreamBuffer, AUDIO_OBJECT_TYPE aot)
346 {
347     int tmp = (int) aot;
348 
349     if (tmp > 31) {
350         FDKwriteBits( hBitstreamBuffer, AOT_ESCAPE, 5 );
351         FDKwriteBits( hBitstreamBuffer, tmp-32, 6 );   /* AudioObjectType */
352     } else {
353         FDKwriteBits( hBitstreamBuffer, tmp, 5 );
354     }
355 }
356 
writeSampleRate(HANDLE_FDK_BITSTREAM hBitstreamBuffer,int sampleRate)357 static void writeSampleRate(HANDLE_FDK_BITSTREAM hBitstreamBuffer, int sampleRate)
358 {
359   int sampleRateIndex = getSamplingRateIndex(sampleRate);
360 
361   FDKwriteBits( hBitstreamBuffer, sampleRateIndex, 4 );
362   if( sampleRateIndex == 15 ) {
363     FDKwriteBits( hBitstreamBuffer, sampleRate, 24 );
364   }
365 }
366 
367 #ifdef TP_GA_ENABLE
368 static
transportEnc_writeGASpecificConfig(HANDLE_FDK_BITSTREAM asc,CODER_CONFIG * config,int extFlg,UINT alignAnchor)369 int transportEnc_writeGASpecificConfig(
370                                         HANDLE_FDK_BITSTREAM asc,
371                                         CODER_CONFIG *config,
372                                         int          extFlg,
373                                         UINT         alignAnchor
374                                        )
375 {
376   int aot = config->aot;
377   int samplesPerFrame = config->samplesPerFrame;
378 
379   /* start of GASpecificConfig according to ISO/IEC 14496-3 Subpart 4, 4.4.1 */
380   FDKwriteBits( asc, ((samplesPerFrame==960 || samplesPerFrame==480)?1:0), 1);  /* frameLengthFlag: 1 for a 960/480 (I)MDCT, 0 for a 1024/512 (I)MDCT*/
381   FDKwriteBits( asc, 0, 1);  /* dependsOnCoreCoder: Sampling Rate Coder Specific, see in ISO/IEC 14496-3 Subpart 4, 4.4.1 */
382   FDKwriteBits( asc, extFlg, 1 ); /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23 */
383 
384   /* Write PCE if channel config is not 1-7 */
385   if (getChannelConfig(config->channelMode) == 0) {
386       transportEnc_writePCE(asc, config->channelMode, config->samplingRate, 0, 1, config->matrixMixdownA, (config->flags&CC_PSEUDO_SURROUND)?1:0, alignAnchor);
387   }
388   if (extFlg) {
389     if (aot == AOT_ER_BSAC) {
390       FDKwriteBits( asc, config->BSACnumOfSubFrame, 5 ); /* numOfSubFrame */
391       FDKwriteBits( asc, config->BSAClayerLength, 11 );  /* layer_length */
392     }
393     if ((aot == AOT_ER_AAC_LC)   || (aot == AOT_ER_AAC_LTP)  ||
394         (aot == AOT_ER_AAC_SCAL) || (aot == AOT_ER_AAC_LD))
395     {
396       FDKwriteBits( asc, (config->flags & CC_VCB11) ? 1 : 0, 1 ); /* aacSectionDataResillienceFlag */
397       FDKwriteBits( asc, (config->flags & CC_RVLC) ? 1 : 0,  1 ); /* aacScaleFactorDataResillienceFlag */
398       FDKwriteBits( asc, (config->flags & CC_HCR) ? 1 : 0,   1 ); /* aacSpectralDataResillienceFlag */
399     }
400     FDKwriteBits( asc, 0, 1 ); /* extensionFlag3: reserved. Shall be '0' */
401   }
402   return 0;
403 }
404 #endif /* TP_GA_ENABLE */
405 
406 #ifdef TP_ELD_ENABLE
407 
408 static
transportEnc_writeELDSpecificConfig(HANDLE_FDK_BITSTREAM hBs,CODER_CONFIG * config,int epConfig,CSTpCallBacks * cb)409 int transportEnc_writeELDSpecificConfig(
410                                          HANDLE_FDK_BITSTREAM hBs,
411                                          CODER_CONFIG *config,
412                                          int        epConfig,
413                                          CSTpCallBacks *cb
414                                         )
415 {
416   /* ELD specific config */
417   if (config->channelMode == MODE_1_1) {
418     return -1;
419   }
420   FDKwriteBits(hBs, (config->samplesPerFrame == 480) ? 1 : 0, 1);
421 
422   FDKwriteBits(hBs, (config->flags & CC_VCB11 ) ? 1:0, 1);
423   FDKwriteBits(hBs, (config->flags & CC_RVLC ) ? 1:0, 1);
424   FDKwriteBits(hBs, (config->flags & CC_HCR  ) ? 1:0, 1);
425 
426   FDKwriteBits(hBs, (config->flags & CC_SBR) ? 1:0, 1); /* SBR header flag */
427   if ( (config->flags & CC_SBR) ) {
428     FDKwriteBits(hBs, (config->samplingRate == config->extSamplingRate) ? 0:1, 1); /* Samplerate Flag */
429     FDKwriteBits(hBs, (config->flags & CC_SBRCRC) ? 1:0, 1); /* SBR CRC flag*/
430 
431     if (cb->cbSbr != NULL) {
432       const PCE_CONFIGURATION *pPce;
433       int e;
434 
435       pPce = getPceEntry(config->channelMode);
436 
437       for (e=0; e<PCE_MAX_ELEMENTS && pPce->el_list[e] != ID_NONE; e++  ) {
438         if ( (pPce->el_list[e] == ID_SCE) || (pPce->el_list[e] == ID_CPE) ) {
439           cb->cbSbr(cb->cbSbrData, hBs, 0, 0, 0, config->aot, pPce->el_list[e], e);
440         }
441       }
442     }
443   }
444 
445   FDKwriteBits(hBs, 0, 4); /* ELDEXT_TERM */
446 
447   return 0;
448 }
449 #endif /* TP_ELD_ENABLE */
450 
451 
transportEnc_writeASC(HANDLE_FDK_BITSTREAM asc,CODER_CONFIG * config,CSTpCallBacks * cb)452 int transportEnc_writeASC (
453                             HANDLE_FDK_BITSTREAM asc,
454                             CODER_CONFIG *config,
455                             CSTpCallBacks *cb
456                            )
457 {
458   UINT extFlag = 0;
459   int err;
460   int epConfig = 0;
461 
462   /* Required for the PCE. */
463   UINT alignAnchor = FDKgetValidBits(asc);
464 
465   /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23,39 */
466   switch (config->aot) {
467     case AOT_ER_AAC_LC:
468     case AOT_ER_AAC_LTP:
469     case AOT_ER_AAC_SCAL:
470     case AOT_ER_TWIN_VQ:
471     case AOT_ER_BSAC:
472     case AOT_ER_AAC_LD:
473     case AOT_ER_AAC_ELD:
474     case AOT_USAC:
475         extFlag = 1;
476         break;
477     default:
478         break;
479   }
480 
481   if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent)
482     writeAot(asc, config->extAOT);
483   else
484     writeAot(asc, config->aot);
485 
486   {
487     writeSampleRate(asc, config->samplingRate);
488   }
489 
490   /* Try to guess a reasonable channel mode if not given */
491   if (config->channelMode == MODE_INVALID) {
492     config->channelMode = transportEnc_GetChannelMode(config->noChannels);
493     if (config->channelMode == MODE_INVALID)
494       return -1;
495   }
496 
497   FDKwriteBits( asc, getChannelConfig(config->channelMode), 4 );
498 
499   if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) {
500     writeSampleRate(asc, config->extSamplingRate);
501     writeAot(asc, config->aot);
502   }
503 
504   switch (config->aot) {
505 #ifdef TP_GA_ENABLE
506     case AOT_AAC_MAIN:
507     case AOT_AAC_LC:
508     case AOT_AAC_SSR:
509     case AOT_AAC_LTP:
510     case AOT_AAC_SCAL:
511     case AOT_TWIN_VQ:
512     case AOT_ER_AAC_LC:
513     case AOT_ER_AAC_LTP:
514     case AOT_ER_AAC_SCAL:
515     case AOT_ER_TWIN_VQ:
516     case AOT_ER_BSAC:
517     case AOT_ER_AAC_LD:
518       err = transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor);
519       if (err)
520         return err;
521       break;
522 #endif /* TP_GA_ENABLE */
523 #ifdef TP_ELD_ENABLE
524     case AOT_ER_AAC_ELD:
525       err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb);
526       if (err)
527         return err;
528       break;
529 #endif /* TP_ELD_ENABLE */
530     default:
531       return -1;
532   }
533 
534   switch (config->aot) {
535     case AOT_ER_AAC_LC:
536     case AOT_ER_AAC_LTP:
537     case AOT_ER_AAC_SCAL:
538     case AOT_ER_TWIN_VQ:
539     case AOT_ER_BSAC:
540     case AOT_ER_AAC_LD:
541     case AOT_ER_CELP:
542     case AOT_ER_HVXC:
543     case AOT_ER_HILN:
544     case AOT_ER_PARA:
545     case AOT_ER_AAC_ELD:
546       FDKwriteBits( asc, 0, 2 ); /* epconfig 0 */
547       break;
548     default:
549       break;
550   }
551 
552   /* backward compatible explicit signaling of extension AOT */
553   if (config->sbrSignaling==SIG_EXPLICIT_BW_COMPATIBLE)
554   {
555     TP_ASC_EXTENSION_ID ascExtId = ASCEXT_UNKOWN;
556 
557     if (config->sbrPresent) {
558       ascExtId=ASCEXT_SBR;
559       FDKwriteBits( asc, ascExtId, 11 );
560       writeAot(asc, config->extAOT);
561       FDKwriteBits( asc, 1, 1 ); /* sbrPresentFlag=1 */
562       writeSampleRate(asc, config->extSamplingRate);
563       if (config->psPresent) {
564         ascExtId=ASCEXT_PS;
565         FDKwriteBits( asc, ascExtId, 11 );
566         FDKwriteBits( asc, 1, 1 ); /* psPresentFlag=1 */
567       }
568     }
569 
570   }
571 
572   /* Make sure all bits are sync'ed */
573   FDKsyncCache( asc );
574 
575   return 0;
576 }
577