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