xref: /aosp_15_r20/external/aac/libAACdec/src/aacdecoder.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker 
7*e5436536SAndroid Build Coastguard Worker  1.    INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker 
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker 
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker 
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker 
34*e5436536SAndroid Build Coastguard Worker 2.    COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker 
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker 
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker 
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker 
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker 
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker 
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker 
61*e5436536SAndroid Build Coastguard Worker 3.    NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker 
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker 
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker 
71*e5436536SAndroid Build Coastguard Worker 4.    DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker 
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker 
84*e5436536SAndroid Build Coastguard Worker 5.    CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker 
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker 
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker 
95*e5436536SAndroid Build Coastguard Worker /**************************** AAC decoder library ******************************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):   Josef Hoepfl
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description:
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker /*!
104*e5436536SAndroid Build Coastguard Worker   \page default General Overview of the AAC Decoder Implementation
105*e5436536SAndroid Build Coastguard Worker 
106*e5436536SAndroid Build Coastguard Worker   The main entry point to decode a AAC frame is CAacDecoder_DecodeFrame(). It
107*e5436536SAndroid Build Coastguard Worker   handles the different transport multiplexes and bitstream formats supported by
108*e5436536SAndroid Build Coastguard Worker   this implementation. It extracts the AAC_raw_data_blocks from these bitstreams
109*e5436536SAndroid Build Coastguard Worker   to further process then in the actual decoding stages.
110*e5436536SAndroid Build Coastguard Worker 
111*e5436536SAndroid Build Coastguard Worker   Note: Click on a function of file in the above image to see details about the
112*e5436536SAndroid Build Coastguard Worker   function. Also note, that this is just an overview of the most important
113*e5436536SAndroid Build Coastguard Worker   functions and not a complete call graph.
114*e5436536SAndroid Build Coastguard Worker 
115*e5436536SAndroid Build Coastguard Worker   <h2>1 Bitstream deformatter</h2>
116*e5436536SAndroid Build Coastguard Worker   The basic bit stream parser function CChannelElement_Read() is called. It uses
117*e5436536SAndroid Build Coastguard Worker   other subcalls in order to parse and unpack the bitstreams. Note, that this
118*e5436536SAndroid Build Coastguard Worker   includes huffmann decoding of the coded spectral data. This operation can be
119*e5436536SAndroid Build Coastguard Worker   computational significant specifically at higher bitrates. Optimization is
120*e5436536SAndroid Build Coastguard Worker   likely in CBlock_ReadSpectralData().
121*e5436536SAndroid Build Coastguard Worker 
122*e5436536SAndroid Build Coastguard Worker   The bitstream deformatter also includes many bitfield operations. Profiling on
123*e5436536SAndroid Build Coastguard Worker   the target will determine required optimizations.
124*e5436536SAndroid Build Coastguard Worker 
125*e5436536SAndroid Build Coastguard Worker   <h2>2 Actual decoding to retain the time domain output</h2>
126*e5436536SAndroid Build Coastguard Worker   The basic bitstream deformatter function CChannelElement_Decode() for CPE
127*e5436536SAndroid Build Coastguard Worker   elements and SCE elements are called. Except for the stereo processing (2.1)
128*e5436536SAndroid Build Coastguard Worker   which is only used for CPE elements, the function calls for CPE or SCE are
129*e5436536SAndroid Build Coastguard Worker   similar, except that CPE always processes to independent channels while SCE
130*e5436536SAndroid Build Coastguard Worker   only processes one channel.
131*e5436536SAndroid Build Coastguard Worker 
132*e5436536SAndroid Build Coastguard Worker   Often there is the distinction between long blocks and short blocks. However,
133*e5436536SAndroid Build Coastguard Worker   computational expensive functions that ususally require optimization are being
134*e5436536SAndroid Build Coastguard Worker   shared by these two groups,
135*e5436536SAndroid Build Coastguard Worker 
136*e5436536SAndroid Build Coastguard Worker   <h3>2.1 Stereo processing for CPE elements</h3>
137*e5436536SAndroid Build Coastguard Worker   CChannelPairElement_Decode() first calles the joint stereo  tools in
138*e5436536SAndroid Build Coastguard Worker   stereo.cpp when required.
139*e5436536SAndroid Build Coastguard Worker 
140*e5436536SAndroid Build Coastguard Worker   <h3>2.2 Scaling of spectral data</h3>
141*e5436536SAndroid Build Coastguard Worker   CBlock_ScaleSpectralData().
142*e5436536SAndroid Build Coastguard Worker 
143*e5436536SAndroid Build Coastguard Worker   <h3>2.3 Apply additional coding tools</h3>
144*e5436536SAndroid Build Coastguard Worker   ApplyTools() calles the PNS tools in case of MPEG-4 bitstreams, and TNS
145*e5436536SAndroid Build Coastguard Worker   filtering CTns_Apply() for MPEG-2 and MPEG-4 bitstreams. The function
146*e5436536SAndroid Build Coastguard Worker   TnsFilterIIR() which is called by CTns_Apply() (2.3.1) might require some
147*e5436536SAndroid Build Coastguard Worker   optimization.
148*e5436536SAndroid Build Coastguard Worker 
149*e5436536SAndroid Build Coastguard Worker   <h2>3 Frequency-To-Time conversion</h3>
150*e5436536SAndroid Build Coastguard Worker   The filterbank is called using CBlock_FrequencyToTime() using the MDCT module
151*e5436536SAndroid Build Coastguard Worker   from the FDK Tools
152*e5436536SAndroid Build Coastguard Worker 
153*e5436536SAndroid Build Coastguard Worker */
154*e5436536SAndroid Build Coastguard Worker 
155*e5436536SAndroid Build Coastguard Worker #include "aacdecoder.h"
156*e5436536SAndroid Build Coastguard Worker 
157*e5436536SAndroid Build Coastguard Worker #include "aac_rom.h"
158*e5436536SAndroid Build Coastguard Worker #include "aac_ram.h"
159*e5436536SAndroid Build Coastguard Worker #include "channel.h"
160*e5436536SAndroid Build Coastguard Worker #include "FDK_audio.h"
161*e5436536SAndroid Build Coastguard Worker 
162*e5436536SAndroid Build Coastguard Worker #include "aacdec_pns.h"
163*e5436536SAndroid Build Coastguard Worker 
164*e5436536SAndroid Build Coastguard Worker #include "sbrdecoder.h"
165*e5436536SAndroid Build Coastguard Worker 
166*e5436536SAndroid Build Coastguard Worker #include "sac_dec_lib.h"
167*e5436536SAndroid Build Coastguard Worker 
168*e5436536SAndroid Build Coastguard Worker #include "aacdec_hcr.h"
169*e5436536SAndroid Build Coastguard Worker #include "rvlc.h"
170*e5436536SAndroid Build Coastguard Worker 
171*e5436536SAndroid Build Coastguard Worker #include "usacdec_lpd.h"
172*e5436536SAndroid Build Coastguard Worker 
173*e5436536SAndroid Build Coastguard Worker #include "ac_arith_coder.h"
174*e5436536SAndroid Build Coastguard Worker 
175*e5436536SAndroid Build Coastguard Worker #include "tpdec_lib.h"
176*e5436536SAndroid Build Coastguard Worker 
177*e5436536SAndroid Build Coastguard Worker #include "conceal.h"
178*e5436536SAndroid Build Coastguard Worker 
179*e5436536SAndroid Build Coastguard Worker #include "FDK_crc.h"
180*e5436536SAndroid Build Coastguard Worker #define PS_IS_EXPLICITLY_DISABLED(aot, flags) \
181*e5436536SAndroid Build Coastguard Worker   (((aot) == AOT_DRM_AAC) && !(flags & AC_PS_PRESENT))
182*e5436536SAndroid Build Coastguard Worker 
183*e5436536SAndroid Build Coastguard Worker #define IS_STEREO_SBR(el_id, stereoConfigIndex)            \
184*e5436536SAndroid Build Coastguard Worker   (((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 0) || \
185*e5436536SAndroid Build Coastguard Worker    ((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 3))
186*e5436536SAndroid Build Coastguard Worker 
CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self)187*e5436536SAndroid Build Coastguard Worker void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) {
188*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(
189*e5436536SAndroid Build Coastguard Worker       !((self->flags[0] & AC_MPS_PRESENT) && (self->flags[0] & AC_PS_PRESENT)));
190*e5436536SAndroid Build Coastguard Worker 
191*e5436536SAndroid Build Coastguard Worker   /* Assign user requested mode */
192*e5436536SAndroid Build Coastguard Worker   self->qmfModeCurr = self->qmfModeUser;
193*e5436536SAndroid Build Coastguard Worker 
194*e5436536SAndroid Build Coastguard Worker   if (IS_USAC(self->streamInfo.aot)) {
195*e5436536SAndroid Build Coastguard Worker     self->qmfModeCurr = MODE_HQ;
196*e5436536SAndroid Build Coastguard Worker   }
197*e5436536SAndroid Build Coastguard Worker 
198*e5436536SAndroid Build Coastguard Worker   if (self->qmfModeCurr == NOT_DEFINED) {
199*e5436536SAndroid Build Coastguard Worker     if ((IS_LOWDELAY(self->streamInfo.aot) &&
200*e5436536SAndroid Build Coastguard Worker          (self->flags[0] & AC_MPS_PRESENT)) ||
201*e5436536SAndroid Build Coastguard Worker         ((self->streamInfo.aacNumChannels == 1) &&
202*e5436536SAndroid Build Coastguard Worker          ((CAN_DO_PS(self->streamInfo.aot) &&
203*e5436536SAndroid Build Coastguard Worker            !(self->flags[0] & AC_MPS_PRESENT)) ||
204*e5436536SAndroid Build Coastguard Worker           (IS_USAC(self->streamInfo.aot))))) {
205*e5436536SAndroid Build Coastguard Worker       self->qmfModeCurr = MODE_HQ;
206*e5436536SAndroid Build Coastguard Worker     } else {
207*e5436536SAndroid Build Coastguard Worker       self->qmfModeCurr = MODE_LP;
208*e5436536SAndroid Build Coastguard Worker     }
209*e5436536SAndroid Build Coastguard Worker   }
210*e5436536SAndroid Build Coastguard Worker 
211*e5436536SAndroid Build Coastguard Worker   if (self->mpsEnableCurr) {
212*e5436536SAndroid Build Coastguard Worker     if (IS_LOWDELAY(self->streamInfo.aot) &&
213*e5436536SAndroid Build Coastguard Worker         (self->qmfModeCurr == MODE_LP)) { /* Overrule user requested QMF mode */
214*e5436536SAndroid Build Coastguard Worker       self->qmfModeCurr = MODE_HQ;
215*e5436536SAndroid Build Coastguard Worker     }
216*e5436536SAndroid Build Coastguard Worker     /* Set and check if MPS decoder allows the current mode */
217*e5436536SAndroid Build Coastguard Worker     switch (mpegSurroundDecoder_SetParam(
218*e5436536SAndroid Build Coastguard Worker         (CMpegSurroundDecoder *)self->pMpegSurroundDecoder,
219*e5436536SAndroid Build Coastguard Worker         SACDEC_PARTIALLY_COMPLEX, self->qmfModeCurr == MODE_LP)) {
220*e5436536SAndroid Build Coastguard Worker       case MPS_OK:
221*e5436536SAndroid Build Coastguard Worker         break;
222*e5436536SAndroid Build Coastguard Worker       case MPS_INVALID_PARAMETER: { /* Only one mode supported. Find out which
223*e5436536SAndroid Build Coastguard Worker                                        one: */
224*e5436536SAndroid Build Coastguard Worker         LIB_INFO libInfo[FDK_MODULE_LAST];
225*e5436536SAndroid Build Coastguard Worker         UINT mpsCaps;
226*e5436536SAndroid Build Coastguard Worker 
227*e5436536SAndroid Build Coastguard Worker         FDKinitLibInfo(libInfo);
228*e5436536SAndroid Build Coastguard Worker         mpegSurroundDecoder_GetLibInfo(libInfo);
229*e5436536SAndroid Build Coastguard Worker         mpsCaps = FDKlibInfo_getCapabilities(libInfo, FDK_MPSDEC);
230*e5436536SAndroid Build Coastguard Worker 
231*e5436536SAndroid Build Coastguard Worker         if (((mpsCaps & CAPF_MPS_LP) && (self->qmfModeCurr == MODE_LP)) ||
232*e5436536SAndroid Build Coastguard Worker             ((mpsCaps & CAPF_MPS_HQ) &&
233*e5436536SAndroid Build Coastguard Worker              (self->qmfModeCurr ==
234*e5436536SAndroid Build Coastguard Worker               MODE_HQ))) { /* MPS decoder does support the requested mode. */
235*e5436536SAndroid Build Coastguard Worker           break;
236*e5436536SAndroid Build Coastguard Worker         }
237*e5436536SAndroid Build Coastguard Worker       }
238*e5436536SAndroid Build Coastguard Worker         FDK_FALLTHROUGH;
239*e5436536SAndroid Build Coastguard Worker       default:
240*e5436536SAndroid Build Coastguard Worker         if (self->qmfModeUser == NOT_DEFINED) {
241*e5436536SAndroid Build Coastguard Worker           /* Revert in case mpegSurroundDecoder_SetParam() fails. */
242*e5436536SAndroid Build Coastguard Worker           self->qmfModeCurr =
243*e5436536SAndroid Build Coastguard Worker               (self->qmfModeCurr == MODE_LP) ? MODE_HQ : MODE_LP;
244*e5436536SAndroid Build Coastguard Worker         } else {
245*e5436536SAndroid Build Coastguard Worker           /* in case specific mode was requested we disable MPS and playout the
246*e5436536SAndroid Build Coastguard Worker            * downmix */
247*e5436536SAndroid Build Coastguard Worker           self->mpsEnableCurr = 0;
248*e5436536SAndroid Build Coastguard Worker         }
249*e5436536SAndroid Build Coastguard Worker     }
250*e5436536SAndroid Build Coastguard Worker   }
251*e5436536SAndroid Build Coastguard Worker 
252*e5436536SAndroid Build Coastguard Worker   /* Set SBR to current QMF mode. Error does not matter. */
253*e5436536SAndroid Build Coastguard Worker   sbrDecoder_SetParam(self->hSbrDecoder, SBR_QMF_MODE,
254*e5436536SAndroid Build Coastguard Worker                       (self->qmfModeCurr == MODE_LP));
255*e5436536SAndroid Build Coastguard Worker   self->psPossible =
256*e5436536SAndroid Build Coastguard Worker       ((CAN_DO_PS(self->streamInfo.aot) &&
257*e5436536SAndroid Build Coastguard Worker         !PS_IS_EXPLICITLY_DISABLED(self->streamInfo.aot, self->flags[0]) &&
258*e5436536SAndroid Build Coastguard Worker         self->streamInfo.aacNumChannels == 1 &&
259*e5436536SAndroid Build Coastguard Worker         !(self->flags[0] & AC_MPS_PRESENT))) &&
260*e5436536SAndroid Build Coastguard Worker       self->qmfModeCurr == MODE_HQ;
261*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(!((self->flags[0] & AC_MPS_PRESENT) && self->psPossible));
262*e5436536SAndroid Build Coastguard Worker }
263*e5436536SAndroid Build Coastguard Worker 
CAacDecoder_SignalInterruption(HANDLE_AACDECODER self)264*e5436536SAndroid Build Coastguard Worker void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self) {
265*e5436536SAndroid Build Coastguard Worker   if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) {
266*e5436536SAndroid Build Coastguard Worker     int i;
267*e5436536SAndroid Build Coastguard Worker 
268*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < fMin(self->aacChannels, (8)); i++) {
269*e5436536SAndroid Build Coastguard Worker       if (self->pAacDecoderStaticChannelInfo
270*e5436536SAndroid Build Coastguard Worker               [i]) { /* number of active channels can be smaller */
271*e5436536SAndroid Build Coastguard Worker         self->pAacDecoderStaticChannelInfo[i]->hArCo->m_numberLinesPrev = 0;
272*e5436536SAndroid Build Coastguard Worker       }
273*e5436536SAndroid Build Coastguard Worker     }
274*e5436536SAndroid Build Coastguard Worker   }
275*e5436536SAndroid Build Coastguard Worker }
276*e5436536SAndroid Build Coastguard Worker 
277*e5436536SAndroid Build Coastguard Worker /*!
278*e5436536SAndroid Build Coastguard Worker   \brief Calculates the number of element channels
279*e5436536SAndroid Build Coastguard Worker 
280*e5436536SAndroid Build Coastguard Worker   \type  channel type
281*e5436536SAndroid Build Coastguard Worker   \usacStereoConfigIndex  usac stereo config index
282*e5436536SAndroid Build Coastguard Worker 
283*e5436536SAndroid Build Coastguard Worker   \return  element channels
284*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_GetELChannels(MP4_ELEMENT_ID type,UCHAR usacStereoConfigIndex)285*e5436536SAndroid Build Coastguard Worker static int CAacDecoder_GetELChannels(MP4_ELEMENT_ID type,
286*e5436536SAndroid Build Coastguard Worker                                      UCHAR usacStereoConfigIndex) {
287*e5436536SAndroid Build Coastguard Worker   int el_channels = 0;
288*e5436536SAndroid Build Coastguard Worker 
289*e5436536SAndroid Build Coastguard Worker   switch (type) {
290*e5436536SAndroid Build Coastguard Worker     case ID_USAC_CPE:
291*e5436536SAndroid Build Coastguard Worker       if (usacStereoConfigIndex == 1) {
292*e5436536SAndroid Build Coastguard Worker         el_channels = 1;
293*e5436536SAndroid Build Coastguard Worker       } else {
294*e5436536SAndroid Build Coastguard Worker         el_channels = 2;
295*e5436536SAndroid Build Coastguard Worker       }
296*e5436536SAndroid Build Coastguard Worker       break;
297*e5436536SAndroid Build Coastguard Worker     case ID_CPE:
298*e5436536SAndroid Build Coastguard Worker       el_channels = 2;
299*e5436536SAndroid Build Coastguard Worker       break;
300*e5436536SAndroid Build Coastguard Worker     case ID_USAC_SCE:
301*e5436536SAndroid Build Coastguard Worker     case ID_USAC_LFE:
302*e5436536SAndroid Build Coastguard Worker     case ID_SCE:
303*e5436536SAndroid Build Coastguard Worker     case ID_LFE:
304*e5436536SAndroid Build Coastguard Worker       el_channels = 1;
305*e5436536SAndroid Build Coastguard Worker       break;
306*e5436536SAndroid Build Coastguard Worker     default:
307*e5436536SAndroid Build Coastguard Worker       el_channels = 0;
308*e5436536SAndroid Build Coastguard Worker       break;
309*e5436536SAndroid Build Coastguard Worker   }
310*e5436536SAndroid Build Coastguard Worker 
311*e5436536SAndroid Build Coastguard Worker   return el_channels;
312*e5436536SAndroid Build Coastguard Worker }
313*e5436536SAndroid Build Coastguard Worker 
314*e5436536SAndroid Build Coastguard Worker /*!
315*e5436536SAndroid Build Coastguard Worker   \brief Reset ancillary data struct. Call before parsing a new frame.
316*e5436536SAndroid Build Coastguard Worker 
317*e5436536SAndroid Build Coastguard Worker   \ancData Pointer to ancillary data structure
318*e5436536SAndroid Build Coastguard Worker 
319*e5436536SAndroid Build Coastguard Worker   \return  Error code
320*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_AncDataReset(CAncData * ancData)321*e5436536SAndroid Build Coastguard Worker static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData) {
322*e5436536SAndroid Build Coastguard Worker   int i;
323*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < 8; i++) {
324*e5436536SAndroid Build Coastguard Worker     ancData->offset[i] = 0;
325*e5436536SAndroid Build Coastguard Worker   }
326*e5436536SAndroid Build Coastguard Worker   ancData->nrElements = 0;
327*e5436536SAndroid Build Coastguard Worker 
328*e5436536SAndroid Build Coastguard Worker   return AAC_DEC_OK;
329*e5436536SAndroid Build Coastguard Worker }
330*e5436536SAndroid Build Coastguard Worker 
331*e5436536SAndroid Build Coastguard Worker /*!
332*e5436536SAndroid Build Coastguard Worker   \brief Initialize ancillary buffer
333*e5436536SAndroid Build Coastguard Worker 
334*e5436536SAndroid Build Coastguard Worker   \ancData Pointer to ancillary data structure
335*e5436536SAndroid Build Coastguard Worker   \buffer Pointer to (external) anc data buffer
336*e5436536SAndroid Build Coastguard Worker   \size Size of the buffer pointed on by buffer in bytes
337*e5436536SAndroid Build Coastguard Worker 
338*e5436536SAndroid Build Coastguard Worker   \return  Error code
339*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_AncDataInit(CAncData * ancData,unsigned char * buffer,int size)340*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData,
341*e5436536SAndroid Build Coastguard Worker                                           unsigned char *buffer, int size) {
342*e5436536SAndroid Build Coastguard Worker   if (size >= 0) {
343*e5436536SAndroid Build Coastguard Worker     ancData->buffer = buffer;
344*e5436536SAndroid Build Coastguard Worker     ancData->bufferSize = size;
345*e5436536SAndroid Build Coastguard Worker 
346*e5436536SAndroid Build Coastguard Worker     CAacDecoder_AncDataReset(ancData);
347*e5436536SAndroid Build Coastguard Worker 
348*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_OK;
349*e5436536SAndroid Build Coastguard Worker   }
350*e5436536SAndroid Build Coastguard Worker 
351*e5436536SAndroid Build Coastguard Worker   return AAC_DEC_ANC_DATA_ERROR;
352*e5436536SAndroid Build Coastguard Worker }
353*e5436536SAndroid Build Coastguard Worker 
354*e5436536SAndroid Build Coastguard Worker /*!
355*e5436536SAndroid Build Coastguard Worker   \brief Get one ancillary data element
356*e5436536SAndroid Build Coastguard Worker 
357*e5436536SAndroid Build Coastguard Worker   \ancData Pointer to ancillary data structure
358*e5436536SAndroid Build Coastguard Worker   \index Index of the anc data element to get
359*e5436536SAndroid Build Coastguard Worker   \ptr Pointer to a buffer receiving a pointer to the requested anc data element
360*e5436536SAndroid Build Coastguard Worker   \size Pointer to a buffer receiving the length of the requested anc data
361*e5436536SAndroid Build Coastguard Worker   element in bytes
362*e5436536SAndroid Build Coastguard Worker 
363*e5436536SAndroid Build Coastguard Worker   \return  Error code
364*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_AncDataGet(CAncData * ancData,int index,unsigned char ** ptr,int * size)365*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index,
366*e5436536SAndroid Build Coastguard Worker                                          unsigned char **ptr, int *size) {
367*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR error = AAC_DEC_OK;
368*e5436536SAndroid Build Coastguard Worker 
369*e5436536SAndroid Build Coastguard Worker   *ptr = NULL;
370*e5436536SAndroid Build Coastguard Worker   *size = 0;
371*e5436536SAndroid Build Coastguard Worker 
372*e5436536SAndroid Build Coastguard Worker   if (index >= 0 && index < 8 - 1 && index < ancData->nrElements) {
373*e5436536SAndroid Build Coastguard Worker     *ptr = &ancData->buffer[ancData->offset[index]];
374*e5436536SAndroid Build Coastguard Worker     *size = ancData->offset[index + 1] - ancData->offset[index];
375*e5436536SAndroid Build Coastguard Worker   }
376*e5436536SAndroid Build Coastguard Worker 
377*e5436536SAndroid Build Coastguard Worker   return error;
378*e5436536SAndroid Build Coastguard Worker }
379*e5436536SAndroid Build Coastguard Worker 
380*e5436536SAndroid Build Coastguard Worker /*!
381*e5436536SAndroid Build Coastguard Worker   \brief Parse ancillary data
382*e5436536SAndroid Build Coastguard Worker 
383*e5436536SAndroid Build Coastguard Worker   \ancData Pointer to ancillary data structure
384*e5436536SAndroid Build Coastguard Worker   \hBs Handle to FDK bitstream
385*e5436536SAndroid Build Coastguard Worker   \ancBytes Length of ancillary data to read from the bitstream
386*e5436536SAndroid Build Coastguard Worker 
387*e5436536SAndroid Build Coastguard Worker   \return  Error code
388*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_AncDataParse(CAncData * ancData,HANDLE_FDK_BITSTREAM hBs,const int ancBytes)389*e5436536SAndroid Build Coastguard Worker static AAC_DECODER_ERROR CAacDecoder_AncDataParse(CAncData *ancData,
390*e5436536SAndroid Build Coastguard Worker                                                   HANDLE_FDK_BITSTREAM hBs,
391*e5436536SAndroid Build Coastguard Worker                                                   const int ancBytes) {
392*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR error = AAC_DEC_OK;
393*e5436536SAndroid Build Coastguard Worker   int readBytes = 0;
394*e5436536SAndroid Build Coastguard Worker 
395*e5436536SAndroid Build Coastguard Worker   if (ancData->buffer != NULL) {
396*e5436536SAndroid Build Coastguard Worker     if (ancBytes > 0) {
397*e5436536SAndroid Build Coastguard Worker       /* write ancillary data to external buffer */
398*e5436536SAndroid Build Coastguard Worker       int offset = ancData->offset[ancData->nrElements];
399*e5436536SAndroid Build Coastguard Worker 
400*e5436536SAndroid Build Coastguard Worker       if ((offset + ancBytes) > ancData->bufferSize) {
401*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_TOO_SMALL_ANC_BUFFER;
402*e5436536SAndroid Build Coastguard Worker       } else if (ancData->nrElements >= 8 - 1) {
403*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_TOO_MANY_ANC_ELEMENTS;
404*e5436536SAndroid Build Coastguard Worker       } else {
405*e5436536SAndroid Build Coastguard Worker         int i;
406*e5436536SAndroid Build Coastguard Worker 
407*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < ancBytes; i++) {
408*e5436536SAndroid Build Coastguard Worker           ancData->buffer[i + offset] = FDKreadBits(hBs, 8);
409*e5436536SAndroid Build Coastguard Worker           readBytes++;
410*e5436536SAndroid Build Coastguard Worker         }
411*e5436536SAndroid Build Coastguard Worker 
412*e5436536SAndroid Build Coastguard Worker         ancData->nrElements++;
413*e5436536SAndroid Build Coastguard Worker         ancData->offset[ancData->nrElements] =
414*e5436536SAndroid Build Coastguard Worker             ancBytes + ancData->offset[ancData->nrElements - 1];
415*e5436536SAndroid Build Coastguard Worker       }
416*e5436536SAndroid Build Coastguard Worker     }
417*e5436536SAndroid Build Coastguard Worker   }
418*e5436536SAndroid Build Coastguard Worker 
419*e5436536SAndroid Build Coastguard Worker   readBytes = ancBytes - readBytes;
420*e5436536SAndroid Build Coastguard Worker 
421*e5436536SAndroid Build Coastguard Worker   if (readBytes > 0) {
422*e5436536SAndroid Build Coastguard Worker     /* skip data */
423*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, readBytes << 3);
424*e5436536SAndroid Build Coastguard Worker   }
425*e5436536SAndroid Build Coastguard Worker 
426*e5436536SAndroid Build Coastguard Worker   return error;
427*e5436536SAndroid Build Coastguard Worker }
428*e5436536SAndroid Build Coastguard Worker 
429*e5436536SAndroid Build Coastguard Worker /*!
430*e5436536SAndroid Build Coastguard Worker   \brief Read Stream Data Element
431*e5436536SAndroid Build Coastguard Worker 
432*e5436536SAndroid Build Coastguard Worker   \bs Bitstream Handle
433*e5436536SAndroid Build Coastguard Worker 
434*e5436536SAndroid Build Coastguard Worker   \return  Error code
435*e5436536SAndroid Build Coastguard Worker */
CDataStreamElement_Read(HANDLE_AACDECODER self,HANDLE_FDK_BITSTREAM bs,UCHAR * elementInstanceTag,UINT alignmentAnchor)436*e5436536SAndroid Build Coastguard Worker static AAC_DECODER_ERROR CDataStreamElement_Read(HANDLE_AACDECODER self,
437*e5436536SAndroid Build Coastguard Worker                                                  HANDLE_FDK_BITSTREAM bs,
438*e5436536SAndroid Build Coastguard Worker                                                  UCHAR *elementInstanceTag,
439*e5436536SAndroid Build Coastguard Worker                                                  UINT alignmentAnchor) {
440*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR error = AAC_DEC_OK;
441*e5436536SAndroid Build Coastguard Worker   UINT dseBits;
442*e5436536SAndroid Build Coastguard Worker   INT dataStart;
443*e5436536SAndroid Build Coastguard Worker   int dataByteAlignFlag, count;
444*e5436536SAndroid Build Coastguard Worker 
445*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(self != NULL);
446*e5436536SAndroid Build Coastguard Worker 
447*e5436536SAndroid Build Coastguard Worker   int crcReg = transportDec_CrcStartReg(self->hInput, 0);
448*e5436536SAndroid Build Coastguard Worker 
449*e5436536SAndroid Build Coastguard Worker   /* Element Instance Tag */
450*e5436536SAndroid Build Coastguard Worker   *elementInstanceTag = FDKreadBits(bs, 4);
451*e5436536SAndroid Build Coastguard Worker   /* Data Byte Align Flag */
452*e5436536SAndroid Build Coastguard Worker   dataByteAlignFlag = FDKreadBits(bs, 1);
453*e5436536SAndroid Build Coastguard Worker 
454*e5436536SAndroid Build Coastguard Worker   count = FDKreadBits(bs, 8);
455*e5436536SAndroid Build Coastguard Worker 
456*e5436536SAndroid Build Coastguard Worker   if (count == 255) {
457*e5436536SAndroid Build Coastguard Worker     count += FDKreadBits(bs, 8); /* EscCount */
458*e5436536SAndroid Build Coastguard Worker   }
459*e5436536SAndroid Build Coastguard Worker   dseBits = count * 8;
460*e5436536SAndroid Build Coastguard Worker 
461*e5436536SAndroid Build Coastguard Worker   if (dataByteAlignFlag) {
462*e5436536SAndroid Build Coastguard Worker     FDKbyteAlign(bs, alignmentAnchor);
463*e5436536SAndroid Build Coastguard Worker   }
464*e5436536SAndroid Build Coastguard Worker 
465*e5436536SAndroid Build Coastguard Worker   dataStart = (INT)FDKgetValidBits(bs);
466*e5436536SAndroid Build Coastguard Worker 
467*e5436536SAndroid Build Coastguard Worker   error = CAacDecoder_AncDataParse(&self->ancData, bs, count);
468*e5436536SAndroid Build Coastguard Worker   transportDec_CrcEndReg(self->hInput, crcReg);
469*e5436536SAndroid Build Coastguard Worker 
470*e5436536SAndroid Build Coastguard Worker   {
471*e5436536SAndroid Build Coastguard Worker     /* Move to the beginning of the data chunk */
472*e5436536SAndroid Build Coastguard Worker     FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs));
473*e5436536SAndroid Build Coastguard Worker 
474*e5436536SAndroid Build Coastguard Worker     /* Read Anc data if available */
475*e5436536SAndroid Build Coastguard Worker     aacDecoder_drcMarkPayload(self->hDrcInfo, bs, DVB_DRC_ANC_DATA);
476*e5436536SAndroid Build Coastguard Worker   }
477*e5436536SAndroid Build Coastguard Worker 
478*e5436536SAndroid Build Coastguard Worker   {
479*e5436536SAndroid Build Coastguard Worker     PCMDMX_ERROR dmxErr = PCMDMX_OK;
480*e5436536SAndroid Build Coastguard Worker 
481*e5436536SAndroid Build Coastguard Worker     /* Move to the beginning of the data chunk */
482*e5436536SAndroid Build Coastguard Worker     FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs));
483*e5436536SAndroid Build Coastguard Worker 
484*e5436536SAndroid Build Coastguard Worker     /* Read DMX meta-data */
485*e5436536SAndroid Build Coastguard Worker     dmxErr = pcmDmx_Parse(self->hPcmUtils, bs, dseBits, 0 /* not mpeg2 */);
486*e5436536SAndroid Build Coastguard Worker     if (error == AAC_DEC_OK && dmxErr != PCMDMX_OK) {
487*e5436536SAndroid Build Coastguard Worker       error = AAC_DEC_UNKNOWN;
488*e5436536SAndroid Build Coastguard Worker     }
489*e5436536SAndroid Build Coastguard Worker   }
490*e5436536SAndroid Build Coastguard Worker 
491*e5436536SAndroid Build Coastguard Worker   /* Move to the very end of the element. */
492*e5436536SAndroid Build Coastguard Worker   FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - dataStart + (INT)dseBits);
493*e5436536SAndroid Build Coastguard Worker 
494*e5436536SAndroid Build Coastguard Worker   return error;
495*e5436536SAndroid Build Coastguard Worker }
496*e5436536SAndroid Build Coastguard Worker 
findElementInstanceTag(INT elementTag,MP4_ELEMENT_ID elementId,CAacDecoderChannelInfo ** pAacDecoderChannelInfo,INT nChannels,MP4_ELEMENT_ID * pElementIdTab,INT nElements)497*e5436536SAndroid Build Coastguard Worker static INT findElementInstanceTag(
498*e5436536SAndroid Build Coastguard Worker     INT elementTag, MP4_ELEMENT_ID elementId,
499*e5436536SAndroid Build Coastguard Worker     CAacDecoderChannelInfo **pAacDecoderChannelInfo, INT nChannels,
500*e5436536SAndroid Build Coastguard Worker     MP4_ELEMENT_ID *pElementIdTab, INT nElements) {
501*e5436536SAndroid Build Coastguard Worker   int el, chCnt = 0;
502*e5436536SAndroid Build Coastguard Worker 
503*e5436536SAndroid Build Coastguard Worker   for (el = 0; el < nElements; el++) {
504*e5436536SAndroid Build Coastguard Worker     switch (pElementIdTab[el]) {
505*e5436536SAndroid Build Coastguard Worker       case ID_CPE:
506*e5436536SAndroid Build Coastguard Worker       case ID_SCE:
507*e5436536SAndroid Build Coastguard Worker       case ID_LFE:
508*e5436536SAndroid Build Coastguard Worker         if ((elementTag == pAacDecoderChannelInfo[chCnt]->ElementInstanceTag) &&
509*e5436536SAndroid Build Coastguard Worker             (elementId == pElementIdTab[el])) {
510*e5436536SAndroid Build Coastguard Worker           return 1; /* element instance tag found */
511*e5436536SAndroid Build Coastguard Worker         }
512*e5436536SAndroid Build Coastguard Worker         chCnt += (pElementIdTab[el] == ID_CPE) ? 2 : 1;
513*e5436536SAndroid Build Coastguard Worker         break;
514*e5436536SAndroid Build Coastguard Worker       default:
515*e5436536SAndroid Build Coastguard Worker         break;
516*e5436536SAndroid Build Coastguard Worker     }
517*e5436536SAndroid Build Coastguard Worker     if (chCnt >= nChannels) break;
518*e5436536SAndroid Build Coastguard Worker     if (pElementIdTab[el] == ID_END) break;
519*e5436536SAndroid Build Coastguard Worker   }
520*e5436536SAndroid Build Coastguard Worker 
521*e5436536SAndroid Build Coastguard Worker   return 0; /* element instance tag not found */
522*e5436536SAndroid Build Coastguard Worker }
523*e5436536SAndroid Build Coastguard Worker 
validateElementInstanceTags(CProgramConfig * pce,CAacDecoderChannelInfo ** pAacDecoderChannelInfo,INT nChannels,MP4_ELEMENT_ID * pElementIdTab,INT nElements)524*e5436536SAndroid Build Coastguard Worker static INT validateElementInstanceTags(
525*e5436536SAndroid Build Coastguard Worker     CProgramConfig *pce, CAacDecoderChannelInfo **pAacDecoderChannelInfo,
526*e5436536SAndroid Build Coastguard Worker     INT nChannels, MP4_ELEMENT_ID *pElementIdTab, INT nElements) {
527*e5436536SAndroid Build Coastguard Worker   if (nChannels >= pce->NumChannels) {
528*e5436536SAndroid Build Coastguard Worker     for (int el = 0; el < pce->NumFrontChannelElements; el++) {
529*e5436536SAndroid Build Coastguard Worker       if (!findElementInstanceTag(pce->FrontElementTagSelect[el],
530*e5436536SAndroid Build Coastguard Worker                                   pce->FrontElementIsCpe[el] ? ID_CPE : ID_SCE,
531*e5436536SAndroid Build Coastguard Worker                                   pAacDecoderChannelInfo, nChannels,
532*e5436536SAndroid Build Coastguard Worker                                   pElementIdTab, nElements)) {
533*e5436536SAndroid Build Coastguard Worker         return 0; /* element instance tag not in raw_data_block() */
534*e5436536SAndroid Build Coastguard Worker       }
535*e5436536SAndroid Build Coastguard Worker     }
536*e5436536SAndroid Build Coastguard Worker     for (int el = 0; el < pce->NumSideChannelElements; el++) {
537*e5436536SAndroid Build Coastguard Worker       if (!findElementInstanceTag(pce->SideElementTagSelect[el],
538*e5436536SAndroid Build Coastguard Worker                                   pce->SideElementIsCpe[el] ? ID_CPE : ID_SCE,
539*e5436536SAndroid Build Coastguard Worker                                   pAacDecoderChannelInfo, nChannels,
540*e5436536SAndroid Build Coastguard Worker                                   pElementIdTab, nElements)) {
541*e5436536SAndroid Build Coastguard Worker         return 0; /* element instance tag not in raw_data_block() */
542*e5436536SAndroid Build Coastguard Worker       }
543*e5436536SAndroid Build Coastguard Worker     }
544*e5436536SAndroid Build Coastguard Worker     for (int el = 0; el < pce->NumBackChannelElements; el++) {
545*e5436536SAndroid Build Coastguard Worker       if (!findElementInstanceTag(pce->BackElementTagSelect[el],
546*e5436536SAndroid Build Coastguard Worker                                   pce->BackElementIsCpe[el] ? ID_CPE : ID_SCE,
547*e5436536SAndroid Build Coastguard Worker                                   pAacDecoderChannelInfo, nChannels,
548*e5436536SAndroid Build Coastguard Worker                                   pElementIdTab, nElements)) {
549*e5436536SAndroid Build Coastguard Worker         return 0; /* element instance tag not in raw_data_block() */
550*e5436536SAndroid Build Coastguard Worker       }
551*e5436536SAndroid Build Coastguard Worker     }
552*e5436536SAndroid Build Coastguard Worker     for (int el = 0; el < pce->NumLfeChannelElements; el++) {
553*e5436536SAndroid Build Coastguard Worker       if (!findElementInstanceTag(pce->LfeElementTagSelect[el], ID_LFE,
554*e5436536SAndroid Build Coastguard Worker                                   pAacDecoderChannelInfo, nChannels,
555*e5436536SAndroid Build Coastguard Worker                                   pElementIdTab, nElements)) {
556*e5436536SAndroid Build Coastguard Worker         return 0; /* element instance tag not in raw_data_block() */
557*e5436536SAndroid Build Coastguard Worker       }
558*e5436536SAndroid Build Coastguard Worker     }
559*e5436536SAndroid Build Coastguard Worker   } else {
560*e5436536SAndroid Build Coastguard Worker     return 0; /* too less decoded audio channels */
561*e5436536SAndroid Build Coastguard Worker   }
562*e5436536SAndroid Build Coastguard Worker 
563*e5436536SAndroid Build Coastguard Worker   return 1; /* all element instance tags found in raw_data_block() */
564*e5436536SAndroid Build Coastguard Worker }
565*e5436536SAndroid Build Coastguard Worker 
566*e5436536SAndroid Build Coastguard Worker /*!
567*e5436536SAndroid Build Coastguard Worker   \brief Read Program Config Element
568*e5436536SAndroid Build Coastguard Worker 
569*e5436536SAndroid Build Coastguard Worker   \bs Bitstream Handle
570*e5436536SAndroid Build Coastguard Worker   \pTp Transport decoder handle for CRC handling
571*e5436536SAndroid Build Coastguard Worker   \pce Pointer to PCE buffer
572*e5436536SAndroid Build Coastguard Worker   \channelConfig Current channel configuration
573*e5436536SAndroid Build Coastguard Worker   \alignAnchor Anchor for byte alignment
574*e5436536SAndroid Build Coastguard Worker 
575*e5436536SAndroid Build Coastguard Worker   \return  PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated
576*e5436536SAndroid Build Coastguard Worker   need re-config).
577*e5436536SAndroid Build Coastguard Worker */
CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs,HANDLE_TRANSPORTDEC pTp,CProgramConfig * pce,const UINT channelConfig,const UINT alignAnchor)578*e5436536SAndroid Build Coastguard Worker static int CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs,
579*e5436536SAndroid Build Coastguard Worker                                       HANDLE_TRANSPORTDEC pTp,
580*e5436536SAndroid Build Coastguard Worker                                       CProgramConfig *pce,
581*e5436536SAndroid Build Coastguard Worker                                       const UINT channelConfig,
582*e5436536SAndroid Build Coastguard Worker                                       const UINT alignAnchor) {
583*e5436536SAndroid Build Coastguard Worker   int pceStatus = 0;
584*e5436536SAndroid Build Coastguard Worker   int crcReg;
585*e5436536SAndroid Build Coastguard Worker 
586*e5436536SAndroid Build Coastguard Worker   /* read PCE to temporal buffer first */
587*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
588*e5436536SAndroid Build Coastguard Worker 
589*e5436536SAndroid Build Coastguard Worker   CProgramConfig_Init(tmpPce);
590*e5436536SAndroid Build Coastguard Worker 
591*e5436536SAndroid Build Coastguard Worker   crcReg = transportDec_CrcStartReg(pTp, 0);
592*e5436536SAndroid Build Coastguard Worker 
593*e5436536SAndroid Build Coastguard Worker   CProgramConfig_Read(tmpPce, bs, alignAnchor);
594*e5436536SAndroid Build Coastguard Worker 
595*e5436536SAndroid Build Coastguard Worker   transportDec_CrcEndReg(pTp, crcReg);
596*e5436536SAndroid Build Coastguard Worker 
597*e5436536SAndroid Build Coastguard Worker   if (CProgramConfig_IsValid(tmpPce) && (tmpPce->Profile == 1)) {
598*e5436536SAndroid Build Coastguard Worker     if (!CProgramConfig_IsValid(pce) && (channelConfig > 0)) {
599*e5436536SAndroid Build Coastguard Worker       /* Create a standard channel config PCE to compare with */
600*e5436536SAndroid Build Coastguard Worker       CProgramConfig_GetDefault(pce, channelConfig);
601*e5436536SAndroid Build Coastguard Worker     }
602*e5436536SAndroid Build Coastguard Worker 
603*e5436536SAndroid Build Coastguard Worker     if (CProgramConfig_IsValid(pce)) {
604*e5436536SAndroid Build Coastguard Worker       /* Compare the new and the old PCE (tags ignored) */
605*e5436536SAndroid Build Coastguard Worker       switch (CProgramConfig_Compare(pce, tmpPce)) {
606*e5436536SAndroid Build Coastguard Worker         case 1: /* Channel configuration not changed. Just new metadata. */
607*e5436536SAndroid Build Coastguard Worker           FDKmemcpy(pce, tmpPce,
608*e5436536SAndroid Build Coastguard Worker                     sizeof(CProgramConfig)); /* Store the complete PCE */
609*e5436536SAndroid Build Coastguard Worker           pceStatus = 1; /* New PCE but no change of config */
610*e5436536SAndroid Build Coastguard Worker           break;
611*e5436536SAndroid Build Coastguard Worker         case 2:  /* The number of channels are identical but not the config */
612*e5436536SAndroid Build Coastguard Worker         case -1: /* The channel configuration is completely different */
613*e5436536SAndroid Build Coastguard Worker           pceStatus = -1; /* Not supported! */
614*e5436536SAndroid Build Coastguard Worker           break;
615*e5436536SAndroid Build Coastguard Worker         case 0: /* Nothing to do because PCE matches the old one exactly. */
616*e5436536SAndroid Build Coastguard Worker         default:
617*e5436536SAndroid Build Coastguard Worker           /* pceStatus = 0; */
618*e5436536SAndroid Build Coastguard Worker           break;
619*e5436536SAndroid Build Coastguard Worker       }
620*e5436536SAndroid Build Coastguard Worker     }
621*e5436536SAndroid Build Coastguard Worker   }
622*e5436536SAndroid Build Coastguard Worker 
623*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
624*e5436536SAndroid Build Coastguard Worker 
625*e5436536SAndroid Build Coastguard Worker   return pceStatus;
626*e5436536SAndroid Build Coastguard Worker }
627*e5436536SAndroid Build Coastguard Worker 
628*e5436536SAndroid Build Coastguard Worker /*!
629*e5436536SAndroid Build Coastguard Worker   \brief Prepares crossfade for USAC DASH IPF config change
630*e5436536SAndroid Build Coastguard Worker 
631*e5436536SAndroid Build Coastguard Worker   \pTimeData             Pointer to time data
632*e5436536SAndroid Build Coastguard Worker   \pTimeDataFlush        Pointer to flushed time data
633*e5436536SAndroid Build Coastguard Worker   \numChannels           Number of channels
634*e5436536SAndroid Build Coastguard Worker   \frameSize             Size of frame
635*e5436536SAndroid Build Coastguard Worker   \interleaved           Indicates if time data is interleaved
636*e5436536SAndroid Build Coastguard Worker 
637*e5436536SAndroid Build Coastguard Worker   \return  Error code
638*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_PrepareCrossFade(const PCM_DEC * pTimeData,PCM_DEC ** pTimeDataFlush,const INT numChannels,const INT frameSize,const INT interleaved)639*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
640*e5436536SAndroid Build Coastguard Worker     const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
641*e5436536SAndroid Build Coastguard Worker     const INT frameSize, const INT interleaved) {
642*e5436536SAndroid Build Coastguard Worker   int i, ch, s1, s2;
643*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR ErrorStatus;
644*e5436536SAndroid Build Coastguard Worker 
645*e5436536SAndroid Build Coastguard Worker   ErrorStatus = AAC_DEC_OK;
646*e5436536SAndroid Build Coastguard Worker 
647*e5436536SAndroid Build Coastguard Worker   if (interleaved) {
648*e5436536SAndroid Build Coastguard Worker     s1 = 1;
649*e5436536SAndroid Build Coastguard Worker     s2 = numChannels;
650*e5436536SAndroid Build Coastguard Worker   } else {
651*e5436536SAndroid Build Coastguard Worker     s1 = frameSize;
652*e5436536SAndroid Build Coastguard Worker     s2 = 1;
653*e5436536SAndroid Build Coastguard Worker   }
654*e5436536SAndroid Build Coastguard Worker 
655*e5436536SAndroid Build Coastguard Worker   for (ch = 0; ch < numChannels; ch++) {
656*e5436536SAndroid Build Coastguard Worker     const PCM_DEC *pIn = &pTimeData[ch * s1];
657*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
658*e5436536SAndroid Build Coastguard Worker       pTimeDataFlush[ch][i] = *pIn;
659*e5436536SAndroid Build Coastguard Worker       pIn += s2;
660*e5436536SAndroid Build Coastguard Worker     }
661*e5436536SAndroid Build Coastguard Worker   }
662*e5436536SAndroid Build Coastguard Worker 
663*e5436536SAndroid Build Coastguard Worker   return ErrorStatus;
664*e5436536SAndroid Build Coastguard Worker }
665*e5436536SAndroid Build Coastguard Worker 
666*e5436536SAndroid Build Coastguard Worker /*!
667*e5436536SAndroid Build Coastguard Worker   \brief Applies crossfade for USAC DASH IPF config change
668*e5436536SAndroid Build Coastguard Worker 
669*e5436536SAndroid Build Coastguard Worker   \pTimeData             Pointer to time data
670*e5436536SAndroid Build Coastguard Worker   \pTimeDataFlush        Pointer to flushed time data
671*e5436536SAndroid Build Coastguard Worker   \numChannels           Number of channels
672*e5436536SAndroid Build Coastguard Worker   \frameSize             Size of frame
673*e5436536SAndroid Build Coastguard Worker   \interleaved           Indicates if time data is interleaved
674*e5436536SAndroid Build Coastguard Worker 
675*e5436536SAndroid Build Coastguard Worker   \return  Error code
676*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_ApplyCrossFade(PCM_DEC * pTimeData,PCM_DEC ** pTimeDataFlush,const INT numChannels,const INT frameSize,const INT interleaved)677*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
678*e5436536SAndroid Build Coastguard Worker     PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
679*e5436536SAndroid Build Coastguard Worker     const INT frameSize, const INT interleaved) {
680*e5436536SAndroid Build Coastguard Worker   int i, ch, s1, s2;
681*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR ErrorStatus;
682*e5436536SAndroid Build Coastguard Worker 
683*e5436536SAndroid Build Coastguard Worker   ErrorStatus = AAC_DEC_OK;
684*e5436536SAndroid Build Coastguard Worker 
685*e5436536SAndroid Build Coastguard Worker   if (interleaved) {
686*e5436536SAndroid Build Coastguard Worker     s1 = 1;
687*e5436536SAndroid Build Coastguard Worker     s2 = numChannels;
688*e5436536SAndroid Build Coastguard Worker   } else {
689*e5436536SAndroid Build Coastguard Worker     s1 = frameSize;
690*e5436536SAndroid Build Coastguard Worker     s2 = 1;
691*e5436536SAndroid Build Coastguard Worker   }
692*e5436536SAndroid Build Coastguard Worker 
693*e5436536SAndroid Build Coastguard Worker   for (ch = 0; ch < numChannels; ch++) {
694*e5436536SAndroid Build Coastguard Worker     PCM_DEC *pIn = &pTimeData[ch * s1];
695*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
696*e5436536SAndroid Build Coastguard Worker       FIXP_SGL alpha = (FIXP_SGL)i
697*e5436536SAndroid Build Coastguard Worker                        << (FRACT_BITS - 1 - TIME_DATA_FLUSH_SIZE_SF);
698*e5436536SAndroid Build Coastguard Worker       FIXP_DBL time = PCM_DEC2FIXP_DBL(*pIn);
699*e5436536SAndroid Build Coastguard Worker       FIXP_DBL timeFlush = PCM_DEC2FIXP_DBL(pTimeDataFlush[ch][i]);
700*e5436536SAndroid Build Coastguard Worker 
701*e5436536SAndroid Build Coastguard Worker       *pIn = FIXP_DBL2PCM_DEC(timeFlush - fMult(timeFlush, alpha) +
702*e5436536SAndroid Build Coastguard Worker                               fMult(time, alpha));
703*e5436536SAndroid Build Coastguard Worker       pIn += s2;
704*e5436536SAndroid Build Coastguard Worker     }
705*e5436536SAndroid Build Coastguard Worker   }
706*e5436536SAndroid Build Coastguard Worker 
707*e5436536SAndroid Build Coastguard Worker   return ErrorStatus;
708*e5436536SAndroid Build Coastguard Worker }
709*e5436536SAndroid Build Coastguard Worker 
710*e5436536SAndroid Build Coastguard Worker /*!
711*e5436536SAndroid Build Coastguard Worker   \brief Parse PreRoll Extension Payload
712*e5436536SAndroid Build Coastguard Worker 
713*e5436536SAndroid Build Coastguard Worker   \self             Handle of AAC decoder
714*e5436536SAndroid Build Coastguard Worker   \numPrerollAU     Number of preRoll AUs
715*e5436536SAndroid Build Coastguard Worker   \prerollAUOffset  Offset to each preRoll AU
716*e5436536SAndroid Build Coastguard Worker   \prerollAULength  Length of each preRoll AU
717*e5436536SAndroid Build Coastguard Worker 
718*e5436536SAndroid Build Coastguard Worker   \return  Error code
719*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_PreRollExtensionPayloadParse(HANDLE_AACDECODER self,UINT * numPrerollAU,UINT * prerollAUOffset,UINT * prerollAULength)720*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse(
721*e5436536SAndroid Build Coastguard Worker     HANDLE_AACDECODER self, UINT *numPrerollAU, UINT *prerollAUOffset,
722*e5436536SAndroid Build Coastguard Worker     UINT *prerollAULength) {
723*e5436536SAndroid Build Coastguard Worker   FDK_BITSTREAM bs;
724*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs;
725*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR ErrorStatus;
726*e5436536SAndroid Build Coastguard Worker 
727*e5436536SAndroid Build Coastguard Worker   INT auStartAnchor;
728*e5436536SAndroid Build Coastguard Worker   UINT independencyFlag;
729*e5436536SAndroid Build Coastguard Worker   UINT extPayloadPresentFlag;
730*e5436536SAndroid Build Coastguard Worker   UINT useDefaultLengthFlag;
731*e5436536SAndroid Build Coastguard Worker   UINT configLength = 0;
732*e5436536SAndroid Build Coastguard Worker   UINT preRollPossible = 1;
733*e5436536SAndroid Build Coastguard Worker   UINT i;
734*e5436536SAndroid Build Coastguard Worker   UCHAR configChanged = 0;
735*e5436536SAndroid Build Coastguard Worker   UCHAR config[TP_USAC_MAX_CONFIG_LEN] = {0};
736*e5436536SAndroid Build Coastguard Worker   UCHAR
737*e5436536SAndroid Build Coastguard Worker   implicitExplicitCfgDiff = 0; /* in case implicit and explicit config is
738*e5436536SAndroid Build Coastguard Worker                                   equal preroll AU's should be processed
739*e5436536SAndroid Build Coastguard Worker                                   after decoder reset */
740*e5436536SAndroid Build Coastguard Worker 
741*e5436536SAndroid Build Coastguard Worker   ErrorStatus = AAC_DEC_OK;
742*e5436536SAndroid Build Coastguard Worker 
743*e5436536SAndroid Build Coastguard Worker   hBs = transportDec_GetBitstream(self->hInput, 0);
744*e5436536SAndroid Build Coastguard Worker   bs = *hBs;
745*e5436536SAndroid Build Coastguard Worker 
746*e5436536SAndroid Build Coastguard Worker   auStartAnchor = (INT)FDKgetValidBits(hBs);
747*e5436536SAndroid Build Coastguard Worker   if (auStartAnchor <= 0) {
748*e5436536SAndroid Build Coastguard Worker     ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS;
749*e5436536SAndroid Build Coastguard Worker     goto bail;
750*e5436536SAndroid Build Coastguard Worker   }
751*e5436536SAndroid Build Coastguard Worker 
752*e5436536SAndroid Build Coastguard Worker   /* Independency flag */
753*e5436536SAndroid Build Coastguard Worker   FDKreadBit(hBs);
754*e5436536SAndroid Build Coastguard Worker 
755*e5436536SAndroid Build Coastguard Worker   /* Payload present flag of extension ID_EXT_ELE_AUDIOPREROLL must be one */
756*e5436536SAndroid Build Coastguard Worker   extPayloadPresentFlag = FDKreadBits(hBs, 1);
757*e5436536SAndroid Build Coastguard Worker   if (!extPayloadPresentFlag) {
758*e5436536SAndroid Build Coastguard Worker     preRollPossible = 0;
759*e5436536SAndroid Build Coastguard Worker   }
760*e5436536SAndroid Build Coastguard Worker 
761*e5436536SAndroid Build Coastguard Worker   /* Default length flag of extension ID_EXT_ELE_AUDIOPREROLL must be zero */
762*e5436536SAndroid Build Coastguard Worker   useDefaultLengthFlag = FDKreadBits(hBs, 1);
763*e5436536SAndroid Build Coastguard Worker   if (useDefaultLengthFlag) {
764*e5436536SAndroid Build Coastguard Worker     preRollPossible = 0;
765*e5436536SAndroid Build Coastguard Worker   }
766*e5436536SAndroid Build Coastguard Worker 
767*e5436536SAndroid Build Coastguard Worker   if (preRollPossible) { /* extPayloadPresentFlag && !useDefaultLengthFlag */
768*e5436536SAndroid Build Coastguard Worker     /* Read overall ext payload length, useDefaultLengthFlag must be zero.  */
769*e5436536SAndroid Build Coastguard Worker     escapedValue(hBs, 8, 16, 0);
770*e5436536SAndroid Build Coastguard Worker 
771*e5436536SAndroid Build Coastguard Worker     /* Read RSVD60 Config size */
772*e5436536SAndroid Build Coastguard Worker     configLength = escapedValue(hBs, 4, 4, 8);
773*e5436536SAndroid Build Coastguard Worker 
774*e5436536SAndroid Build Coastguard Worker     /* Avoid decoding pre roll frames if there was no config change and no
775*e5436536SAndroid Build Coastguard Worker      * config is included in the pre roll ext payload. */
776*e5436536SAndroid Build Coastguard Worker   }
777*e5436536SAndroid Build Coastguard Worker 
778*e5436536SAndroid Build Coastguard Worker   /* If pre roll not possible then exit. */
779*e5436536SAndroid Build Coastguard Worker   if (preRollPossible == 0) {
780*e5436536SAndroid Build Coastguard Worker     /* Sanity check: if flushing is switched on, preRollPossible must be 1 */
781*e5436536SAndroid Build Coastguard Worker     if (self->flushStatus != AACDEC_FLUSH_OFF) {
782*e5436536SAndroid Build Coastguard Worker       /* Mismatch of current payload and flushing status */
783*e5436536SAndroid Build Coastguard Worker       self->flushStatus = AACDEC_FLUSH_OFF;
784*e5436536SAndroid Build Coastguard Worker       ErrorStatus = AAC_DEC_PARSE_ERROR;
785*e5436536SAndroid Build Coastguard Worker     }
786*e5436536SAndroid Build Coastguard Worker     goto bail;
787*e5436536SAndroid Build Coastguard Worker   }
788*e5436536SAndroid Build Coastguard Worker 
789*e5436536SAndroid Build Coastguard Worker   if (self->flags[0] & AC_USAC) {
790*e5436536SAndroid Build Coastguard Worker     if (configLength > 0) {
791*e5436536SAndroid Build Coastguard Worker       /* DASH IPF USAC Config Change: Read new config and compare with current
792*e5436536SAndroid Build Coastguard Worker        * config. Apply reconfiguration if config's are different. */
793*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < configLength; i++) {
794*e5436536SAndroid Build Coastguard Worker         config[i] = FDKreadBits(hBs, 8);
795*e5436536SAndroid Build Coastguard Worker       }
796*e5436536SAndroid Build Coastguard Worker       TRANSPORTDEC_ERROR terr;
797*e5436536SAndroid Build Coastguard Worker       terr = transportDec_InBandConfig(self->hInput, config, configLength,
798*e5436536SAndroid Build Coastguard Worker                                        self->buildUpStatus, &configChanged, 0,
799*e5436536SAndroid Build Coastguard Worker                                        &implicitExplicitCfgDiff);
800*e5436536SAndroid Build Coastguard Worker       if (terr != TRANSPORTDEC_OK) {
801*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_PARSE_ERROR;
802*e5436536SAndroid Build Coastguard Worker         goto bail;
803*e5436536SAndroid Build Coastguard Worker       }
804*e5436536SAndroid Build Coastguard Worker     }
805*e5436536SAndroid Build Coastguard Worker   }
806*e5436536SAndroid Build Coastguard Worker 
807*e5436536SAndroid Build Coastguard Worker   /* For the first frame buildUpStatus is not set and no flushing is performed
808*e5436536SAndroid Build Coastguard Worker    * but preroll AU's should processed. */
809*e5436536SAndroid Build Coastguard Worker   /* For USAC there is no idle state. */
810*e5436536SAndroid Build Coastguard Worker   if ((self->streamInfo.numChannels == 0) && !implicitExplicitCfgDiff &&
811*e5436536SAndroid Build Coastguard Worker       (self->flags[0] & AC_USAC)) {
812*e5436536SAndroid Build Coastguard Worker     self->buildUpStatus = AACDEC_USAC_BUILD_UP_ON;
813*e5436536SAndroid Build Coastguard Worker     /* sanity check: if buildUp status on -> flushing must be off */
814*e5436536SAndroid Build Coastguard Worker     if (self->flushStatus != AACDEC_FLUSH_OFF) {
815*e5436536SAndroid Build Coastguard Worker       self->flushStatus = AACDEC_FLUSH_OFF;
816*e5436536SAndroid Build Coastguard Worker       ErrorStatus = AAC_DEC_PARSE_ERROR;
817*e5436536SAndroid Build Coastguard Worker       goto bail;
818*e5436536SAndroid Build Coastguard Worker     }
819*e5436536SAndroid Build Coastguard Worker   }
820*e5436536SAndroid Build Coastguard Worker 
821*e5436536SAndroid Build Coastguard Worker   if (self->flags[0] & AC_USAC) {
822*e5436536SAndroid Build Coastguard Worker     /* We are interested in preroll AUs if an explicit or an implicit config
823*e5436536SAndroid Build Coastguard Worker      * change is signalized in other words if the build up status is set. */
824*e5436536SAndroid Build Coastguard Worker     if (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON) {
825*e5436536SAndroid Build Coastguard Worker       UCHAR applyCrossfade = FDKreadBit(hBs);
826*e5436536SAndroid Build Coastguard Worker       if (applyCrossfade) {
827*e5436536SAndroid Build Coastguard Worker         self->applyCrossfade |= AACDEC_CROSSFADE_BITMASK_PREROLL;
828*e5436536SAndroid Build Coastguard Worker       } else {
829*e5436536SAndroid Build Coastguard Worker         self->applyCrossfade &= ~AACDEC_CROSSFADE_BITMASK_PREROLL;
830*e5436536SAndroid Build Coastguard Worker       }
831*e5436536SAndroid Build Coastguard Worker       FDKreadBit(hBs); /* reserved */
832*e5436536SAndroid Build Coastguard Worker       /* Read num preroll AU's */
833*e5436536SAndroid Build Coastguard Worker       *numPrerollAU = escapedValue(hBs, 2, 4, 0);
834*e5436536SAndroid Build Coastguard Worker       /* check limits for USAC */
835*e5436536SAndroid Build Coastguard Worker       if (*numPrerollAU > AACDEC_MAX_NUM_PREROLL_AU_USAC) {
836*e5436536SAndroid Build Coastguard Worker         *numPrerollAU = 0;
837*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_PARSE_ERROR;
838*e5436536SAndroid Build Coastguard Worker         goto bail;
839*e5436536SAndroid Build Coastguard Worker       }
840*e5436536SAndroid Build Coastguard Worker     }
841*e5436536SAndroid Build Coastguard Worker   }
842*e5436536SAndroid Build Coastguard Worker 
843*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < *numPrerollAU; i++) {
844*e5436536SAndroid Build Coastguard Worker     /* For every AU get length and offset in the bitstream */
845*e5436536SAndroid Build Coastguard Worker     prerollAULength[i] = escapedValue(hBs, 16, 16, 0);
846*e5436536SAndroid Build Coastguard Worker     if (prerollAULength[i] > 0) {
847*e5436536SAndroid Build Coastguard Worker       prerollAUOffset[i] = auStartAnchor - (INT)FDKgetValidBits(hBs);
848*e5436536SAndroid Build Coastguard Worker       independencyFlag = FDKreadBit(hBs);
849*e5436536SAndroid Build Coastguard Worker       if (i == 0 && !independencyFlag) {
850*e5436536SAndroid Build Coastguard Worker         *numPrerollAU = 0;
851*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_PARSE_ERROR;
852*e5436536SAndroid Build Coastguard Worker         goto bail;
853*e5436536SAndroid Build Coastguard Worker       }
854*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, prerollAULength[i] * 8 - 1);
855*e5436536SAndroid Build Coastguard Worker       self->prerollAULength[i] = (prerollAULength[i] * 8) + prerollAUOffset[i];
856*e5436536SAndroid Build Coastguard Worker     } else {
857*e5436536SAndroid Build Coastguard Worker       *numPrerollAU = 0;
858*e5436536SAndroid Build Coastguard Worker       ErrorStatus = AAC_DEC_PARSE_ERROR; /* Something is wrong */
859*e5436536SAndroid Build Coastguard Worker       goto bail;
860*e5436536SAndroid Build Coastguard Worker     }
861*e5436536SAndroid Build Coastguard Worker   }
862*e5436536SAndroid Build Coastguard Worker 
863*e5436536SAndroid Build Coastguard Worker bail:
864*e5436536SAndroid Build Coastguard Worker 
865*e5436536SAndroid Build Coastguard Worker   *hBs = bs;
866*e5436536SAndroid Build Coastguard Worker 
867*e5436536SAndroid Build Coastguard Worker   return ErrorStatus;
868*e5436536SAndroid Build Coastguard Worker }
869*e5436536SAndroid Build Coastguard Worker 
870*e5436536SAndroid Build Coastguard Worker /*!
871*e5436536SAndroid Build Coastguard Worker   \brief Parse Extension Payload
872*e5436536SAndroid Build Coastguard Worker 
873*e5436536SAndroid Build Coastguard Worker   \self Handle of AAC decoder
874*e5436536SAndroid Build Coastguard Worker   \count Pointer to bit counter.
875*e5436536SAndroid Build Coastguard Worker   \previous_element ID of previous element (required by some extension payloads)
876*e5436536SAndroid Build Coastguard Worker 
877*e5436536SAndroid Build Coastguard Worker   \return  Error code
878*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_ExtPayloadParse(HANDLE_AACDECODER self,HANDLE_FDK_BITSTREAM hBs,int * count,MP4_ELEMENT_ID previous_element,int elIndex,int fIsFillElement)879*e5436536SAndroid Build Coastguard Worker static AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse(
880*e5436536SAndroid Build Coastguard Worker     HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM hBs, int *count,
881*e5436536SAndroid Build Coastguard Worker     MP4_ELEMENT_ID previous_element, int elIndex, int fIsFillElement) {
882*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR error = AAC_DEC_OK;
883*e5436536SAndroid Build Coastguard Worker   EXT_PAYLOAD_TYPE extension_type;
884*e5436536SAndroid Build Coastguard Worker   int bytes = (*count) >> 3;
885*e5436536SAndroid Build Coastguard Worker   int crcFlag = 0;
886*e5436536SAndroid Build Coastguard Worker 
887*e5436536SAndroid Build Coastguard Worker   if (*count < 4) {
888*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_PARSE_ERROR;
889*e5436536SAndroid Build Coastguard Worker   } else if ((INT)FDKgetValidBits(hBs) < *count) {
890*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_DECODE_FRAME_ERROR;
891*e5436536SAndroid Build Coastguard Worker   }
892*e5436536SAndroid Build Coastguard Worker 
893*e5436536SAndroid Build Coastguard Worker   extension_type =
894*e5436536SAndroid Build Coastguard Worker       (EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4); /* bs_extension_type */
895*e5436536SAndroid Build Coastguard Worker   *count -= 4;
896*e5436536SAndroid Build Coastguard Worker 
897*e5436536SAndroid Build Coastguard Worker   /* For ELD, the SBR signaling is explicit and parsed in
898*e5436536SAndroid Build Coastguard Worker      aacDecoder_ParseExplicitMpsAndSbr(), therefore skip SBR if implicit
899*e5436536SAndroid Build Coastguard Worker      present. */
900*e5436536SAndroid Build Coastguard Worker   if ((self->flags[0] & AC_ELD) && ((extension_type == EXT_SBR_DATA_CRC) ||
901*e5436536SAndroid Build Coastguard Worker                                     (extension_type == EXT_SBR_DATA))) {
902*e5436536SAndroid Build Coastguard Worker     extension_type = EXT_FIL; /* skip sbr data */
903*e5436536SAndroid Build Coastguard Worker   }
904*e5436536SAndroid Build Coastguard Worker 
905*e5436536SAndroid Build Coastguard Worker   switch (extension_type) {
906*e5436536SAndroid Build Coastguard Worker     case EXT_DYNAMIC_RANGE: {
907*e5436536SAndroid Build Coastguard Worker       INT readBits =
908*e5436536SAndroid Build Coastguard Worker           aacDecoder_drcMarkPayload(self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA);
909*e5436536SAndroid Build Coastguard Worker 
910*e5436536SAndroid Build Coastguard Worker       if (readBits > *count) { /* Read too much. Something went wrong! */
911*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
912*e5436536SAndroid Build Coastguard Worker       }
913*e5436536SAndroid Build Coastguard Worker       *count -= readBits;
914*e5436536SAndroid Build Coastguard Worker     } break;
915*e5436536SAndroid Build Coastguard Worker     case EXT_LDSAC_DATA:
916*e5436536SAndroid Build Coastguard Worker     case EXT_SAC_DATA:
917*e5436536SAndroid Build Coastguard Worker       /* Read MPEG Surround Extension payload */
918*e5436536SAndroid Build Coastguard Worker       {
919*e5436536SAndroid Build Coastguard Worker         int err, mpsSampleRate, mpsFrameSize;
920*e5436536SAndroid Build Coastguard Worker 
921*e5436536SAndroid Build Coastguard Worker         if (self->flags[0] & AC_PS_PRESENT) {
922*e5436536SAndroid Build Coastguard Worker           error = AAC_DEC_PARSE_ERROR;
923*e5436536SAndroid Build Coastguard Worker           goto bail;
924*e5436536SAndroid Build Coastguard Worker         }
925*e5436536SAndroid Build Coastguard Worker 
926*e5436536SAndroid Build Coastguard Worker         /* Handle SBR dual rate case */
927*e5436536SAndroid Build Coastguard Worker         if (self->streamInfo.extSamplingRate != 0) {
928*e5436536SAndroid Build Coastguard Worker           mpsSampleRate = self->streamInfo.extSamplingRate;
929*e5436536SAndroid Build Coastguard Worker           mpsFrameSize = self->streamInfo.aacSamplesPerFrame *
930*e5436536SAndroid Build Coastguard Worker                          (self->streamInfo.extSamplingRate /
931*e5436536SAndroid Build Coastguard Worker                           self->streamInfo.aacSampleRate);
932*e5436536SAndroid Build Coastguard Worker         } else {
933*e5436536SAndroid Build Coastguard Worker           mpsSampleRate = self->streamInfo.aacSampleRate;
934*e5436536SAndroid Build Coastguard Worker           mpsFrameSize = self->streamInfo.aacSamplesPerFrame;
935*e5436536SAndroid Build Coastguard Worker         }
936*e5436536SAndroid Build Coastguard Worker         /* Setting of internal MPS state; may be reset in
937*e5436536SAndroid Build Coastguard Worker            CAacDecoder_SyncQmfMode if decoder is unable to decode with user
938*e5436536SAndroid Build Coastguard Worker            defined qmfMode */
939*e5436536SAndroid Build Coastguard Worker         if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD))) {
940*e5436536SAndroid Build Coastguard Worker           self->mpsEnableCurr = self->mpsEnableUser;
941*e5436536SAndroid Build Coastguard Worker         }
942*e5436536SAndroid Build Coastguard Worker         if (self->mpsEnableCurr) {
943*e5436536SAndroid Build Coastguard Worker           if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig) {
944*e5436536SAndroid Build Coastguard Worker             /* if not done yet, allocate full MPEG Surround decoder instance */
945*e5436536SAndroid Build Coastguard Worker             if (mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable(
946*e5436536SAndroid Build Coastguard Worker                     (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) ==
947*e5436536SAndroid Build Coastguard Worker                 SAC_INSTANCE_NOT_FULL_AVAILABLE) {
948*e5436536SAndroid Build Coastguard Worker               if (mpegSurroundDecoder_Open(
949*e5436536SAndroid Build Coastguard Worker                       (CMpegSurroundDecoder **)&self->pMpegSurroundDecoder, -1,
950*e5436536SAndroid Build Coastguard Worker                       &self->qmfDomain)) {
951*e5436536SAndroid Build Coastguard Worker                 return AAC_DEC_OUT_OF_MEMORY;
952*e5436536SAndroid Build Coastguard Worker               }
953*e5436536SAndroid Build Coastguard Worker             }
954*e5436536SAndroid Build Coastguard Worker           }
955*e5436536SAndroid Build Coastguard Worker           err = mpegSurroundDecoder_Parse(
956*e5436536SAndroid Build Coastguard Worker               (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, hBs, count,
957*e5436536SAndroid Build Coastguard Worker               self->streamInfo.aot, mpsSampleRate, mpsFrameSize,
958*e5436536SAndroid Build Coastguard Worker               self->flags[0] & AC_INDEP);
959*e5436536SAndroid Build Coastguard Worker           if (err == MPS_OK) {
960*e5436536SAndroid Build Coastguard Worker             self->flags[0] |= AC_MPS_PRESENT;
961*e5436536SAndroid Build Coastguard Worker           } else {
962*e5436536SAndroid Build Coastguard Worker             error = AAC_DEC_PARSE_ERROR;
963*e5436536SAndroid Build Coastguard Worker           }
964*e5436536SAndroid Build Coastguard Worker         }
965*e5436536SAndroid Build Coastguard Worker         /* Skip any trailing bytes */
966*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, *count);
967*e5436536SAndroid Build Coastguard Worker         *count = 0;
968*e5436536SAndroid Build Coastguard Worker       }
969*e5436536SAndroid Build Coastguard Worker       break;
970*e5436536SAndroid Build Coastguard Worker 
971*e5436536SAndroid Build Coastguard Worker     case EXT_SBR_DATA_CRC:
972*e5436536SAndroid Build Coastguard Worker       crcFlag = 1;
973*e5436536SAndroid Build Coastguard Worker       FDK_FALLTHROUGH;
974*e5436536SAndroid Build Coastguard Worker     case EXT_SBR_DATA:
975*e5436536SAndroid Build Coastguard Worker       if (IS_CHANNEL_ELEMENT(previous_element)) {
976*e5436536SAndroid Build Coastguard Worker         SBR_ERROR sbrError;
977*e5436536SAndroid Build Coastguard Worker         UCHAR configMode = 0;
978*e5436536SAndroid Build Coastguard Worker         UCHAR configChanged = 0;
979*e5436536SAndroid Build Coastguard Worker 
980*e5436536SAndroid Build Coastguard Worker         CAacDecoder_SyncQmfMode(self);
981*e5436536SAndroid Build Coastguard Worker 
982*e5436536SAndroid Build Coastguard Worker         configMode |= AC_CM_ALLOC_MEM;
983*e5436536SAndroid Build Coastguard Worker 
984*e5436536SAndroid Build Coastguard Worker         sbrError = sbrDecoder_InitElement(
985*e5436536SAndroid Build Coastguard Worker             self->hSbrDecoder, self->streamInfo.aacSampleRate,
986*e5436536SAndroid Build Coastguard Worker             self->streamInfo.extSamplingRate,
987*e5436536SAndroid Build Coastguard Worker             self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot,
988*e5436536SAndroid Build Coastguard Worker             previous_element, elIndex,
989*e5436536SAndroid Build Coastguard Worker             2, /* Signalize that harmonicSBR shall be ignored in the config
990*e5436536SAndroid Build Coastguard Worker                   change detection */
991*e5436536SAndroid Build Coastguard Worker             0, configMode, &configChanged, self->downscaleFactor);
992*e5436536SAndroid Build Coastguard Worker 
993*e5436536SAndroid Build Coastguard Worker         if (sbrError == SBRDEC_OK) {
994*e5436536SAndroid Build Coastguard Worker           sbrError = sbrDecoder_Parse(self->hSbrDecoder, hBs,
995*e5436536SAndroid Build Coastguard Worker                                       self->pDrmBsBuffer, self->drmBsBufferSize,
996*e5436536SAndroid Build Coastguard Worker                                       count, *count, crcFlag, previous_element,
997*e5436536SAndroid Build Coastguard Worker                                       elIndex, self->flags[0], self->elFlags);
998*e5436536SAndroid Build Coastguard Worker           /* Enable SBR for implicit SBR signalling but only if no severe error
999*e5436536SAndroid Build Coastguard Worker            * happend. */
1000*e5436536SAndroid Build Coastguard Worker           if ((sbrError == SBRDEC_OK) || (sbrError == SBRDEC_PARSE_ERROR)) {
1001*e5436536SAndroid Build Coastguard Worker             self->sbrEnabled = 1;
1002*e5436536SAndroid Build Coastguard Worker           }
1003*e5436536SAndroid Build Coastguard Worker         } else {
1004*e5436536SAndroid Build Coastguard Worker           /* Do not try to apply SBR because initializing the element failed. */
1005*e5436536SAndroid Build Coastguard Worker           self->sbrEnabled = 0;
1006*e5436536SAndroid Build Coastguard Worker         }
1007*e5436536SAndroid Build Coastguard Worker         /* Citation from ISO/IEC 14496-3 chapter 4.5.2.1.5.2
1008*e5436536SAndroid Build Coastguard Worker         Fill elements containing an extension_payload() with an extension_type
1009*e5436536SAndroid Build Coastguard Worker         of EXT_SBR_DATA or EXT_SBR_DATA_CRC shall not contain any other
1010*e5436536SAndroid Build Coastguard Worker         extension_payload of any other extension_type.
1011*e5436536SAndroid Build Coastguard Worker         */
1012*e5436536SAndroid Build Coastguard Worker         if (fIsFillElement) {
1013*e5436536SAndroid Build Coastguard Worker           FDKpushBiDirectional(hBs, *count);
1014*e5436536SAndroid Build Coastguard Worker           *count = 0;
1015*e5436536SAndroid Build Coastguard Worker         } else {
1016*e5436536SAndroid Build Coastguard Worker           /* If this is not a fill element with a known length, we are screwed
1017*e5436536SAndroid Build Coastguard Worker            * and further parsing makes no sense. */
1018*e5436536SAndroid Build Coastguard Worker           if (sbrError != SBRDEC_OK) {
1019*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
1020*e5436536SAndroid Build Coastguard Worker           }
1021*e5436536SAndroid Build Coastguard Worker         }
1022*e5436536SAndroid Build Coastguard Worker       } else {
1023*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
1024*e5436536SAndroid Build Coastguard Worker       }
1025*e5436536SAndroid Build Coastguard Worker       break;
1026*e5436536SAndroid Build Coastguard Worker 
1027*e5436536SAndroid Build Coastguard Worker     case EXT_FILL_DATA: {
1028*e5436536SAndroid Build Coastguard Worker       int temp;
1029*e5436536SAndroid Build Coastguard Worker 
1030*e5436536SAndroid Build Coastguard Worker       temp = FDKreadBits(hBs, 4);
1031*e5436536SAndroid Build Coastguard Worker       bytes--;
1032*e5436536SAndroid Build Coastguard Worker       if (temp != 0) {
1033*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
1034*e5436536SAndroid Build Coastguard Worker         break;
1035*e5436536SAndroid Build Coastguard Worker       }
1036*e5436536SAndroid Build Coastguard Worker       while (bytes > 0) {
1037*e5436536SAndroid Build Coastguard Worker         temp = FDKreadBits(hBs, 8);
1038*e5436536SAndroid Build Coastguard Worker         bytes--;
1039*e5436536SAndroid Build Coastguard Worker         if (temp != 0xa5) {
1040*e5436536SAndroid Build Coastguard Worker           error = AAC_DEC_PARSE_ERROR;
1041*e5436536SAndroid Build Coastguard Worker           break;
1042*e5436536SAndroid Build Coastguard Worker         }
1043*e5436536SAndroid Build Coastguard Worker       }
1044*e5436536SAndroid Build Coastguard Worker       *count = bytes << 3;
1045*e5436536SAndroid Build Coastguard Worker     } break;
1046*e5436536SAndroid Build Coastguard Worker 
1047*e5436536SAndroid Build Coastguard Worker     case EXT_DATA_ELEMENT: {
1048*e5436536SAndroid Build Coastguard Worker       int dataElementVersion;
1049*e5436536SAndroid Build Coastguard Worker 
1050*e5436536SAndroid Build Coastguard Worker       dataElementVersion = FDKreadBits(hBs, 4);
1051*e5436536SAndroid Build Coastguard Worker       *count -= 4;
1052*e5436536SAndroid Build Coastguard Worker       if (dataElementVersion == 0) /* ANC_DATA */
1053*e5436536SAndroid Build Coastguard Worker       {
1054*e5436536SAndroid Build Coastguard Worker         int temp, dataElementLength = 0;
1055*e5436536SAndroid Build Coastguard Worker         do {
1056*e5436536SAndroid Build Coastguard Worker           temp = FDKreadBits(hBs, 8);
1057*e5436536SAndroid Build Coastguard Worker           *count -= 8;
1058*e5436536SAndroid Build Coastguard Worker           dataElementLength += temp;
1059*e5436536SAndroid Build Coastguard Worker         } while (temp == 255);
1060*e5436536SAndroid Build Coastguard Worker 
1061*e5436536SAndroid Build Coastguard Worker         CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength);
1062*e5436536SAndroid Build Coastguard Worker         *count -= (dataElementLength << 3);
1063*e5436536SAndroid Build Coastguard Worker       } else {
1064*e5436536SAndroid Build Coastguard Worker         /* align = 0 */
1065*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
1066*e5436536SAndroid Build Coastguard Worker         goto bail;
1067*e5436536SAndroid Build Coastguard Worker       }
1068*e5436536SAndroid Build Coastguard Worker     } break;
1069*e5436536SAndroid Build Coastguard Worker 
1070*e5436536SAndroid Build Coastguard Worker     case EXT_DATA_LENGTH:
1071*e5436536SAndroid Build Coastguard Worker       if (!fIsFillElement /* Makes no sens to have an additional length in a
1072*e5436536SAndroid Build Coastguard Worker                              fill ...   */
1073*e5436536SAndroid Build Coastguard Worker           &&
1074*e5436536SAndroid Build Coastguard Worker           (self->flags[0] &
1075*e5436536SAndroid Build Coastguard Worker            AC_ER)) /* ... element because this extension payload type was ... */
1076*e5436536SAndroid Build Coastguard Worker       { /* ... created to circumvent the missing length in ER-Syntax. */
1077*e5436536SAndroid Build Coastguard Worker         int bitCnt, len = FDKreadBits(hBs, 4);
1078*e5436536SAndroid Build Coastguard Worker         *count -= 4;
1079*e5436536SAndroid Build Coastguard Worker 
1080*e5436536SAndroid Build Coastguard Worker         if (len == 15) {
1081*e5436536SAndroid Build Coastguard Worker           int add_len = FDKreadBits(hBs, 8);
1082*e5436536SAndroid Build Coastguard Worker           *count -= 8;
1083*e5436536SAndroid Build Coastguard Worker           len += add_len;
1084*e5436536SAndroid Build Coastguard Worker 
1085*e5436536SAndroid Build Coastguard Worker           if (add_len == 255) {
1086*e5436536SAndroid Build Coastguard Worker             len += FDKreadBits(hBs, 16);
1087*e5436536SAndroid Build Coastguard Worker             *count -= 16;
1088*e5436536SAndroid Build Coastguard Worker           }
1089*e5436536SAndroid Build Coastguard Worker         }
1090*e5436536SAndroid Build Coastguard Worker         len <<= 3;
1091*e5436536SAndroid Build Coastguard Worker         bitCnt = len;
1092*e5436536SAndroid Build Coastguard Worker 
1093*e5436536SAndroid Build Coastguard Worker         if ((EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4) == EXT_DATA_LENGTH) {
1094*e5436536SAndroid Build Coastguard Worker           /* Check NOTE 2: The extension_payload() included here must
1095*e5436536SAndroid Build Coastguard Worker                            not have extension_type == EXT_DATA_LENGTH. */
1096*e5436536SAndroid Build Coastguard Worker           error = AAC_DEC_PARSE_ERROR;
1097*e5436536SAndroid Build Coastguard Worker           goto bail;
1098*e5436536SAndroid Build Coastguard Worker         } else {
1099*e5436536SAndroid Build Coastguard Worker           /* rewind and call myself again. */
1100*e5436536SAndroid Build Coastguard Worker           FDKpushBack(hBs, 4);
1101*e5436536SAndroid Build Coastguard Worker 
1102*e5436536SAndroid Build Coastguard Worker           error = CAacDecoder_ExtPayloadParse(
1103*e5436536SAndroid Build Coastguard Worker               self, hBs, &bitCnt, previous_element, elIndex,
1104*e5436536SAndroid Build Coastguard Worker               1); /* Treat same as fill element */
1105*e5436536SAndroid Build Coastguard Worker 
1106*e5436536SAndroid Build Coastguard Worker           *count -= len - bitCnt;
1107*e5436536SAndroid Build Coastguard Worker         }
1108*e5436536SAndroid Build Coastguard Worker         /* Note: the fall through in case the if statement above is not taken is
1109*e5436536SAndroid Build Coastguard Worker          * intentional. */
1110*e5436536SAndroid Build Coastguard Worker         break;
1111*e5436536SAndroid Build Coastguard Worker       }
1112*e5436536SAndroid Build Coastguard Worker       FDK_FALLTHROUGH;
1113*e5436536SAndroid Build Coastguard Worker 
1114*e5436536SAndroid Build Coastguard Worker     case EXT_FIL:
1115*e5436536SAndroid Build Coastguard Worker 
1116*e5436536SAndroid Build Coastguard Worker     default:
1117*e5436536SAndroid Build Coastguard Worker       /* align = 4 */
1118*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, *count);
1119*e5436536SAndroid Build Coastguard Worker       *count = 0;
1120*e5436536SAndroid Build Coastguard Worker       break;
1121*e5436536SAndroid Build Coastguard Worker   }
1122*e5436536SAndroid Build Coastguard Worker 
1123*e5436536SAndroid Build Coastguard Worker bail:
1124*e5436536SAndroid Build Coastguard Worker   if ((error != AAC_DEC_OK) &&
1125*e5436536SAndroid Build Coastguard Worker       fIsFillElement) { /* Skip the remaining extension bytes */
1126*e5436536SAndroid Build Coastguard Worker     FDKpushBiDirectional(hBs, *count);
1127*e5436536SAndroid Build Coastguard Worker     *count = 0;
1128*e5436536SAndroid Build Coastguard Worker     /* Patch error code because decoding can go on. */
1129*e5436536SAndroid Build Coastguard Worker     error = AAC_DEC_OK;
1130*e5436536SAndroid Build Coastguard Worker     /* Be sure that parsing errors have been stored. */
1131*e5436536SAndroid Build Coastguard Worker   }
1132*e5436536SAndroid Build Coastguard Worker   return error;
1133*e5436536SAndroid Build Coastguard Worker }
1134*e5436536SAndroid Build Coastguard Worker 
aacDecoder_ParseExplicitMpsAndSbr(HANDLE_AACDECODER self,HANDLE_FDK_BITSTREAM bs,const MP4_ELEMENT_ID previous_element,const int previous_element_index,const int element_index,const int el_cnt[])1135*e5436536SAndroid Build Coastguard Worker static AAC_DECODER_ERROR aacDecoder_ParseExplicitMpsAndSbr(
1136*e5436536SAndroid Build Coastguard Worker     HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM bs,
1137*e5436536SAndroid Build Coastguard Worker     const MP4_ELEMENT_ID previous_element, const int previous_element_index,
1138*e5436536SAndroid Build Coastguard Worker     const int element_index, const int el_cnt[]) {
1139*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
1140*e5436536SAndroid Build Coastguard Worker   INT bitCnt = 0;
1141*e5436536SAndroid Build Coastguard Worker 
1142*e5436536SAndroid Build Coastguard Worker   /* get the remaining bits of this frame */
1143*e5436536SAndroid Build Coastguard Worker   bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0);
1144*e5436536SAndroid Build Coastguard Worker 
1145*e5436536SAndroid Build Coastguard Worker   if ((self->flags[0] & AC_SBR_PRESENT) &&
1146*e5436536SAndroid Build Coastguard Worker       (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD | AC_DRM))) {
1147*e5436536SAndroid Build Coastguard Worker     SBR_ERROR err = SBRDEC_OK;
1148*e5436536SAndroid Build Coastguard Worker     int chElIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE] +
1149*e5436536SAndroid Build Coastguard Worker                                  el_cnt[ID_LFE] + el_cnt[ID_USAC_SCE] +
1150*e5436536SAndroid Build Coastguard Worker                                  el_cnt[ID_USAC_CPE] + el_cnt[ID_USAC_LFE];
1151*e5436536SAndroid Build Coastguard Worker     INT bitCntTmp = bitCnt;
1152*e5436536SAndroid Build Coastguard Worker 
1153*e5436536SAndroid Build Coastguard Worker     if (self->flags[0] & AC_USAC) {
1154*e5436536SAndroid Build Coastguard Worker       chElIdx = numChElements - 1;
1155*e5436536SAndroid Build Coastguard Worker     } else {
1156*e5436536SAndroid Build Coastguard Worker       chElIdx = 0; /* ELD case */
1157*e5436536SAndroid Build Coastguard Worker     }
1158*e5436536SAndroid Build Coastguard Worker 
1159*e5436536SAndroid Build Coastguard Worker     for (; chElIdx < numChElements; chElIdx += 1) {
1160*e5436536SAndroid Build Coastguard Worker       MP4_ELEMENT_ID sbrType;
1161*e5436536SAndroid Build Coastguard Worker       SBR_ERROR errTmp;
1162*e5436536SAndroid Build Coastguard Worker       if (self->flags[0] & (AC_USAC)) {
1163*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT((self->elements[element_index] == ID_USAC_SCE) ||
1164*e5436536SAndroid Build Coastguard Worker                    (self->elements[element_index] == ID_USAC_CPE));
1165*e5436536SAndroid Build Coastguard Worker         sbrType = IS_STEREO_SBR(self->elements[element_index],
1166*e5436536SAndroid Build Coastguard Worker                                 self->usacStereoConfigIndex[element_index])
1167*e5436536SAndroid Build Coastguard Worker                       ? ID_CPE
1168*e5436536SAndroid Build Coastguard Worker                       : ID_SCE;
1169*e5436536SAndroid Build Coastguard Worker       } else
1170*e5436536SAndroid Build Coastguard Worker         sbrType = self->elements[chElIdx];
1171*e5436536SAndroid Build Coastguard Worker       errTmp = sbrDecoder_Parse(self->hSbrDecoder, bs, self->pDrmBsBuffer,
1172*e5436536SAndroid Build Coastguard Worker                                 self->drmBsBufferSize, &bitCnt, -1,
1173*e5436536SAndroid Build Coastguard Worker                                 self->flags[0] & AC_SBRCRC, sbrType, chElIdx,
1174*e5436536SAndroid Build Coastguard Worker                                 self->flags[0], self->elFlags);
1175*e5436536SAndroid Build Coastguard Worker       if (errTmp != SBRDEC_OK) {
1176*e5436536SAndroid Build Coastguard Worker         err = errTmp;
1177*e5436536SAndroid Build Coastguard Worker         bitCntTmp = bitCnt;
1178*e5436536SAndroid Build Coastguard Worker         bitCnt = 0;
1179*e5436536SAndroid Build Coastguard Worker       }
1180*e5436536SAndroid Build Coastguard Worker     }
1181*e5436536SAndroid Build Coastguard Worker     switch (err) {
1182*e5436536SAndroid Build Coastguard Worker       case SBRDEC_PARSE_ERROR:
1183*e5436536SAndroid Build Coastguard Worker         /* Can not go on parsing because we do not
1184*e5436536SAndroid Build Coastguard Worker             know the length of the SBR extension data. */
1185*e5436536SAndroid Build Coastguard Worker         FDKpushFor(bs, bitCntTmp);
1186*e5436536SAndroid Build Coastguard Worker         bitCnt = 0;
1187*e5436536SAndroid Build Coastguard Worker         break;
1188*e5436536SAndroid Build Coastguard Worker       case SBRDEC_OK:
1189*e5436536SAndroid Build Coastguard Worker         self->sbrEnabled = 1;
1190*e5436536SAndroid Build Coastguard Worker         break;
1191*e5436536SAndroid Build Coastguard Worker       default:
1192*e5436536SAndroid Build Coastguard Worker         self->frameOK = 0;
1193*e5436536SAndroid Build Coastguard Worker         break;
1194*e5436536SAndroid Build Coastguard Worker     }
1195*e5436536SAndroid Build Coastguard Worker   }
1196*e5436536SAndroid Build Coastguard Worker 
1197*e5436536SAndroid Build Coastguard Worker   if ((bitCnt > 0) && (self->flags[0] & (AC_USAC | AC_RSVD50))) {
1198*e5436536SAndroid Build Coastguard Worker     if ((self->flags[0] & AC_MPS_PRESENT) ||
1199*e5436536SAndroid Build Coastguard Worker         (self->elFlags[element_index] & AC_EL_USAC_MPS212)) {
1200*e5436536SAndroid Build Coastguard Worker       int err;
1201*e5436536SAndroid Build Coastguard Worker 
1202*e5436536SAndroid Build Coastguard Worker       err = mpegSurroundDecoder_ParseNoHeader(
1203*e5436536SAndroid Build Coastguard Worker           (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, bs, &bitCnt,
1204*e5436536SAndroid Build Coastguard Worker           self->flags[0] & AC_INDEP);
1205*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) {
1206*e5436536SAndroid Build Coastguard Worker         self->frameOK = 0;
1207*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_PARSE_ERROR;
1208*e5436536SAndroid Build Coastguard Worker       }
1209*e5436536SAndroid Build Coastguard Worker     }
1210*e5436536SAndroid Build Coastguard Worker   }
1211*e5436536SAndroid Build Coastguard Worker 
1212*e5436536SAndroid Build Coastguard Worker   if (self->flags[0] & AC_DRM) {
1213*e5436536SAndroid Build Coastguard Worker     if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) {
1214*e5436536SAndroid Build Coastguard Worker       FDKpushBiDirectional(bs, bitCnt);
1215*e5436536SAndroid Build Coastguard Worker     }
1216*e5436536SAndroid Build Coastguard Worker   }
1217*e5436536SAndroid Build Coastguard Worker 
1218*e5436536SAndroid Build Coastguard Worker   if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_DRM))) {
1219*e5436536SAndroid Build Coastguard Worker     while (bitCnt > 7) {
1220*e5436536SAndroid Build Coastguard Worker       ErrorStatus = CAacDecoder_ExtPayloadParse(
1221*e5436536SAndroid Build Coastguard Worker           self, bs, &bitCnt, previous_element, previous_element_index, 0);
1222*e5436536SAndroid Build Coastguard Worker       if (ErrorStatus != AAC_DEC_OK) {
1223*e5436536SAndroid Build Coastguard Worker         self->frameOK = 0;
1224*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_PARSE_ERROR;
1225*e5436536SAndroid Build Coastguard Worker         break;
1226*e5436536SAndroid Build Coastguard Worker       }
1227*e5436536SAndroid Build Coastguard Worker     }
1228*e5436536SAndroid Build Coastguard Worker   }
1229*e5436536SAndroid Build Coastguard Worker   return ErrorStatus;
1230*e5436536SAndroid Build Coastguard Worker }
1231*e5436536SAndroid Build Coastguard Worker 
1232*e5436536SAndroid Build Coastguard Worker /*  Stream Configuration and Information.
1233*e5436536SAndroid Build Coastguard Worker 
1234*e5436536SAndroid Build Coastguard Worker     This class holds configuration and information data for a stream to be
1235*e5436536SAndroid Build Coastguard Worker    decoded. It provides the calling application as well as the decoder with
1236*e5436536SAndroid Build Coastguard Worker    substantial information, e.g. profile, sampling rate, number of channels
1237*e5436536SAndroid Build Coastguard Worker    found in the bitstream etc.
1238*e5436536SAndroid Build Coastguard Worker */
CStreamInfoInit(CStreamInfo * pStreamInfo)1239*e5436536SAndroid Build Coastguard Worker static void CStreamInfoInit(CStreamInfo *pStreamInfo) {
1240*e5436536SAndroid Build Coastguard Worker   pStreamInfo->aacSampleRate = 0;
1241*e5436536SAndroid Build Coastguard Worker   pStreamInfo->profile = -1;
1242*e5436536SAndroid Build Coastguard Worker   pStreamInfo->aot = AOT_NONE;
1243*e5436536SAndroid Build Coastguard Worker 
1244*e5436536SAndroid Build Coastguard Worker   pStreamInfo->channelConfig = -1;
1245*e5436536SAndroid Build Coastguard Worker   pStreamInfo->bitRate = 0;
1246*e5436536SAndroid Build Coastguard Worker   pStreamInfo->aacSamplesPerFrame = 0;
1247*e5436536SAndroid Build Coastguard Worker 
1248*e5436536SAndroid Build Coastguard Worker   pStreamInfo->extAot = AOT_NONE;
1249*e5436536SAndroid Build Coastguard Worker   pStreamInfo->extSamplingRate = 0;
1250*e5436536SAndroid Build Coastguard Worker 
1251*e5436536SAndroid Build Coastguard Worker   pStreamInfo->flags = 0;
1252*e5436536SAndroid Build Coastguard Worker 
1253*e5436536SAndroid Build Coastguard Worker   pStreamInfo->epConfig = -1; /* default: no ER */
1254*e5436536SAndroid Build Coastguard Worker 
1255*e5436536SAndroid Build Coastguard Worker   pStreamInfo->numChannels = 0;
1256*e5436536SAndroid Build Coastguard Worker   pStreamInfo->sampleRate = 0;
1257*e5436536SAndroid Build Coastguard Worker   pStreamInfo->frameSize = 0;
1258*e5436536SAndroid Build Coastguard Worker 
1259*e5436536SAndroid Build Coastguard Worker   pStreamInfo->outputDelay = 0;
1260*e5436536SAndroid Build Coastguard Worker 
1261*e5436536SAndroid Build Coastguard Worker   /* DRC */
1262*e5436536SAndroid Build Coastguard Worker   pStreamInfo->drcProgRefLev =
1263*e5436536SAndroid Build Coastguard Worker       -1; /* set program reference level to not indicated */
1264*e5436536SAndroid Build Coastguard Worker   pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
1265*e5436536SAndroid Build Coastguard Worker 
1266*e5436536SAndroid Build Coastguard Worker   pStreamInfo->outputLoudness = -1; /* default: no loudness metadata present */
1267*e5436536SAndroid Build Coastguard Worker }
1268*e5436536SAndroid Build Coastguard Worker 
1269*e5436536SAndroid Build Coastguard Worker /*!
1270*e5436536SAndroid Build Coastguard Worker   \brief Initialization of AacDecoderChannelInfo
1271*e5436536SAndroid Build Coastguard Worker 
1272*e5436536SAndroid Build Coastguard Worker   The function initializes the pointers to AacDecoderChannelInfo for each
1273*e5436536SAndroid Build Coastguard Worker   channel, set the start values for window shape and window sequence of
1274*e5436536SAndroid Build Coastguard Worker   overlap&add to zero, set the overlap buffer to zero and initializes the
1275*e5436536SAndroid Build Coastguard Worker   pointers to the window coefficients. \param bsFormat is the format of the AAC
1276*e5436536SAndroid Build Coastguard Worker   bitstream
1277*e5436536SAndroid Build Coastguard Worker 
1278*e5436536SAndroid Build Coastguard Worker   \return  AACDECODER instance
1279*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_Open(TRANSPORT_TYPE bsFormat)1280*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(
1281*e5436536SAndroid Build Coastguard Worker     TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */
1282*e5436536SAndroid Build Coastguard Worker {
1283*e5436536SAndroid Build Coastguard Worker   HANDLE_AACDECODER self;
1284*e5436536SAndroid Build Coastguard Worker 
1285*e5436536SAndroid Build Coastguard Worker   self = GetAacDecoder();
1286*e5436536SAndroid Build Coastguard Worker   if (self == NULL) {
1287*e5436536SAndroid Build Coastguard Worker     goto bail;
1288*e5436536SAndroid Build Coastguard Worker   }
1289*e5436536SAndroid Build Coastguard Worker 
1290*e5436536SAndroid Build Coastguard Worker   FDK_QmfDomain_ClearRequested(&self->qmfDomain.globalConf);
1291*e5436536SAndroid Build Coastguard Worker 
1292*e5436536SAndroid Build Coastguard Worker   /* Assign channel mapping info arrays (doing so removes dependency of settings
1293*e5436536SAndroid Build Coastguard Worker    * header in API header). */
1294*e5436536SAndroid Build Coastguard Worker   self->streamInfo.pChannelIndices = self->channelIndices;
1295*e5436536SAndroid Build Coastguard Worker   self->streamInfo.pChannelType = self->channelType;
1296*e5436536SAndroid Build Coastguard Worker   self->downscaleFactor = 1;
1297*e5436536SAndroid Build Coastguard Worker   self->downscaleFactorInBS = 1;
1298*e5436536SAndroid Build Coastguard Worker 
1299*e5436536SAndroid Build Coastguard Worker   /* initialize anc data */
1300*e5436536SAndroid Build Coastguard Worker   CAacDecoder_AncDataInit(&self->ancData, NULL, 0);
1301*e5436536SAndroid Build Coastguard Worker 
1302*e5436536SAndroid Build Coastguard Worker   /* initialize stream info */
1303*e5436536SAndroid Build Coastguard Worker   CStreamInfoInit(&self->streamInfo);
1304*e5436536SAndroid Build Coastguard Worker 
1305*e5436536SAndroid Build Coastguard Worker   /* initialize progam config */
1306*e5436536SAndroid Build Coastguard Worker   CProgramConfig_Init(&self->pce);
1307*e5436536SAndroid Build Coastguard Worker 
1308*e5436536SAndroid Build Coastguard Worker   /* initialize error concealment common data */
1309*e5436536SAndroid Build Coastguard Worker   CConcealment_InitCommonData(&self->concealCommonData);
1310*e5436536SAndroid Build Coastguard Worker   self->concealMethodUser = ConcealMethodNone; /* undefined -> auto mode */
1311*e5436536SAndroid Build Coastguard Worker 
1312*e5436536SAndroid Build Coastguard Worker   self->hDrcInfo = GetDrcInfo();
1313*e5436536SAndroid Build Coastguard Worker   if (self->hDrcInfo == NULL) {
1314*e5436536SAndroid Build Coastguard Worker     goto bail;
1315*e5436536SAndroid Build Coastguard Worker   }
1316*e5436536SAndroid Build Coastguard Worker   /* Init common DRC structure */
1317*e5436536SAndroid Build Coastguard Worker   aacDecoder_drcInit(self->hDrcInfo);
1318*e5436536SAndroid Build Coastguard Worker   /* Set default frame delay */
1319*e5436536SAndroid Build Coastguard Worker   aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY,
1320*e5436536SAndroid Build Coastguard Worker                          CConcealment_GetDelay(&self->concealCommonData));
1321*e5436536SAndroid Build Coastguard Worker   self->workBufferCore1 = (FIXP_DBL *)GetWorkBufferCore1();
1322*e5436536SAndroid Build Coastguard Worker 
1323*e5436536SAndroid Build Coastguard Worker   self->workBufferCore2 = GetWorkBufferCore2();
1324*e5436536SAndroid Build Coastguard Worker   if (self->workBufferCore2 == NULL) goto bail;
1325*e5436536SAndroid Build Coastguard Worker 
1326*e5436536SAndroid Build Coastguard Worker   /* When RSVD60 is active use dedicated memory for core decoding */
1327*e5436536SAndroid Build Coastguard Worker   self->pTimeData2 = GetWorkBufferCore5();
1328*e5436536SAndroid Build Coastguard Worker   self->timeData2Size = GetRequiredMemWorkBufferCore5();
1329*e5436536SAndroid Build Coastguard Worker   if (self->pTimeData2 == NULL) {
1330*e5436536SAndroid Build Coastguard Worker     goto bail;
1331*e5436536SAndroid Build Coastguard Worker   }
1332*e5436536SAndroid Build Coastguard Worker 
1333*e5436536SAndroid Build Coastguard Worker   return self;
1334*e5436536SAndroid Build Coastguard Worker 
1335*e5436536SAndroid Build Coastguard Worker bail:
1336*e5436536SAndroid Build Coastguard Worker   CAacDecoder_Close(self);
1337*e5436536SAndroid Build Coastguard Worker 
1338*e5436536SAndroid Build Coastguard Worker   return NULL;
1339*e5436536SAndroid Build Coastguard Worker }
1340*e5436536SAndroid Build Coastguard Worker 
1341*e5436536SAndroid Build Coastguard Worker /* Revert CAacDecoder_Init() */
CAacDecoder_DeInit(HANDLE_AACDECODER self,const int subStreamIndex)1342*e5436536SAndroid Build Coastguard Worker static void CAacDecoder_DeInit(HANDLE_AACDECODER self,
1343*e5436536SAndroid Build Coastguard Worker                                const int subStreamIndex) {
1344*e5436536SAndroid Build Coastguard Worker   int ch;
1345*e5436536SAndroid Build Coastguard Worker   int aacChannelOffset = 0, aacChannels = (8);
1346*e5436536SAndroid Build Coastguard Worker   int numElements = (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1),
1347*e5436536SAndroid Build Coastguard Worker       elementOffset = 0;
1348*e5436536SAndroid Build Coastguard Worker 
1349*e5436536SAndroid Build Coastguard Worker   if (self == NULL) return;
1350*e5436536SAndroid Build Coastguard Worker 
1351*e5436536SAndroid Build Coastguard Worker   {
1352*e5436536SAndroid Build Coastguard Worker     self->ascChannels[0] = 0;
1353*e5436536SAndroid Build Coastguard Worker     self->elements[0] = ID_END;
1354*e5436536SAndroid Build Coastguard Worker   }
1355*e5436536SAndroid Build Coastguard Worker 
1356*e5436536SAndroid Build Coastguard Worker   for (ch = aacChannelOffset; ch < aacChannelOffset + aacChannels; ch++) {
1357*e5436536SAndroid Build Coastguard Worker     if (self->pAacDecoderChannelInfo[ch] != NULL) {
1358*e5436536SAndroid Build Coastguard Worker       if (self->pAacDecoderChannelInfo[ch]->pComStaticData != NULL) {
1359*e5436536SAndroid Build Coastguard Worker         if (self->pAacDecoderChannelInfo[ch]
1360*e5436536SAndroid Build Coastguard Worker                 ->pComStaticData->pWorkBufferCore1 != NULL) {
1361*e5436536SAndroid Build Coastguard Worker           if (ch == aacChannelOffset) {
1362*e5436536SAndroid Build Coastguard Worker             FreeWorkBufferCore1(&self->pAacDecoderChannelInfo[ch]
1363*e5436536SAndroid Build Coastguard Worker                                      ->pComStaticData->pWorkBufferCore1);
1364*e5436536SAndroid Build Coastguard Worker           }
1365*e5436536SAndroid Build Coastguard Worker         }
1366*e5436536SAndroid Build Coastguard Worker         if (self->pAacDecoderChannelInfo[ch]
1367*e5436536SAndroid Build Coastguard Worker                 ->pComStaticData->cplxPredictionData != NULL) {
1368*e5436536SAndroid Build Coastguard Worker           FreeCplxPredictionData(&self->pAacDecoderChannelInfo[ch]
1369*e5436536SAndroid Build Coastguard Worker                                       ->pComStaticData->cplxPredictionData);
1370*e5436536SAndroid Build Coastguard Worker         }
1371*e5436536SAndroid Build Coastguard Worker         /* Avoid double free of linked pComStaticData in case of CPE by settings
1372*e5436536SAndroid Build Coastguard Worker          * pointer to NULL. */
1373*e5436536SAndroid Build Coastguard Worker         if (ch < (8) - 1) {
1374*e5436536SAndroid Build Coastguard Worker           if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) &&
1375*e5436536SAndroid Build Coastguard Worker               (self->pAacDecoderChannelInfo[ch + 1]->pComStaticData ==
1376*e5436536SAndroid Build Coastguard Worker                self->pAacDecoderChannelInfo[ch]->pComStaticData)) {
1377*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderChannelInfo[ch + 1]->pComStaticData = NULL;
1378*e5436536SAndroid Build Coastguard Worker           }
1379*e5436536SAndroid Build Coastguard Worker         }
1380*e5436536SAndroid Build Coastguard Worker         FDKfree(self->pAacDecoderChannelInfo[ch]->pComStaticData);
1381*e5436536SAndroid Build Coastguard Worker         self->pAacDecoderChannelInfo[ch]->pComStaticData = NULL;
1382*e5436536SAndroid Build Coastguard Worker       }
1383*e5436536SAndroid Build Coastguard Worker       if (self->pAacDecoderChannelInfo[ch]->pComData != NULL) {
1384*e5436536SAndroid Build Coastguard Worker         /* Avoid double free of linked pComData in case of CPE by settings
1385*e5436536SAndroid Build Coastguard Worker          * pointer to NULL. */
1386*e5436536SAndroid Build Coastguard Worker         if (ch < (8) - 1) {
1387*e5436536SAndroid Build Coastguard Worker           if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) &&
1388*e5436536SAndroid Build Coastguard Worker               (self->pAacDecoderChannelInfo[ch + 1]->pComData ==
1389*e5436536SAndroid Build Coastguard Worker                self->pAacDecoderChannelInfo[ch]->pComData)) {
1390*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderChannelInfo[ch + 1]->pComData = NULL;
1391*e5436536SAndroid Build Coastguard Worker           }
1392*e5436536SAndroid Build Coastguard Worker         }
1393*e5436536SAndroid Build Coastguard Worker         if (ch == aacChannelOffset) {
1394*e5436536SAndroid Build Coastguard Worker           FreeWorkBufferCore6(
1395*e5436536SAndroid Build Coastguard Worker               (SCHAR **)&self->pAacDecoderChannelInfo[ch]->pComData);
1396*e5436536SAndroid Build Coastguard Worker         } else {
1397*e5436536SAndroid Build Coastguard Worker           FDKafree(self->pAacDecoderChannelInfo[ch]->pComData);
1398*e5436536SAndroid Build Coastguard Worker         }
1399*e5436536SAndroid Build Coastguard Worker         self->pAacDecoderChannelInfo[ch]->pComData = NULL;
1400*e5436536SAndroid Build Coastguard Worker       }
1401*e5436536SAndroid Build Coastguard Worker     }
1402*e5436536SAndroid Build Coastguard Worker     if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
1403*e5436536SAndroid Build Coastguard Worker       if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
1404*e5436536SAndroid Build Coastguard Worker         FreeOverlapBuffer(
1405*e5436536SAndroid Build Coastguard Worker             &self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
1406*e5436536SAndroid Build Coastguard Worker       }
1407*e5436536SAndroid Build Coastguard Worker       if (self->pAacDecoderStaticChannelInfo[ch]->hArCo != NULL) {
1408*e5436536SAndroid Build Coastguard Worker         CArco_Destroy(self->pAacDecoderStaticChannelInfo[ch]->hArCo);
1409*e5436536SAndroid Build Coastguard Worker       }
1410*e5436536SAndroid Build Coastguard Worker       FreeAacDecoderStaticChannelInfo(&self->pAacDecoderStaticChannelInfo[ch]);
1411*e5436536SAndroid Build Coastguard Worker     }
1412*e5436536SAndroid Build Coastguard Worker     if (self->pAacDecoderChannelInfo[ch] != NULL) {
1413*e5436536SAndroid Build Coastguard Worker       FreeAacDecoderChannelInfo(&self->pAacDecoderChannelInfo[ch]);
1414*e5436536SAndroid Build Coastguard Worker     }
1415*e5436536SAndroid Build Coastguard Worker   }
1416*e5436536SAndroid Build Coastguard Worker 
1417*e5436536SAndroid Build Coastguard Worker   {
1418*e5436536SAndroid Build Coastguard Worker     int el;
1419*e5436536SAndroid Build Coastguard Worker     for (el = elementOffset; el < elementOffset + numElements; el++) {
1420*e5436536SAndroid Build Coastguard Worker       if (self->cpeStaticData[el] != NULL) {
1421*e5436536SAndroid Build Coastguard Worker         FreeCpePersistentData(&self->cpeStaticData[el]);
1422*e5436536SAndroid Build Coastguard Worker       }
1423*e5436536SAndroid Build Coastguard Worker     }
1424*e5436536SAndroid Build Coastguard Worker   }
1425*e5436536SAndroid Build Coastguard Worker 
1426*e5436536SAndroid Build Coastguard Worker   FDK_Delay_Destroy(&self->usacResidualDelay);
1427*e5436536SAndroid Build Coastguard Worker 
1428*e5436536SAndroid Build Coastguard Worker   self->aacChannels = 0;
1429*e5436536SAndroid Build Coastguard Worker   self->streamInfo.aacSampleRate = 0;
1430*e5436536SAndroid Build Coastguard Worker   self->streamInfo.sampleRate = 0;
1431*e5436536SAndroid Build Coastguard Worker   /* This samplerate value is checked for configuration change, not the others
1432*e5436536SAndroid Build Coastguard Worker    * above. */
1433*e5436536SAndroid Build Coastguard Worker   self->samplingRateInfo[subStreamIndex].samplingRate = 0;
1434*e5436536SAndroid Build Coastguard Worker }
1435*e5436536SAndroid Build Coastguard Worker 
1436*e5436536SAndroid Build Coastguard Worker /*!
1437*e5436536SAndroid Build Coastguard Worker  * \brief CAacDecoder_AcceptFlags Accept flags and element flags
1438*e5436536SAndroid Build Coastguard Worker  *
1439*e5436536SAndroid Build Coastguard Worker  * \param self          [o]   handle to AACDECODER structure
1440*e5436536SAndroid Build Coastguard Worker  * \param asc           [i]   handle to ASC structure
1441*e5436536SAndroid Build Coastguard Worker  * \param flags         [i]   flags
1442*e5436536SAndroid Build Coastguard Worker  * \param elFlags       [i]   pointer to element flags
1443*e5436536SAndroid Build Coastguard Worker  * \param streamIndex   [i]   stream index
1444*e5436536SAndroid Build Coastguard Worker  * \param elementOffset [i]   element offset
1445*e5436536SAndroid Build Coastguard Worker  *
1446*e5436536SAndroid Build Coastguard Worker  * \return void
1447*e5436536SAndroid Build Coastguard Worker  */
CAacDecoder_AcceptFlags(HANDLE_AACDECODER self,const CSAudioSpecificConfig * asc,UINT flags,UINT * elFlags,int streamIndex,int elementOffset)1448*e5436536SAndroid Build Coastguard Worker static void CAacDecoder_AcceptFlags(HANDLE_AACDECODER self,
1449*e5436536SAndroid Build Coastguard Worker                                     const CSAudioSpecificConfig *asc,
1450*e5436536SAndroid Build Coastguard Worker                                     UINT flags, UINT *elFlags, int streamIndex,
1451*e5436536SAndroid Build Coastguard Worker                                     int elementOffset) {
1452*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(self->elFlags, elFlags, sizeof(self->elFlags));
1453*e5436536SAndroid Build Coastguard Worker 
1454*e5436536SAndroid Build Coastguard Worker   self->flags[streamIndex] = flags;
1455*e5436536SAndroid Build Coastguard Worker }
1456*e5436536SAndroid Build Coastguard Worker 
1457*e5436536SAndroid Build Coastguard Worker /*!
1458*e5436536SAndroid Build Coastguard Worker  * \brief CAacDecoder_CtrlCFGChange Set config change parameters.
1459*e5436536SAndroid Build Coastguard Worker  *
1460*e5436536SAndroid Build Coastguard Worker  * \param self           [i]   handle to AACDECODER structure
1461*e5436536SAndroid Build Coastguard Worker  * \param flushStatus    [i]   flush status: on|off
1462*e5436536SAndroid Build Coastguard Worker  * \param flushCnt       [i]   flush frame counter
1463*e5436536SAndroid Build Coastguard Worker  * \param buildUpStatus  [i]   build up status: on|off
1464*e5436536SAndroid Build Coastguard Worker  * \param buildUpCnt     [i]   build up frame counter
1465*e5436536SAndroid Build Coastguard Worker  *
1466*e5436536SAndroid Build Coastguard Worker  * \return error
1467*e5436536SAndroid Build Coastguard Worker  */
CAacDecoder_CtrlCFGChange(HANDLE_AACDECODER self,UCHAR flushStatus,SCHAR flushCnt,UCHAR buildUpStatus,SCHAR buildUpCnt)1468*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_CtrlCFGChange(HANDLE_AACDECODER self,
1469*e5436536SAndroid Build Coastguard Worker                                                          UCHAR flushStatus,
1470*e5436536SAndroid Build Coastguard Worker                                                          SCHAR flushCnt,
1471*e5436536SAndroid Build Coastguard Worker                                                          UCHAR buildUpStatus,
1472*e5436536SAndroid Build Coastguard Worker                                                          SCHAR buildUpCnt) {
1473*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR err = AAC_DEC_OK;
1474*e5436536SAndroid Build Coastguard Worker 
1475*e5436536SAndroid Build Coastguard Worker   self->flushStatus = flushStatus;
1476*e5436536SAndroid Build Coastguard Worker   self->flushCnt = flushCnt;
1477*e5436536SAndroid Build Coastguard Worker   self->buildUpStatus = buildUpStatus;
1478*e5436536SAndroid Build Coastguard Worker   self->buildUpCnt = buildUpCnt;
1479*e5436536SAndroid Build Coastguard Worker 
1480*e5436536SAndroid Build Coastguard Worker   return (err);
1481*e5436536SAndroid Build Coastguard Worker }
1482*e5436536SAndroid Build Coastguard Worker 
1483*e5436536SAndroid Build Coastguard Worker /*!
1484*e5436536SAndroid Build Coastguard Worker  * \brief CAacDecoder_FreeMem Free config dependent AAC memory.
1485*e5436536SAndroid Build Coastguard Worker  *
1486*e5436536SAndroid Build Coastguard Worker  * \param self       [i]   handle to AACDECODER structure
1487*e5436536SAndroid Build Coastguard Worker  *
1488*e5436536SAndroid Build Coastguard Worker  * \return error
1489*e5436536SAndroid Build Coastguard Worker  */
CAacDecoder_FreeMem(HANDLE_AACDECODER self,const int subStreamIndex)1490*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self,
1491*e5436536SAndroid Build Coastguard Worker                                                    const int subStreamIndex) {
1492*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR err = AAC_DEC_OK;
1493*e5436536SAndroid Build Coastguard Worker 
1494*e5436536SAndroid Build Coastguard Worker   CAacDecoder_DeInit(self, subStreamIndex);
1495*e5436536SAndroid Build Coastguard Worker 
1496*e5436536SAndroid Build Coastguard Worker   return (err);
1497*e5436536SAndroid Build Coastguard Worker }
1498*e5436536SAndroid Build Coastguard Worker 
1499*e5436536SAndroid Build Coastguard Worker /* Destroy aac decoder */
CAacDecoder_Close(HANDLE_AACDECODER self)1500*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) {
1501*e5436536SAndroid Build Coastguard Worker   if (self == NULL) return;
1502*e5436536SAndroid Build Coastguard Worker 
1503*e5436536SAndroid Build Coastguard Worker   CAacDecoder_DeInit(self, 0);
1504*e5436536SAndroid Build Coastguard Worker 
1505*e5436536SAndroid Build Coastguard Worker   {
1506*e5436536SAndroid Build Coastguard Worker     int ch;
1507*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < (8); ch++) {
1508*e5436536SAndroid Build Coastguard Worker       if (self->pTimeDataFlush[ch] != NULL) {
1509*e5436536SAndroid Build Coastguard Worker         FreeTimeDataFlush(&self->pTimeDataFlush[ch]);
1510*e5436536SAndroid Build Coastguard Worker       }
1511*e5436536SAndroid Build Coastguard Worker     }
1512*e5436536SAndroid Build Coastguard Worker   }
1513*e5436536SAndroid Build Coastguard Worker 
1514*e5436536SAndroid Build Coastguard Worker   if (self->hDrcInfo) {
1515*e5436536SAndroid Build Coastguard Worker     FreeDrcInfo(&self->hDrcInfo);
1516*e5436536SAndroid Build Coastguard Worker   }
1517*e5436536SAndroid Build Coastguard Worker 
1518*e5436536SAndroid Build Coastguard Worker   if (self->workBufferCore1 != NULL) {
1519*e5436536SAndroid Build Coastguard Worker     FreeWorkBufferCore1((CWorkBufferCore1 **)&self->workBufferCore1);
1520*e5436536SAndroid Build Coastguard Worker   }
1521*e5436536SAndroid Build Coastguard Worker 
1522*e5436536SAndroid Build Coastguard Worker   /* Free WorkBufferCore2 */
1523*e5436536SAndroid Build Coastguard Worker   if (self->workBufferCore2 != NULL) {
1524*e5436536SAndroid Build Coastguard Worker     FreeWorkBufferCore2(&self->workBufferCore2);
1525*e5436536SAndroid Build Coastguard Worker   }
1526*e5436536SAndroid Build Coastguard Worker   if (self->pTimeData2 != NULL) {
1527*e5436536SAndroid Build Coastguard Worker     FreeWorkBufferCore5(&self->pTimeData2);
1528*e5436536SAndroid Build Coastguard Worker   }
1529*e5436536SAndroid Build Coastguard Worker 
1530*e5436536SAndroid Build Coastguard Worker   FDK_QmfDomain_Close(&self->qmfDomain);
1531*e5436536SAndroid Build Coastguard Worker 
1532*e5436536SAndroid Build Coastguard Worker   FreeAacDecoder(&self);
1533*e5436536SAndroid Build Coastguard Worker }
1534*e5436536SAndroid Build Coastguard Worker 
1535*e5436536SAndroid Build Coastguard Worker /*!
1536*e5436536SAndroid Build Coastguard Worker   \brief Initialization of decoder instance
1537*e5436536SAndroid Build Coastguard Worker 
1538*e5436536SAndroid Build Coastguard Worker   The function initializes the decoder.
1539*e5436536SAndroid Build Coastguard Worker 
1540*e5436536SAndroid Build Coastguard Worker   \return  error status: 0 for success, <>0 for unsupported configurations
1541*e5436536SAndroid Build Coastguard Worker */
1542*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP AAC_DECODER_ERROR
CAacDecoder_Init(HANDLE_AACDECODER self,const CSAudioSpecificConfig * asc,UCHAR configMode,UCHAR * configChanged)1543*e5436536SAndroid Build Coastguard Worker CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
1544*e5436536SAndroid Build Coastguard Worker                  UCHAR configMode, UCHAR *configChanged) {
1545*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR err = AAC_DEC_OK;
1546*e5436536SAndroid Build Coastguard Worker   INT ascChannels, ascChanged = 0;
1547*e5436536SAndroid Build Coastguard Worker   AACDEC_RENDER_MODE initRenderMode = AACDEC_RENDER_INVALID;
1548*e5436536SAndroid Build Coastguard Worker   SCHAR usacStereoConfigIndex = -1;
1549*e5436536SAndroid Build Coastguard Worker   int usacResidualDelayCompSamples = 0;
1550*e5436536SAndroid Build Coastguard Worker   int elementOffset, aacChannelsOffset, aacChannelsOffsetIdx;
1551*e5436536SAndroid Build Coastguard Worker   const int streamIndex = 0;
1552*e5436536SAndroid Build Coastguard Worker   INT flushChannels = 0;
1553*e5436536SAndroid Build Coastguard Worker 
1554*e5436536SAndroid Build Coastguard Worker   UINT flags;
1555*e5436536SAndroid Build Coastguard Worker   /* elFlags[(3*MAX_CHANNELS + (MAX_CHANNELS)/2 + 4 * (MAX_TRACKS) + 1]
1556*e5436536SAndroid Build Coastguard Worker      where MAX_CHANNELS is (8*2) and MAX_TRACKS is 1 */
1557*e5436536SAndroid Build Coastguard Worker   UINT elFlags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)];
1558*e5436536SAndroid Build Coastguard Worker 
1559*e5436536SAndroid Build Coastguard Worker   UCHAR sbrEnabled = self->sbrEnabled;
1560*e5436536SAndroid Build Coastguard Worker   UCHAR sbrEnabledPrev = self->sbrEnabledPrev;
1561*e5436536SAndroid Build Coastguard Worker   UCHAR mpsEnableCurr = self->mpsEnableCurr;
1562*e5436536SAndroid Build Coastguard Worker 
1563*e5436536SAndroid Build Coastguard Worker   if (!self) return AAC_DEC_INVALID_HANDLE;
1564*e5436536SAndroid Build Coastguard Worker 
1565*e5436536SAndroid Build Coastguard Worker   UCHAR downscaleFactor = self->downscaleFactor;
1566*e5436536SAndroid Build Coastguard Worker   UCHAR downscaleFactorInBS = self->downscaleFactorInBS;
1567*e5436536SAndroid Build Coastguard Worker 
1568*e5436536SAndroid Build Coastguard Worker   self->aacOutDataHeadroom = (3);
1569*e5436536SAndroid Build Coastguard Worker 
1570*e5436536SAndroid Build Coastguard Worker   // set profile and check for supported aot
1571*e5436536SAndroid Build Coastguard Worker   // leave profile on default (=-1) for all other supported MPEG-4 aot's except
1572*e5436536SAndroid Build Coastguard Worker   // aot=2 (=AAC-LC)
1573*e5436536SAndroid Build Coastguard Worker   switch (asc->m_aot) {
1574*e5436536SAndroid Build Coastguard Worker     case AOT_AAC_LC:
1575*e5436536SAndroid Build Coastguard Worker       self->streamInfo.profile = 1;
1576*e5436536SAndroid Build Coastguard Worker       FDK_FALLTHROUGH;
1577*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_SCAL:
1578*e5436536SAndroid Build Coastguard Worker       if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) {
1579*e5436536SAndroid Build Coastguard Worker         /* aac_scalable_extension_element() currently not supported. */
1580*e5436536SAndroid Build Coastguard Worker         return AAC_DEC_UNSUPPORTED_FORMAT;
1581*e5436536SAndroid Build Coastguard Worker       }
1582*e5436536SAndroid Build Coastguard Worker       FDK_FALLTHROUGH;
1583*e5436536SAndroid Build Coastguard Worker     case AOT_SBR:
1584*e5436536SAndroid Build Coastguard Worker     case AOT_PS:
1585*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_LC:
1586*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_LD:
1587*e5436536SAndroid Build Coastguard Worker     case AOT_DRM_AAC:
1588*e5436536SAndroid Build Coastguard Worker     case AOT_DRM_SURROUND:
1589*e5436536SAndroid Build Coastguard Worker       initRenderMode = AACDEC_RENDER_IMDCT;
1590*e5436536SAndroid Build Coastguard Worker       break;
1591*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_ELD:
1592*e5436536SAndroid Build Coastguard Worker       initRenderMode = AACDEC_RENDER_ELDFB;
1593*e5436536SAndroid Build Coastguard Worker       break;
1594*e5436536SAndroid Build Coastguard Worker     case AOT_USAC:
1595*e5436536SAndroid Build Coastguard Worker       initRenderMode = AACDEC_RENDER_IMDCT;
1596*e5436536SAndroid Build Coastguard Worker       break;
1597*e5436536SAndroid Build Coastguard Worker     default:
1598*e5436536SAndroid Build Coastguard Worker       return AAC_DEC_UNSUPPORTED_AOT;
1599*e5436536SAndroid Build Coastguard Worker   }
1600*e5436536SAndroid Build Coastguard Worker 
1601*e5436536SAndroid Build Coastguard Worker   if (CProgramConfig_IsValid(&self->pce) && (asc->m_channelConfiguration > 0)) {
1602*e5436536SAndroid Build Coastguard Worker     /* Compare the stored (old) PCE with a default PCE created from the (new)
1603*e5436536SAndroid Build Coastguard Worker        channel_config (on a temporal buffer) to find out wheter we can keep it
1604*e5436536SAndroid Build Coastguard Worker        (and its metadata) or not. */
1605*e5436536SAndroid Build Coastguard Worker     int pceCmpResult;
1606*e5436536SAndroid Build Coastguard Worker     C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
1607*e5436536SAndroid Build Coastguard Worker 
1608*e5436536SAndroid Build Coastguard Worker     CProgramConfig_GetDefault(tmpPce, asc->m_channelConfiguration);
1609*e5436536SAndroid Build Coastguard Worker     pceCmpResult = CProgramConfig_Compare(&self->pce, tmpPce);
1610*e5436536SAndroid Build Coastguard Worker     if ((pceCmpResult < 0) /* Reset if PCEs are completely different ... */
1611*e5436536SAndroid Build Coastguard Worker         ||
1612*e5436536SAndroid Build Coastguard Worker         (pceCmpResult > 1)) { /*            ... or have a different layout. */
1613*e5436536SAndroid Build Coastguard Worker       CProgramConfig_Init(&self->pce);
1614*e5436536SAndroid Build Coastguard Worker     } /* Otherwise keep the PCE (and its metadata). */
1615*e5436536SAndroid Build Coastguard Worker     C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
1616*e5436536SAndroid Build Coastguard Worker   } else {
1617*e5436536SAndroid Build Coastguard Worker     CProgramConfig_Init(&self->pce);
1618*e5436536SAndroid Build Coastguard Worker   }
1619*e5436536SAndroid Build Coastguard Worker 
1620*e5436536SAndroid Build Coastguard Worker   /* set channels */
1621*e5436536SAndroid Build Coastguard Worker   switch (asc->m_channelConfiguration) {
1622*e5436536SAndroid Build Coastguard Worker     case 0:
1623*e5436536SAndroid Build Coastguard Worker       switch (asc->m_aot) {
1624*e5436536SAndroid Build Coastguard Worker         case AOT_USAC:
1625*e5436536SAndroid Build Coastguard Worker           self->chMapIndex = 0;
1626*e5436536SAndroid Build Coastguard Worker           ascChannels = asc->m_sc.m_usacConfig.m_nUsacChannels;
1627*e5436536SAndroid Build Coastguard Worker           break;
1628*e5436536SAndroid Build Coastguard Worker         default:
1629*e5436536SAndroid Build Coastguard Worker           /* get channels from program config (ASC) */
1630*e5436536SAndroid Build Coastguard Worker           if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) {
1631*e5436536SAndroid Build Coastguard Worker             ascChannels = asc->m_progrConfigElement.NumChannels;
1632*e5436536SAndroid Build Coastguard Worker             if (ascChannels > 0) {
1633*e5436536SAndroid Build Coastguard Worker               int el_tmp;
1634*e5436536SAndroid Build Coastguard Worker               /* valid number of channels -> copy program config element (PCE)
1635*e5436536SAndroid Build Coastguard Worker                * from ASC */
1636*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(&self->pce, &asc->m_progrConfigElement,
1637*e5436536SAndroid Build Coastguard Worker                         sizeof(CProgramConfig));
1638*e5436536SAndroid Build Coastguard Worker               /* Built element table */
1639*e5436536SAndroid Build Coastguard Worker               el_tmp = CProgramConfig_GetElementTable(
1640*e5436536SAndroid Build Coastguard Worker                   &asc->m_progrConfigElement, self->elements, (((8)) + (8)),
1641*e5436536SAndroid Build Coastguard Worker                   &self->chMapIndex);
1642*e5436536SAndroid Build Coastguard Worker               for (; el_tmp < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1);
1643*e5436536SAndroid Build Coastguard Worker                    el_tmp++) {
1644*e5436536SAndroid Build Coastguard Worker                 self->elements[el_tmp] = ID_NONE;
1645*e5436536SAndroid Build Coastguard Worker               }
1646*e5436536SAndroid Build Coastguard Worker             } else {
1647*e5436536SAndroid Build Coastguard Worker               return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
1648*e5436536SAndroid Build Coastguard Worker             }
1649*e5436536SAndroid Build Coastguard Worker           } else {
1650*e5436536SAndroid Build Coastguard Worker             self->chMapIndex = 0;
1651*e5436536SAndroid Build Coastguard Worker             return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
1652*e5436536SAndroid Build Coastguard Worker           }
1653*e5436536SAndroid Build Coastguard Worker           break;
1654*e5436536SAndroid Build Coastguard Worker       }
1655*e5436536SAndroid Build Coastguard Worker       break;
1656*e5436536SAndroid Build Coastguard Worker     case 1:
1657*e5436536SAndroid Build Coastguard Worker     case 2:
1658*e5436536SAndroid Build Coastguard Worker     case 3:
1659*e5436536SAndroid Build Coastguard Worker     case 4:
1660*e5436536SAndroid Build Coastguard Worker     case 5:
1661*e5436536SAndroid Build Coastguard Worker     case 6:
1662*e5436536SAndroid Build Coastguard Worker       ascChannels = asc->m_channelConfiguration;
1663*e5436536SAndroid Build Coastguard Worker       break;
1664*e5436536SAndroid Build Coastguard Worker     case 11:
1665*e5436536SAndroid Build Coastguard Worker       ascChannels = 7;
1666*e5436536SAndroid Build Coastguard Worker       break;
1667*e5436536SAndroid Build Coastguard Worker     case 7:
1668*e5436536SAndroid Build Coastguard Worker     case 12:
1669*e5436536SAndroid Build Coastguard Worker     case 14:
1670*e5436536SAndroid Build Coastguard Worker       ascChannels = 8;
1671*e5436536SAndroid Build Coastguard Worker       break;
1672*e5436536SAndroid Build Coastguard Worker     default:
1673*e5436536SAndroid Build Coastguard Worker       return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
1674*e5436536SAndroid Build Coastguard Worker   }
1675*e5436536SAndroid Build Coastguard Worker 
1676*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_USAC) {
1677*e5436536SAndroid Build Coastguard Worker     flushChannels = fMin(ascChannels, (8));
1678*e5436536SAndroid Build Coastguard Worker     INT numChannel;
1679*e5436536SAndroid Build Coastguard Worker     pcmDmx_GetParam(self->hPcmUtils, MIN_NUMBER_OF_OUTPUT_CHANNELS,
1680*e5436536SAndroid Build Coastguard Worker                     &numChannel);
1681*e5436536SAndroid Build Coastguard Worker     flushChannels = fMin(fMax(numChannel, flushChannels), (8));
1682*e5436536SAndroid Build Coastguard Worker   }
1683*e5436536SAndroid Build Coastguard Worker 
1684*e5436536SAndroid Build Coastguard Worker   if (IS_USAC(asc->m_aot)) {
1685*e5436536SAndroid Build Coastguard Worker     for (int el = 0; el < (INT)asc->m_sc.m_usacConfig.m_usacNumElements; el++) {
1686*e5436536SAndroid Build Coastguard Worker       /* fix number of core channels aka ascChannels for stereoConfigIndex = 1
1687*e5436536SAndroid Build Coastguard Worker        * cases */
1688*e5436536SAndroid Build Coastguard Worker       if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 1) {
1689*e5436536SAndroid Build Coastguard Worker         ascChannels--; /* stereoConfigIndex == 1 stereo cases do actually
1690*e5436536SAndroid Build Coastguard Worker                           contain only a mono core channel. */
1691*e5436536SAndroid Build Coastguard Worker       } else if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 2) {
1692*e5436536SAndroid Build Coastguard Worker         /* In this case it is necessary to follow up the DMX signal delay caused
1693*e5436536SAndroid Build Coastguard Worker            by HBE also with the residual signal (2nd core channel). The SBR
1694*e5436536SAndroid Build Coastguard Worker            overlap delay is not regarded here, this is handled by the MPS212
1695*e5436536SAndroid Build Coastguard Worker            implementation.
1696*e5436536SAndroid Build Coastguard Worker         */
1697*e5436536SAndroid Build Coastguard Worker         if (asc->m_sc.m_usacConfig.element[el].m_harmonicSBR) {
1698*e5436536SAndroid Build Coastguard Worker           usacResidualDelayCompSamples += asc->m_samplesPerFrame;
1699*e5436536SAndroid Build Coastguard Worker         }
1700*e5436536SAndroid Build Coastguard Worker         if (asc->m_sc.m_usacConfig.m_coreSbrFrameLengthIndex == 4) {
1701*e5436536SAndroid Build Coastguard Worker           usacResidualDelayCompSamples +=
1702*e5436536SAndroid Build Coastguard Worker               6 * 16; /* difference between 12 SBR
1703*e5436536SAndroid Build Coastguard Worker                          overlap slots from SBR and 6
1704*e5436536SAndroid Build Coastguard Worker                          slots delayed in MPS212 */
1705*e5436536SAndroid Build Coastguard Worker         }
1706*e5436536SAndroid Build Coastguard Worker       }
1707*e5436536SAndroid Build Coastguard Worker     }
1708*e5436536SAndroid Build Coastguard Worker   }
1709*e5436536SAndroid Build Coastguard Worker 
1710*e5436536SAndroid Build Coastguard Worker   aacChannelsOffset = 0;
1711*e5436536SAndroid Build Coastguard Worker   aacChannelsOffsetIdx = 0;
1712*e5436536SAndroid Build Coastguard Worker   elementOffset = 0;
1713*e5436536SAndroid Build Coastguard Worker   if ((ascChannels <= 0) || (ascChannels > (8)) ||
1714*e5436536SAndroid Build Coastguard Worker       (asc->m_channelConfiguration > AACDEC_MAX_CH_CONF)) {
1715*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
1716*e5436536SAndroid Build Coastguard Worker   }
1717*e5436536SAndroid Build Coastguard Worker 
1718*e5436536SAndroid Build Coastguard Worker   /* Set syntax flags */
1719*e5436536SAndroid Build Coastguard Worker   flags = 0;
1720*e5436536SAndroid Build Coastguard Worker   { FDKmemclear(elFlags, sizeof(elFlags)); }
1721*e5436536SAndroid Build Coastguard Worker 
1722*e5436536SAndroid Build Coastguard Worker   if ((asc->m_channelConfiguration > 0) || IS_USAC(asc->m_aot)) {
1723*e5436536SAndroid Build Coastguard Worker     if (IS_USAC(asc->m_aot)) {
1724*e5436536SAndroid Build Coastguard Worker       /* copy pointer to usac config
1725*e5436536SAndroid Build Coastguard Worker         (this is preliminary since there's an ongoing discussion about storing
1726*e5436536SAndroid Build Coastguard Worker         the config-part of the bitstream rather than the complete decoded
1727*e5436536SAndroid Build Coastguard Worker         configuration) */
1728*e5436536SAndroid Build Coastguard Worker       self->pUsacConfig[streamIndex] = &asc->m_sc.m_usacConfig;
1729*e5436536SAndroid Build Coastguard Worker 
1730*e5436536SAndroid Build Coastguard Worker       /* copy list of elements */
1731*e5436536SAndroid Build Coastguard Worker       if (self->pUsacConfig[streamIndex]->m_usacNumElements >
1732*e5436536SAndroid Build Coastguard Worker           (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
1733*e5436536SAndroid Build Coastguard Worker         goto bail;
1734*e5436536SAndroid Build Coastguard Worker       }
1735*e5436536SAndroid Build Coastguard Worker 
1736*e5436536SAndroid Build Coastguard Worker       if (self->numUsacElements[streamIndex] !=
1737*e5436536SAndroid Build Coastguard Worker           asc->m_sc.m_usacConfig.m_usacNumElements) {
1738*e5436536SAndroid Build Coastguard Worker         ascChanged = 1;
1739*e5436536SAndroid Build Coastguard Worker       }
1740*e5436536SAndroid Build Coastguard Worker 
1741*e5436536SAndroid Build Coastguard Worker       if (configMode & AC_CM_ALLOC_MEM) {
1742*e5436536SAndroid Build Coastguard Worker         self->numUsacElements[streamIndex] =
1743*e5436536SAndroid Build Coastguard Worker             asc->m_sc.m_usacConfig.m_usacNumElements;
1744*e5436536SAndroid Build Coastguard Worker       }
1745*e5436536SAndroid Build Coastguard Worker 
1746*e5436536SAndroid Build Coastguard Worker       mpsEnableCurr = 0;
1747*e5436536SAndroid Build Coastguard Worker       for (int _el = 0;
1748*e5436536SAndroid Build Coastguard Worker            _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
1749*e5436536SAndroid Build Coastguard Worker            _el++) {
1750*e5436536SAndroid Build Coastguard Worker         int el = _el + elementOffset;
1751*e5436536SAndroid Build Coastguard Worker         if (self->elements[el] !=
1752*e5436536SAndroid Build Coastguard Worker             self->pUsacConfig[streamIndex]->element[_el].usacElementType) {
1753*e5436536SAndroid Build Coastguard Worker           ascChanged = 1;
1754*e5436536SAndroid Build Coastguard Worker         }
1755*e5436536SAndroid Build Coastguard Worker         if (self->usacStereoConfigIndex[el] !=
1756*e5436536SAndroid Build Coastguard Worker             asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex) {
1757*e5436536SAndroid Build Coastguard Worker           ascChanged = 1;
1758*e5436536SAndroid Build Coastguard Worker         }
1759*e5436536SAndroid Build Coastguard Worker         if (configMode & AC_CM_ALLOC_MEM) {
1760*e5436536SAndroid Build Coastguard Worker           self->elements[el] =
1761*e5436536SAndroid Build Coastguard Worker               self->pUsacConfig[streamIndex]->element[_el].usacElementType;
1762*e5436536SAndroid Build Coastguard Worker           /* for Unified Stereo Coding */
1763*e5436536SAndroid Build Coastguard Worker           self->usacStereoConfigIndex[el] =
1764*e5436536SAndroid Build Coastguard Worker               asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex;
1765*e5436536SAndroid Build Coastguard Worker           if (self->elements[el] == ID_USAC_CPE) {
1766*e5436536SAndroid Build Coastguard Worker             mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0;
1767*e5436536SAndroid Build Coastguard Worker           }
1768*e5436536SAndroid Build Coastguard Worker         }
1769*e5436536SAndroid Build Coastguard Worker 
1770*e5436536SAndroid Build Coastguard Worker         elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling)
1771*e5436536SAndroid Build Coastguard Worker                            ? AC_EL_USAC_NOISE
1772*e5436536SAndroid Build Coastguard Worker                            : 0;
1773*e5436536SAndroid Build Coastguard Worker         elFlags[el] |=
1774*e5436536SAndroid Build Coastguard Worker             (asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex > 0)
1775*e5436536SAndroid Build Coastguard Worker                 ? AC_EL_USAC_MPS212
1776*e5436536SAndroid Build Coastguard Worker                 : 0;
1777*e5436536SAndroid Build Coastguard Worker         elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes)
1778*e5436536SAndroid Build Coastguard Worker                            ? AC_EL_USAC_ITES
1779*e5436536SAndroid Build Coastguard Worker                            : 0;
1780*e5436536SAndroid Build Coastguard Worker         elFlags[el] |=
1781*e5436536SAndroid Build Coastguard Worker             (asc->m_sc.m_usacConfig.element[_el].m_pvc) ? AC_EL_USAC_PVC : 0;
1782*e5436536SAndroid Build Coastguard Worker         elFlags[el] |=
1783*e5436536SAndroid Build Coastguard Worker             (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
1784*e5436536SAndroid Build Coastguard Worker                 ? AC_EL_USAC_LFE
1785*e5436536SAndroid Build Coastguard Worker                 : 0;
1786*e5436536SAndroid Build Coastguard Worker         elFlags[el] |=
1787*e5436536SAndroid Build Coastguard Worker             (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
1788*e5436536SAndroid Build Coastguard Worker                 ? AC_EL_LFE
1789*e5436536SAndroid Build Coastguard Worker                 : 0;
1790*e5436536SAndroid Build Coastguard Worker         if ((asc->m_sc.m_usacConfig.element[_el].usacElementType ==
1791*e5436536SAndroid Build Coastguard Worker              ID_USAC_CPE) &&
1792*e5436536SAndroid Build Coastguard Worker             ((self->usacStereoConfigIndex[el] == 0))) {
1793*e5436536SAndroid Build Coastguard Worker           elFlags[el] |= AC_EL_USAC_CP_POSSIBLE;
1794*e5436536SAndroid Build Coastguard Worker         }
1795*e5436536SAndroid Build Coastguard Worker       }
1796*e5436536SAndroid Build Coastguard Worker 
1797*e5436536SAndroid Build Coastguard Worker       self->hasAudioPreRoll = 0;
1798*e5436536SAndroid Build Coastguard Worker       if (self->pUsacConfig[streamIndex]->m_usacNumElements) {
1799*e5436536SAndroid Build Coastguard Worker         self->hasAudioPreRoll = asc->m_sc.m_usacConfig.element[0]
1800*e5436536SAndroid Build Coastguard Worker                                     .extElement.usacExtElementHasAudioPreRoll;
1801*e5436536SAndroid Build Coastguard Worker       }
1802*e5436536SAndroid Build Coastguard Worker       if (configMode & AC_CM_ALLOC_MEM) {
1803*e5436536SAndroid Build Coastguard Worker         self->elements[elementOffset +
1804*e5436536SAndroid Build Coastguard Worker                        self->pUsacConfig[streamIndex]->m_usacNumElements] =
1805*e5436536SAndroid Build Coastguard Worker             ID_END;
1806*e5436536SAndroid Build Coastguard Worker       }
1807*e5436536SAndroid Build Coastguard Worker     } else {
1808*e5436536SAndroid Build Coastguard Worker       /* Initialize constant mappings for channel config 1-7 */
1809*e5436536SAndroid Build Coastguard Worker       int i;
1810*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < AACDEC_CH_ELEMENTS_TAB_SIZE; i++) {
1811*e5436536SAndroid Build Coastguard Worker         self->elements[i] = elementsTab[asc->m_channelConfiguration - 1][i];
1812*e5436536SAndroid Build Coastguard Worker       }
1813*e5436536SAndroid Build Coastguard Worker       for (; i < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); i++) {
1814*e5436536SAndroid Build Coastguard Worker         self->elements[i] = ID_NONE;
1815*e5436536SAndroid Build Coastguard Worker       }
1816*e5436536SAndroid Build Coastguard Worker     }
1817*e5436536SAndroid Build Coastguard Worker 
1818*e5436536SAndroid Build Coastguard Worker     {
1819*e5436536SAndroid Build Coastguard Worker       int ch;
1820*e5436536SAndroid Build Coastguard Worker 
1821*e5436536SAndroid Build Coastguard Worker       for (ch = 0; ch < ascChannels; ch++) {
1822*e5436536SAndroid Build Coastguard Worker         self->chMapping[ch] = ch;
1823*e5436536SAndroid Build Coastguard Worker       }
1824*e5436536SAndroid Build Coastguard Worker       for (; ch < (8); ch++) {
1825*e5436536SAndroid Build Coastguard Worker         self->chMapping[ch] = 255;
1826*e5436536SAndroid Build Coastguard Worker       }
1827*e5436536SAndroid Build Coastguard Worker     }
1828*e5436536SAndroid Build Coastguard Worker 
1829*e5436536SAndroid Build Coastguard Worker     self->chMapIndex = asc->m_channelConfiguration;
1830*e5436536SAndroid Build Coastguard Worker   } else {
1831*e5436536SAndroid Build Coastguard Worker     if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) {
1832*e5436536SAndroid Build Coastguard Worker       /* Set matrix mixdown infos if available from PCE. */
1833*e5436536SAndroid Build Coastguard Worker       pcmDmx_SetMatrixMixdownFromPce(
1834*e5436536SAndroid Build Coastguard Worker           self->hPcmUtils, asc->m_progrConfigElement.MatrixMixdownIndexPresent,
1835*e5436536SAndroid Build Coastguard Worker           asc->m_progrConfigElement.MatrixMixdownIndex,
1836*e5436536SAndroid Build Coastguard Worker           asc->m_progrConfigElement.PseudoSurroundEnable);
1837*e5436536SAndroid Build Coastguard Worker     }
1838*e5436536SAndroid Build Coastguard Worker   }
1839*e5436536SAndroid Build Coastguard Worker 
1840*e5436536SAndroid Build Coastguard Worker   self->streamInfo.channelConfig = asc->m_channelConfiguration;
1841*e5436536SAndroid Build Coastguard Worker 
1842*e5436536SAndroid Build Coastguard Worker   if (self->streamInfo.aot != asc->m_aot) {
1843*e5436536SAndroid Build Coastguard Worker     if (configMode & AC_CM_ALLOC_MEM) {
1844*e5436536SAndroid Build Coastguard Worker       self->streamInfo.aot = asc->m_aot;
1845*e5436536SAndroid Build Coastguard Worker     }
1846*e5436536SAndroid Build Coastguard Worker     ascChanged = 1;
1847*e5436536SAndroid Build Coastguard Worker   }
1848*e5436536SAndroid Build Coastguard Worker 
1849*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_ER_AAC_ELD &&
1850*e5436536SAndroid Build Coastguard Worker       asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency != 0) {
1851*e5436536SAndroid Build Coastguard Worker     if (self->samplingRateInfo[0].samplingRate !=
1852*e5436536SAndroid Build Coastguard Worker             asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency ||
1853*e5436536SAndroid Build Coastguard Worker         self->samplingRateInfo[0].samplingRate * self->downscaleFactor !=
1854*e5436536SAndroid Build Coastguard Worker             asc->m_samplingFrequency) {
1855*e5436536SAndroid Build Coastguard Worker       /* get downscaledSamplingFrequency from ESC and compute the downscale
1856*e5436536SAndroid Build Coastguard Worker        * factor */
1857*e5436536SAndroid Build Coastguard Worker       downscaleFactorInBS =
1858*e5436536SAndroid Build Coastguard Worker           asc->m_samplingFrequency /
1859*e5436536SAndroid Build Coastguard Worker           asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency;
1860*e5436536SAndroid Build Coastguard Worker       if ((downscaleFactorInBS == 1 || downscaleFactorInBS == 2 ||
1861*e5436536SAndroid Build Coastguard Worker            (downscaleFactorInBS == 3 &&
1862*e5436536SAndroid Build Coastguard Worker             asc->m_sc.m_eldSpecificConfig.m_frameLengthFlag) ||
1863*e5436536SAndroid Build Coastguard Worker            downscaleFactorInBS == 4) &&
1864*e5436536SAndroid Build Coastguard Worker           ((asc->m_samplingFrequency %
1865*e5436536SAndroid Build Coastguard Worker             asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency) ==
1866*e5436536SAndroid Build Coastguard Worker            0)) {
1867*e5436536SAndroid Build Coastguard Worker         downscaleFactor = downscaleFactorInBS;
1868*e5436536SAndroid Build Coastguard Worker       } else {
1869*e5436536SAndroid Build Coastguard Worker         downscaleFactorInBS = 1;
1870*e5436536SAndroid Build Coastguard Worker         downscaleFactor = 1;
1871*e5436536SAndroid Build Coastguard Worker       }
1872*e5436536SAndroid Build Coastguard Worker     }
1873*e5436536SAndroid Build Coastguard Worker   } else {
1874*e5436536SAndroid Build Coastguard Worker     downscaleFactorInBS = 1;
1875*e5436536SAndroid Build Coastguard Worker     downscaleFactor = 1;
1876*e5436536SAndroid Build Coastguard Worker   }
1877*e5436536SAndroid Build Coastguard Worker 
1878*e5436536SAndroid Build Coastguard Worker   if (self->downscaleFactorInBS != downscaleFactorInBS) {
1879*e5436536SAndroid Build Coastguard Worker     if (configMode & AC_CM_ALLOC_MEM) {
1880*e5436536SAndroid Build Coastguard Worker       self->downscaleFactorInBS = downscaleFactorInBS;
1881*e5436536SAndroid Build Coastguard Worker       self->downscaleFactor = downscaleFactor;
1882*e5436536SAndroid Build Coastguard Worker     }
1883*e5436536SAndroid Build Coastguard Worker     ascChanged = 1;
1884*e5436536SAndroid Build Coastguard Worker   }
1885*e5436536SAndroid Build Coastguard Worker 
1886*e5436536SAndroid Build Coastguard Worker   if ((INT)asc->m_samplesPerFrame % downscaleFactor != 0) {
1887*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* frameSize/dsf must be an integer
1888*e5436536SAndroid Build Coastguard Worker                                                 number */
1889*e5436536SAndroid Build Coastguard Worker   }
1890*e5436536SAndroid Build Coastguard Worker 
1891*e5436536SAndroid Build Coastguard Worker   self->streamInfo.bitRate = 0;
1892*e5436536SAndroid Build Coastguard Worker 
1893*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_ER_AAC_ELD) {
1894*e5436536SAndroid Build Coastguard Worker     if (self->useLdQmfTimeAlign !=
1895*e5436536SAndroid Build Coastguard Worker         asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) {
1896*e5436536SAndroid Build Coastguard Worker       ascChanged = 1;
1897*e5436536SAndroid Build Coastguard Worker     }
1898*e5436536SAndroid Build Coastguard Worker     if (configMode & AC_CM_ALLOC_MEM) {
1899*e5436536SAndroid Build Coastguard Worker       self->useLdQmfTimeAlign =
1900*e5436536SAndroid Build Coastguard Worker           asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
1901*e5436536SAndroid Build Coastguard Worker     }
1902*e5436536SAndroid Build Coastguard Worker     if (sbrEnabled != asc->m_sbrPresentFlag) {
1903*e5436536SAndroid Build Coastguard Worker       ascChanged = 1;
1904*e5436536SAndroid Build Coastguard Worker     }
1905*e5436536SAndroid Build Coastguard Worker   }
1906*e5436536SAndroid Build Coastguard Worker 
1907*e5436536SAndroid Build Coastguard Worker   self->streamInfo.extAot = asc->m_extensionAudioObjectType;
1908*e5436536SAndroid Build Coastguard Worker   if (self->streamInfo.extSamplingRate !=
1909*e5436536SAndroid Build Coastguard Worker       (INT)asc->m_extensionSamplingFrequency) {
1910*e5436536SAndroid Build Coastguard Worker     ascChanged = 1;
1911*e5436536SAndroid Build Coastguard Worker   }
1912*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_ALLOC_MEM) {
1913*e5436536SAndroid Build Coastguard Worker     self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency;
1914*e5436536SAndroid Build Coastguard Worker   }
1915*e5436536SAndroid Build Coastguard Worker   flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
1916*e5436536SAndroid Build Coastguard Worker   flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
1917*e5436536SAndroid Build Coastguard Worker   if (asc->m_sbrPresentFlag) {
1918*e5436536SAndroid Build Coastguard Worker     sbrEnabled = 1;
1919*e5436536SAndroid Build Coastguard Worker     sbrEnabledPrev = 1;
1920*e5436536SAndroid Build Coastguard Worker   } else {
1921*e5436536SAndroid Build Coastguard Worker     sbrEnabled = 0;
1922*e5436536SAndroid Build Coastguard Worker     sbrEnabledPrev = 0;
1923*e5436536SAndroid Build Coastguard Worker   }
1924*e5436536SAndroid Build Coastguard Worker   if (sbrEnabled && asc->m_extensionSamplingFrequency) {
1925*e5436536SAndroid Build Coastguard Worker     if (downscaleFactor != 1 && (downscaleFactor)&1) {
1926*e5436536SAndroid Build Coastguard Worker       return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* SBR needs an even downscale
1927*e5436536SAndroid Build Coastguard Worker                                                   factor */
1928*e5436536SAndroid Build Coastguard Worker     }
1929*e5436536SAndroid Build Coastguard Worker     if (configMode & AC_CM_ALLOC_MEM) {
1930*e5436536SAndroid Build Coastguard Worker       self->streamInfo.extSamplingRate =
1931*e5436536SAndroid Build Coastguard Worker           self->streamInfo.extSamplingRate / self->downscaleFactor;
1932*e5436536SAndroid Build Coastguard Worker     }
1933*e5436536SAndroid Build Coastguard Worker   }
1934*e5436536SAndroid Build Coastguard Worker   if ((asc->m_aot == AOT_AAC_LC) && (asc->m_sbrPresentFlag == 1) &&
1935*e5436536SAndroid Build Coastguard Worker       (asc->m_extensionSamplingFrequency > (2 * asc->m_samplingFrequency))) {
1936*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* Core decoder supports at most a
1937*e5436536SAndroid Build Coastguard Worker                                                 1:2 upsampling for HE-AAC and
1938*e5436536SAndroid Build Coastguard Worker                                                 HE-AACv2 */
1939*e5436536SAndroid Build Coastguard Worker   }
1940*e5436536SAndroid Build Coastguard Worker 
1941*e5436536SAndroid Build Coastguard Worker   /* --------- vcb11 ------------ */
1942*e5436536SAndroid Build Coastguard Worker   flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
1943*e5436536SAndroid Build Coastguard Worker 
1944*e5436536SAndroid Build Coastguard Worker   /* ---------- rvlc ------------ */
1945*e5436536SAndroid Build Coastguard Worker   flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
1946*e5436536SAndroid Build Coastguard Worker 
1947*e5436536SAndroid Build Coastguard Worker   /* ----------- hcr ------------ */
1948*e5436536SAndroid Build Coastguard Worker   flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
1949*e5436536SAndroid Build Coastguard Worker 
1950*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_ER_AAC_ELD) {
1951*e5436536SAndroid Build Coastguard Worker     mpsEnableCurr = 0;
1952*e5436536SAndroid Build Coastguard Worker     flags |= AC_ELD;
1953*e5436536SAndroid Build Coastguard Worker     flags |= (asc->m_sbrPresentFlag)
1954*e5436536SAndroid Build Coastguard Worker                  ? AC_SBR_PRESENT
1955*e5436536SAndroid Build Coastguard Worker                  : 0; /* Need to set the SBR flag for backward-compatibility
1956*e5436536SAndroid Build Coastguard Worker                                reasons. Even if SBR is not supported. */
1957*e5436536SAndroid Build Coastguard Worker     flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
1958*e5436536SAndroid Build Coastguard Worker     flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign)
1959*e5436536SAndroid Build Coastguard Worker                  ? AC_MPS_PRESENT
1960*e5436536SAndroid Build Coastguard Worker                  : 0;
1961*e5436536SAndroid Build Coastguard Worker     if (self->mpsApplicable) {
1962*e5436536SAndroid Build Coastguard Worker       mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
1963*e5436536SAndroid Build Coastguard Worker     }
1964*e5436536SAndroid Build Coastguard Worker   }
1965*e5436536SAndroid Build Coastguard Worker   flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
1966*e5436536SAndroid Build Coastguard Worker   flags |= (asc->m_epConfig >= 0) ? AC_ER : 0;
1967*e5436536SAndroid Build Coastguard Worker 
1968*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_USAC) {
1969*e5436536SAndroid Build Coastguard Worker     flags |= AC_USAC;
1970*e5436536SAndroid Build Coastguard Worker     flags |= (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0)
1971*e5436536SAndroid Build Coastguard Worker                  ? AC_MPS_PRESENT
1972*e5436536SAndroid Build Coastguard Worker                  : 0;
1973*e5436536SAndroid Build Coastguard Worker   }
1974*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_DRM_AAC) {
1975*e5436536SAndroid Build Coastguard Worker     flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE;
1976*e5436536SAndroid Build Coastguard Worker   }
1977*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_DRM_SURROUND) {
1978*e5436536SAndroid Build Coastguard Worker     flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT;
1979*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(!asc->m_psPresentFlag);
1980*e5436536SAndroid Build Coastguard Worker   }
1981*e5436536SAndroid Build Coastguard Worker   if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) {
1982*e5436536SAndroid Build Coastguard Worker     flags |= AC_SCALABLE;
1983*e5436536SAndroid Build Coastguard Worker   }
1984*e5436536SAndroid Build Coastguard Worker 
1985*e5436536SAndroid Build Coastguard Worker   if ((asc->m_epConfig >= 0) && (asc->m_channelConfiguration <= 0)) {
1986*e5436536SAndroid Build Coastguard Worker     /* we have to know the number of channels otherwise no decoding is possible
1987*e5436536SAndroid Build Coastguard Worker      */
1988*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_UNSUPPORTED_ER_FORMAT;
1989*e5436536SAndroid Build Coastguard Worker   }
1990*e5436536SAndroid Build Coastguard Worker 
1991*e5436536SAndroid Build Coastguard Worker   self->streamInfo.epConfig = asc->m_epConfig;
1992*e5436536SAndroid Build Coastguard Worker   /* self->hInput->asc.m_epConfig = asc->m_epConfig; */
1993*e5436536SAndroid Build Coastguard Worker 
1994*e5436536SAndroid Build Coastguard Worker   if (asc->m_epConfig > 1) return AAC_DEC_UNSUPPORTED_ER_FORMAT;
1995*e5436536SAndroid Build Coastguard Worker 
1996*e5436536SAndroid Build Coastguard Worker   /* Check if samplerate changed. */
1997*e5436536SAndroid Build Coastguard Worker   if ((self->samplingRateInfo[streamIndex].samplingRate !=
1998*e5436536SAndroid Build Coastguard Worker        asc->m_samplingFrequency) ||
1999*e5436536SAndroid Build Coastguard Worker       (self->streamInfo.aacSamplesPerFrame !=
2000*e5436536SAndroid Build Coastguard Worker        (INT)asc->m_samplesPerFrame / downscaleFactor)) {
2001*e5436536SAndroid Build Coastguard Worker     AAC_DECODER_ERROR error;
2002*e5436536SAndroid Build Coastguard Worker 
2003*e5436536SAndroid Build Coastguard Worker     ascChanged = 1;
2004*e5436536SAndroid Build Coastguard Worker 
2005*e5436536SAndroid Build Coastguard Worker     if (configMode & AC_CM_ALLOC_MEM) {
2006*e5436536SAndroid Build Coastguard Worker       /* Update samplerate info. */
2007*e5436536SAndroid Build Coastguard Worker       error = getSamplingRateInfo(
2008*e5436536SAndroid Build Coastguard Worker           &self->samplingRateInfo[streamIndex], asc->m_samplesPerFrame,
2009*e5436536SAndroid Build Coastguard Worker           asc->m_samplingFrequencyIndex, asc->m_samplingFrequency);
2010*e5436536SAndroid Build Coastguard Worker       if (error != AAC_DEC_OK) {
2011*e5436536SAndroid Build Coastguard Worker         return error;
2012*e5436536SAndroid Build Coastguard Worker       }
2013*e5436536SAndroid Build Coastguard Worker       self->streamInfo.aacSampleRate =
2014*e5436536SAndroid Build Coastguard Worker           self->samplingRateInfo[0].samplingRate / self->downscaleFactor;
2015*e5436536SAndroid Build Coastguard Worker       self->streamInfo.aacSamplesPerFrame =
2016*e5436536SAndroid Build Coastguard Worker           asc->m_samplesPerFrame / self->downscaleFactor;
2017*e5436536SAndroid Build Coastguard Worker       if (self->streamInfo.aacSampleRate <= 0) {
2018*e5436536SAndroid Build Coastguard Worker         return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
2019*e5436536SAndroid Build Coastguard Worker       }
2020*e5436536SAndroid Build Coastguard Worker     }
2021*e5436536SAndroid Build Coastguard Worker   }
2022*e5436536SAndroid Build Coastguard Worker 
2023*e5436536SAndroid Build Coastguard Worker   /* Check if amount of channels has changed. */
2024*e5436536SAndroid Build Coastguard Worker   if (self->ascChannels[streamIndex] != ascChannels) {
2025*e5436536SAndroid Build Coastguard Worker     ascChanged = 1;
2026*e5436536SAndroid Build Coastguard Worker   }
2027*e5436536SAndroid Build Coastguard Worker 
2028*e5436536SAndroid Build Coastguard Worker   /* detect config change */
2029*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_DET_CFG_CHANGE) {
2030*e5436536SAndroid Build Coastguard Worker     if (ascChanged != 0) {
2031*e5436536SAndroid Build Coastguard Worker       *configChanged = 1;
2032*e5436536SAndroid Build Coastguard Worker     }
2033*e5436536SAndroid Build Coastguard Worker 
2034*e5436536SAndroid Build Coastguard Worker     CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex,
2035*e5436536SAndroid Build Coastguard Worker                             elementOffset);
2036*e5436536SAndroid Build Coastguard Worker 
2037*e5436536SAndroid Build Coastguard Worker     return err;
2038*e5436536SAndroid Build Coastguard Worker   }
2039*e5436536SAndroid Build Coastguard Worker 
2040*e5436536SAndroid Build Coastguard Worker   /* set AC_USAC_SCFGI3 globally if any usac element uses */
2041*e5436536SAndroid Build Coastguard Worker   switch (asc->m_aot) {
2042*e5436536SAndroid Build Coastguard Worker     case AOT_USAC:
2043*e5436536SAndroid Build Coastguard Worker       if (sbrEnabled) {
2044*e5436536SAndroid Build Coastguard Worker         for (int _el = 0;
2045*e5436536SAndroid Build Coastguard Worker              _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
2046*e5436536SAndroid Build Coastguard Worker              _el++) {
2047*e5436536SAndroid Build Coastguard Worker           int el = elementOffset + _el;
2048*e5436536SAndroid Build Coastguard Worker           if (IS_USAC_CHANNEL_ELEMENT(self->elements[el])) {
2049*e5436536SAndroid Build Coastguard Worker             if (usacStereoConfigIndex < 0) {
2050*e5436536SAndroid Build Coastguard Worker               usacStereoConfigIndex = self->usacStereoConfigIndex[el];
2051*e5436536SAndroid Build Coastguard Worker             } else {
2052*e5436536SAndroid Build Coastguard Worker               if ((usacStereoConfigIndex != self->usacStereoConfigIndex[el]) ||
2053*e5436536SAndroid Build Coastguard Worker                   (self->usacStereoConfigIndex[el] > 0)) {
2054*e5436536SAndroid Build Coastguard Worker                 goto bail;
2055*e5436536SAndroid Build Coastguard Worker               }
2056*e5436536SAndroid Build Coastguard Worker             }
2057*e5436536SAndroid Build Coastguard Worker           }
2058*e5436536SAndroid Build Coastguard Worker         }
2059*e5436536SAndroid Build Coastguard Worker 
2060*e5436536SAndroid Build Coastguard Worker         if (usacStereoConfigIndex < 0) {
2061*e5436536SAndroid Build Coastguard Worker           goto bail;
2062*e5436536SAndroid Build Coastguard Worker         }
2063*e5436536SAndroid Build Coastguard Worker 
2064*e5436536SAndroid Build Coastguard Worker         if (usacStereoConfigIndex == 3) {
2065*e5436536SAndroid Build Coastguard Worker           flags |= AC_USAC_SCFGI3;
2066*e5436536SAndroid Build Coastguard Worker         }
2067*e5436536SAndroid Build Coastguard Worker       }
2068*e5436536SAndroid Build Coastguard Worker       break;
2069*e5436536SAndroid Build Coastguard Worker     default:
2070*e5436536SAndroid Build Coastguard Worker       break;
2071*e5436536SAndroid Build Coastguard Worker   }
2072*e5436536SAndroid Build Coastguard Worker 
2073*e5436536SAndroid Build Coastguard Worker   if (*configChanged) {
2074*e5436536SAndroid Build Coastguard Worker     /* Set up QMF domain for AOTs with explicit signalling of SBR and or MPS.
2075*e5436536SAndroid Build Coastguard Worker        This is to be able to play out the first frame alway with the correct
2076*e5436536SAndroid Build Coastguard Worker        frame size and sampling rate even in case of concealment.
2077*e5436536SAndroid Build Coastguard Worker     */
2078*e5436536SAndroid Build Coastguard Worker     switch (asc->m_aot) {
2079*e5436536SAndroid Build Coastguard Worker       case AOT_USAC:
2080*e5436536SAndroid Build Coastguard Worker         if (sbrEnabled) {
2081*e5436536SAndroid Build Coastguard Worker           const UCHAR map_sbrRatio_2_nAnaBands[] = {16, 24, 32};
2082*e5436536SAndroid Build Coastguard Worker 
2083*e5436536SAndroid Build Coastguard Worker           FDK_ASSERT(asc->m_sc.m_usacConfig.m_sbrRatioIndex > 0);
2084*e5436536SAndroid Build Coastguard Worker           FDK_ASSERT(streamIndex == 0);
2085*e5436536SAndroid Build Coastguard Worker 
2086*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nInputChannels_requested = ascChannels;
2087*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nOutputChannels_requested =
2088*e5436536SAndroid Build Coastguard Worker               (usacStereoConfigIndex == 1) ? 2 : ascChannels;
2089*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.flags_requested = 0;
2090*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nBandsAnalysis_requested =
2091*e5436536SAndroid Build Coastguard Worker               map_sbrRatio_2_nAnaBands[asc->m_sc.m_usacConfig.m_sbrRatioIndex -
2092*e5436536SAndroid Build Coastguard Worker                                        1];
2093*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nBandsSynthesis_requested = 64;
2094*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nQmfTimeSlots_requested =
2095*e5436536SAndroid Build Coastguard Worker               (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 64 : 32;
2096*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nQmfOvTimeSlots_requested =
2097*e5436536SAndroid Build Coastguard Worker               (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 12 : 6;
2098*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nQmfProcBands_requested = 64;
2099*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.nQmfProcChannels_requested = 1;
2100*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.parkChannel =
2101*e5436536SAndroid Build Coastguard Worker               (usacStereoConfigIndex == 3) ? 1 : 0;
2102*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.parkChannel_requested =
2103*e5436536SAndroid Build Coastguard Worker               (usacStereoConfigIndex == 3) ? 1 : 0;
2104*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1;
2105*e5436536SAndroid Build Coastguard Worker         }
2106*e5436536SAndroid Build Coastguard Worker         break;
2107*e5436536SAndroid Build Coastguard Worker       case AOT_ER_AAC_ELD:
2108*e5436536SAndroid Build Coastguard Worker         if (mpsEnableCurr &&
2109*e5436536SAndroid Build Coastguard Worker             asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) {
2110*e5436536SAndroid Build Coastguard Worker           SAC_INPUT_CONFIG sac_interface = (sbrEnabled && self->hSbrDecoder)
2111*e5436536SAndroid Build Coastguard Worker                                                ? SAC_INTERFACE_QMF
2112*e5436536SAndroid Build Coastguard Worker                                                : SAC_INTERFACE_TIME;
2113*e5436536SAndroid Build Coastguard Worker           mpegSurroundDecoder_ConfigureQmfDomain(
2114*e5436536SAndroid Build Coastguard Worker               (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface,
2115*e5436536SAndroid Build Coastguard Worker               (UINT)self->streamInfo.aacSampleRate, asc->m_aot);
2116*e5436536SAndroid Build Coastguard Worker           self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1;
2117*e5436536SAndroid Build Coastguard Worker         }
2118*e5436536SAndroid Build Coastguard Worker         break;
2119*e5436536SAndroid Build Coastguard Worker       default:
2120*e5436536SAndroid Build Coastguard Worker         self->qmfDomain.globalConf.qmfDomainExplicitConfig =
2121*e5436536SAndroid Build Coastguard Worker             0; /* qmfDomain is initialized by SBR and MPS init functions if
2122*e5436536SAndroid Build Coastguard Worker                   required */
2123*e5436536SAndroid Build Coastguard Worker         break;
2124*e5436536SAndroid Build Coastguard Worker     }
2125*e5436536SAndroid Build Coastguard Worker 
2126*e5436536SAndroid Build Coastguard Worker     /* Allocate all memory structures for each channel */
2127*e5436536SAndroid Build Coastguard Worker     {
2128*e5436536SAndroid Build Coastguard Worker       int ch = aacChannelsOffset;
2129*e5436536SAndroid Build Coastguard Worker       for (int _ch = 0; _ch < ascChannels; _ch++) {
2130*e5436536SAndroid Build Coastguard Worker         if (ch >= (8)) {
2131*e5436536SAndroid Build Coastguard Worker           goto bail;
2132*e5436536SAndroid Build Coastguard Worker         }
2133*e5436536SAndroid Build Coastguard Worker         self->pAacDecoderChannelInfo[ch] = GetAacDecoderChannelInfo(ch);
2134*e5436536SAndroid Build Coastguard Worker         /* This is temporary until the DynamicData is split into two or more
2135*e5436536SAndroid Build Coastguard Worker            regions! The memory could be reused after completed core decoding. */
2136*e5436536SAndroid Build Coastguard Worker         if (self->pAacDecoderChannelInfo[ch] == NULL) {
2137*e5436536SAndroid Build Coastguard Worker           goto bail;
2138*e5436536SAndroid Build Coastguard Worker         }
2139*e5436536SAndroid Build Coastguard Worker         ch++;
2140*e5436536SAndroid Build Coastguard Worker       }
2141*e5436536SAndroid Build Coastguard Worker 
2142*e5436536SAndroid Build Coastguard Worker       int chIdx = aacChannelsOffsetIdx;
2143*e5436536SAndroid Build Coastguard Worker       ch = aacChannelsOffset;
2144*e5436536SAndroid Build Coastguard Worker       int _numElements;
2145*e5436536SAndroid Build Coastguard Worker       _numElements = (((8)) + (8));
2146*e5436536SAndroid Build Coastguard Worker       if (flags & (AC_RSV603DA | AC_USAC)) {
2147*e5436536SAndroid Build Coastguard Worker         _numElements = (int)asc->m_sc.m_usacConfig.m_usacNumElements;
2148*e5436536SAndroid Build Coastguard Worker       }
2149*e5436536SAndroid Build Coastguard Worker       for (int _el = 0; _el < _numElements; _el++) {
2150*e5436536SAndroid Build Coastguard Worker         int el_channels = 0;
2151*e5436536SAndroid Build Coastguard Worker         int el = elementOffset + _el;
2152*e5436536SAndroid Build Coastguard Worker 
2153*e5436536SAndroid Build Coastguard Worker         if (flags &
2154*e5436536SAndroid Build Coastguard Worker             (AC_ER | AC_LD | AC_ELD | AC_RSV603DA | AC_USAC | AC_RSVD50)) {
2155*e5436536SAndroid Build Coastguard Worker           if (ch >= ascChannels) {
2156*e5436536SAndroid Build Coastguard Worker             break;
2157*e5436536SAndroid Build Coastguard Worker           }
2158*e5436536SAndroid Build Coastguard Worker         }
2159*e5436536SAndroid Build Coastguard Worker 
2160*e5436536SAndroid Build Coastguard Worker         switch (self->elements[el]) {
2161*e5436536SAndroid Build Coastguard Worker           case ID_SCE:
2162*e5436536SAndroid Build Coastguard Worker           case ID_CPE:
2163*e5436536SAndroid Build Coastguard Worker           case ID_LFE:
2164*e5436536SAndroid Build Coastguard Worker           case ID_USAC_SCE:
2165*e5436536SAndroid Build Coastguard Worker           case ID_USAC_CPE:
2166*e5436536SAndroid Build Coastguard Worker           case ID_USAC_LFE:
2167*e5436536SAndroid Build Coastguard Worker 
2168*e5436536SAndroid Build Coastguard Worker             el_channels = CAacDecoder_GetELChannels(
2169*e5436536SAndroid Build Coastguard Worker                 self->elements[el], self->usacStereoConfigIndex[el]);
2170*e5436536SAndroid Build Coastguard Worker 
2171*e5436536SAndroid Build Coastguard Worker             {
2172*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderChannelInfo[ch]->pComStaticData =
2173*e5436536SAndroid Build Coastguard Worker                   (CAacDecoderCommonStaticData *)FDKcalloc(
2174*e5436536SAndroid Build Coastguard Worker                       1, sizeof(CAacDecoderCommonStaticData));
2175*e5436536SAndroid Build Coastguard Worker               if (self->pAacDecoderChannelInfo[ch]->pComStaticData == NULL) {
2176*e5436536SAndroid Build Coastguard Worker                 goto bail;
2177*e5436536SAndroid Build Coastguard Worker               }
2178*e5436536SAndroid Build Coastguard Worker               if (ch == aacChannelsOffset) {
2179*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch]->pComData =
2180*e5436536SAndroid Build Coastguard Worker                     (CAacDecoderCommonData *)GetWorkBufferCore6();
2181*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch]
2182*e5436536SAndroid Build Coastguard Worker                     ->pComStaticData->pWorkBufferCore1 = GetWorkBufferCore1();
2183*e5436536SAndroid Build Coastguard Worker               } else {
2184*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch]->pComData =
2185*e5436536SAndroid Build Coastguard Worker                     (CAacDecoderCommonData *)FDKaalloc(
2186*e5436536SAndroid Build Coastguard Worker                         sizeof(CAacDecoderCommonData), ALIGNMENT_DEFAULT);
2187*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch]
2188*e5436536SAndroid Build Coastguard Worker                     ->pComStaticData->pWorkBufferCore1 =
2189*e5436536SAndroid Build Coastguard Worker                     self->pAacDecoderChannelInfo[aacChannelsOffset]
2190*e5436536SAndroid Build Coastguard Worker                         ->pComStaticData->pWorkBufferCore1;
2191*e5436536SAndroid Build Coastguard Worker               }
2192*e5436536SAndroid Build Coastguard Worker               if ((self->pAacDecoderChannelInfo[ch]->pComData == NULL) ||
2193*e5436536SAndroid Build Coastguard Worker                   (self->pAacDecoderChannelInfo[ch]
2194*e5436536SAndroid Build Coastguard Worker                        ->pComStaticData->pWorkBufferCore1 == NULL)) {
2195*e5436536SAndroid Build Coastguard Worker                 goto bail;
2196*e5436536SAndroid Build Coastguard Worker               }
2197*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderChannelInfo[ch]->pDynData =
2198*e5436536SAndroid Build Coastguard Worker                   &(self->pAacDecoderChannelInfo[ch]
2199*e5436536SAndroid Build Coastguard Worker                         ->pComData->pAacDecoderDynamicData[0]);
2200*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderChannelInfo[ch]->pSpectralCoefficient =
2201*e5436536SAndroid Build Coastguard Worker                   (SPECTRAL_PTR)&self->workBufferCore2[ch * 1024];
2202*e5436536SAndroid Build Coastguard Worker 
2203*e5436536SAndroid Build Coastguard Worker               if (el_channels == 2) {
2204*e5436536SAndroid Build Coastguard Worker                 if (ch >= (8) - 1) {
2205*e5436536SAndroid Build Coastguard Worker                   return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
2206*e5436536SAndroid Build Coastguard Worker                 }
2207*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch + 1]->pComData =
2208*e5436536SAndroid Build Coastguard Worker                     self->pAacDecoderChannelInfo[ch]->pComData;
2209*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch + 1]->pComStaticData =
2210*e5436536SAndroid Build Coastguard Worker                     self->pAacDecoderChannelInfo[ch]->pComStaticData;
2211*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch + 1]
2212*e5436536SAndroid Build Coastguard Worker                     ->pComStaticData->pWorkBufferCore1 =
2213*e5436536SAndroid Build Coastguard Worker                     self->pAacDecoderChannelInfo[ch]
2214*e5436536SAndroid Build Coastguard Worker                         ->pComStaticData->pWorkBufferCore1;
2215*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch + 1]->pDynData =
2216*e5436536SAndroid Build Coastguard Worker                     &(self->pAacDecoderChannelInfo[ch]
2217*e5436536SAndroid Build Coastguard Worker                           ->pComData->pAacDecoderDynamicData[1]);
2218*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch + 1]->pSpectralCoefficient =
2219*e5436536SAndroid Build Coastguard Worker                     (SPECTRAL_PTR)&self->workBufferCore2[(ch + 1) * 1024];
2220*e5436536SAndroid Build Coastguard Worker               }
2221*e5436536SAndroid Build Coastguard Worker 
2222*e5436536SAndroid Build Coastguard Worker               ch += el_channels;
2223*e5436536SAndroid Build Coastguard Worker             }
2224*e5436536SAndroid Build Coastguard Worker             chIdx += el_channels;
2225*e5436536SAndroid Build Coastguard Worker             break;
2226*e5436536SAndroid Build Coastguard Worker 
2227*e5436536SAndroid Build Coastguard Worker           default:
2228*e5436536SAndroid Build Coastguard Worker             break;
2229*e5436536SAndroid Build Coastguard Worker         }
2230*e5436536SAndroid Build Coastguard Worker 
2231*e5436536SAndroid Build Coastguard Worker         if (self->elements[el] == ID_END) {
2232*e5436536SAndroid Build Coastguard Worker           break;
2233*e5436536SAndroid Build Coastguard Worker         }
2234*e5436536SAndroid Build Coastguard Worker 
2235*e5436536SAndroid Build Coastguard Worker         el++;
2236*e5436536SAndroid Build Coastguard Worker       }
2237*e5436536SAndroid Build Coastguard Worker 
2238*e5436536SAndroid Build Coastguard Worker       chIdx = aacChannelsOffsetIdx;
2239*e5436536SAndroid Build Coastguard Worker       ch = aacChannelsOffset;
2240*e5436536SAndroid Build Coastguard Worker       for (int _ch = 0; _ch < ascChannels; _ch++) {
2241*e5436536SAndroid Build Coastguard Worker         /* Allocate persistent channel memory */
2242*e5436536SAndroid Build Coastguard Worker         {
2243*e5436536SAndroid Build Coastguard Worker           self->pAacDecoderStaticChannelInfo[ch] =
2244*e5436536SAndroid Build Coastguard Worker               GetAacDecoderStaticChannelInfo(ch);
2245*e5436536SAndroid Build Coastguard Worker           if (self->pAacDecoderStaticChannelInfo[ch] == NULL) {
2246*e5436536SAndroid Build Coastguard Worker             goto bail;
2247*e5436536SAndroid Build Coastguard Worker           }
2248*e5436536SAndroid Build Coastguard Worker           self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer =
2249*e5436536SAndroid Build Coastguard Worker               GetOverlapBuffer(ch); /* This area size depends on the AOT */
2250*e5436536SAndroid Build Coastguard Worker           if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) {
2251*e5436536SAndroid Build Coastguard Worker             goto bail;
2252*e5436536SAndroid Build Coastguard Worker           }
2253*e5436536SAndroid Build Coastguard Worker           if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) {
2254*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderStaticChannelInfo[ch]->hArCo = CArco_Create();
2255*e5436536SAndroid Build Coastguard Worker             if (self->pAacDecoderStaticChannelInfo[ch]->hArCo == NULL) {
2256*e5436536SAndroid Build Coastguard Worker               goto bail;
2257*e5436536SAndroid Build Coastguard Worker             }
2258*e5436536SAndroid Build Coastguard Worker           }
2259*e5436536SAndroid Build Coastguard Worker 
2260*e5436536SAndroid Build Coastguard Worker           if (!(flags & (AC_USAC | AC_RSV603DA))) {
2261*e5436536SAndroid Build Coastguard Worker             CPns_UpdateNoiseState(
2262*e5436536SAndroid Build Coastguard Worker                 &self->pAacDecoderChannelInfo[ch]->data.aac.PnsData,
2263*e5436536SAndroid Build Coastguard Worker                 &self->pAacDecoderStaticChannelInfo[ch]->pnsCurrentSeed,
2264*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderChannelInfo[ch]->pComData->pnsRandomSeed);
2265*e5436536SAndroid Build Coastguard Worker           }
2266*e5436536SAndroid Build Coastguard Worker           ch++;
2267*e5436536SAndroid Build Coastguard Worker         }
2268*e5436536SAndroid Build Coastguard Worker         chIdx++;
2269*e5436536SAndroid Build Coastguard Worker       }
2270*e5436536SAndroid Build Coastguard Worker 
2271*e5436536SAndroid Build Coastguard Worker       if (flags & AC_USAC) {
2272*e5436536SAndroid Build Coastguard Worker         for (int _ch = 0; _ch < flushChannels; _ch++) {
2273*e5436536SAndroid Build Coastguard Worker           ch = aacChannelsOffset + _ch;
2274*e5436536SAndroid Build Coastguard Worker           if (self->pTimeDataFlush[ch] == NULL) {
2275*e5436536SAndroid Build Coastguard Worker             self->pTimeDataFlush[ch] = GetTimeDataFlush(ch);
2276*e5436536SAndroid Build Coastguard Worker             if (self->pTimeDataFlush[ch] == NULL) {
2277*e5436536SAndroid Build Coastguard Worker               goto bail;
2278*e5436536SAndroid Build Coastguard Worker             }
2279*e5436536SAndroid Build Coastguard Worker           }
2280*e5436536SAndroid Build Coastguard Worker         }
2281*e5436536SAndroid Build Coastguard Worker       }
2282*e5436536SAndroid Build Coastguard Worker 
2283*e5436536SAndroid Build Coastguard Worker       if (flags & (AC_USAC | AC_RSV603DA)) {
2284*e5436536SAndroid Build Coastguard Worker         int complexStereoPredPossible = 0;
2285*e5436536SAndroid Build Coastguard Worker         ch = aacChannelsOffset;
2286*e5436536SAndroid Build Coastguard Worker         chIdx = aacChannelsOffsetIdx;
2287*e5436536SAndroid Build Coastguard Worker         for (int _el2 = 0; _el2 < (int)asc->m_sc.m_usacConfig.m_usacNumElements;
2288*e5436536SAndroid Build Coastguard Worker              _el2++) {
2289*e5436536SAndroid Build Coastguard Worker           int el2 = elementOffset + _el2;
2290*e5436536SAndroid Build Coastguard Worker           int elCh = 0, ch2;
2291*e5436536SAndroid Build Coastguard Worker 
2292*e5436536SAndroid Build Coastguard Worker           if ((self->elements[el2] == ID_USAC_CPE) &&
2293*e5436536SAndroid Build Coastguard Worker               !(self->usacStereoConfigIndex[el2] == 1)) {
2294*e5436536SAndroid Build Coastguard Worker             elCh = 2;
2295*e5436536SAndroid Build Coastguard Worker           } else if (IS_CHANNEL_ELEMENT(self->elements[el2])) {
2296*e5436536SAndroid Build Coastguard Worker             elCh = 1;
2297*e5436536SAndroid Build Coastguard Worker           }
2298*e5436536SAndroid Build Coastguard Worker 
2299*e5436536SAndroid Build Coastguard Worker           if (elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) {
2300*e5436536SAndroid Build Coastguard Worker             complexStereoPredPossible = 1;
2301*e5436536SAndroid Build Coastguard Worker             if (self->cpeStaticData[el2] == NULL) {
2302*e5436536SAndroid Build Coastguard Worker               self->cpeStaticData[el2] = GetCpePersistentData();
2303*e5436536SAndroid Build Coastguard Worker               if (self->cpeStaticData[el2] == NULL) {
2304*e5436536SAndroid Build Coastguard Worker                 goto bail;
2305*e5436536SAndroid Build Coastguard Worker               }
2306*e5436536SAndroid Build Coastguard Worker             }
2307*e5436536SAndroid Build Coastguard Worker           }
2308*e5436536SAndroid Build Coastguard Worker 
2309*e5436536SAndroid Build Coastguard Worker           for (ch2 = 0; ch2 < elCh; ch2++) {
2310*e5436536SAndroid Build Coastguard Worker             /* Hook element specific cpeStaticData into channel specific
2311*e5436536SAndroid Build Coastguard Worker              * aacDecoderStaticChannelInfo */
2312*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData =
2313*e5436536SAndroid Build Coastguard Worker                 self->cpeStaticData[el2];
2314*e5436536SAndroid Build Coastguard Worker             if (self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData !=
2315*e5436536SAndroid Build Coastguard Worker                 NULL) {
2316*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderStaticChannelInfo[ch]
2317*e5436536SAndroid Build Coastguard Worker                   ->pCpeStaticData->jointStereoPersistentData
2318*e5436536SAndroid Build Coastguard Worker                   .spectralCoeffs[ch2] =
2319*e5436536SAndroid Build Coastguard Worker                   self->pAacDecoderStaticChannelInfo[ch]
2320*e5436536SAndroid Build Coastguard Worker                       ->concealmentInfo.spectralCoefficient;
2321*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderStaticChannelInfo[ch]
2322*e5436536SAndroid Build Coastguard Worker                   ->pCpeStaticData->jointStereoPersistentData.specScale[ch2] =
2323*e5436536SAndroid Build Coastguard Worker                   self->pAacDecoderStaticChannelInfo[ch]
2324*e5436536SAndroid Build Coastguard Worker                       ->concealmentInfo.specScale;
2325*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderStaticChannelInfo[ch]
2326*e5436536SAndroid Build Coastguard Worker                   ->pCpeStaticData->jointStereoPersistentData.scratchBuffer =
2327*e5436536SAndroid Build Coastguard Worker                   (FIXP_DBL *)self->pTimeData2;
2328*e5436536SAndroid Build Coastguard Worker             }
2329*e5436536SAndroid Build Coastguard Worker             chIdx++;
2330*e5436536SAndroid Build Coastguard Worker             ch++;
2331*e5436536SAndroid Build Coastguard Worker           } /* for each channel in current element */
2332*e5436536SAndroid Build Coastguard Worker           if (complexStereoPredPossible && (elCh == 2)) {
2333*e5436536SAndroid Build Coastguard Worker             /* needed once for all channels */
2334*e5436536SAndroid Build Coastguard Worker             if (self->pAacDecoderChannelInfo[ch - 1]
2335*e5436536SAndroid Build Coastguard Worker                     ->pComStaticData->cplxPredictionData == NULL) {
2336*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderChannelInfo[ch - 1]
2337*e5436536SAndroid Build Coastguard Worker                   ->pComStaticData->cplxPredictionData =
2338*e5436536SAndroid Build Coastguard Worker                   GetCplxPredictionData();
2339*e5436536SAndroid Build Coastguard Worker             }
2340*e5436536SAndroid Build Coastguard Worker             if (self->pAacDecoderChannelInfo[ch - 1]
2341*e5436536SAndroid Build Coastguard Worker                     ->pComStaticData->cplxPredictionData == NULL) {
2342*e5436536SAndroid Build Coastguard Worker               goto bail;
2343*e5436536SAndroid Build Coastguard Worker             }
2344*e5436536SAndroid Build Coastguard Worker           }
2345*e5436536SAndroid Build Coastguard Worker           if (elCh > 0) {
2346*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderStaticChannelInfo[ch - elCh]->nfRandomSeed =
2347*e5436536SAndroid Build Coastguard Worker                 (ULONG)0x3039;
2348*e5436536SAndroid Build Coastguard Worker             if (self->elements[el2] == ID_USAC_CPE) {
2349*e5436536SAndroid Build Coastguard Worker               if (asc->m_sc.m_usacConfig.element[el2].m_stereoConfigIndex !=
2350*e5436536SAndroid Build Coastguard Worker                   1) {
2351*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderStaticChannelInfo[ch - elCh + 1]
2352*e5436536SAndroid Build Coastguard Worker                     ->nfRandomSeed = (ULONG)0x10932;
2353*e5436536SAndroid Build Coastguard Worker               }
2354*e5436536SAndroid Build Coastguard Worker             }
2355*e5436536SAndroid Build Coastguard Worker           }
2356*e5436536SAndroid Build Coastguard Worker         } /* for each element */
2357*e5436536SAndroid Build Coastguard Worker       }
2358*e5436536SAndroid Build Coastguard Worker 
2359*e5436536SAndroid Build Coastguard Worker       if (ascChannels != self->aacChannels) {
2360*e5436536SAndroid Build Coastguard Worker         /* Make allocated channel count persistent in decoder context. */
2361*e5436536SAndroid Build Coastguard Worker         self->aacChannels = aacChannelsOffset + ch;
2362*e5436536SAndroid Build Coastguard Worker       }
2363*e5436536SAndroid Build Coastguard Worker     }
2364*e5436536SAndroid Build Coastguard Worker 
2365*e5436536SAndroid Build Coastguard Worker     if (usacResidualDelayCompSamples) {
2366*e5436536SAndroid Build Coastguard Worker       INT delayErr = FDK_Delay_Create(&self->usacResidualDelay,
2367*e5436536SAndroid Build Coastguard Worker                                       (USHORT)usacResidualDelayCompSamples, 1);
2368*e5436536SAndroid Build Coastguard Worker       if (delayErr) {
2369*e5436536SAndroid Build Coastguard Worker         goto bail;
2370*e5436536SAndroid Build Coastguard Worker       }
2371*e5436536SAndroid Build Coastguard Worker     }
2372*e5436536SAndroid Build Coastguard Worker 
2373*e5436536SAndroid Build Coastguard Worker     /* Make amount of signalled channels persistent in decoder context. */
2374*e5436536SAndroid Build Coastguard Worker     self->ascChannels[streamIndex] = ascChannels;
2375*e5436536SAndroid Build Coastguard Worker     /* Init the previous channel count values. This is required to avoid a
2376*e5436536SAndroid Build Coastguard Worker        mismatch of memory accesses in the error concealment module and the
2377*e5436536SAndroid Build Coastguard Worker        allocated channel structures in this function. */
2378*e5436536SAndroid Build Coastguard Worker     self->aacChannelsPrev = 0;
2379*e5436536SAndroid Build Coastguard Worker   }
2380*e5436536SAndroid Build Coastguard Worker 
2381*e5436536SAndroid Build Coastguard Worker   if (self->pAacDecoderChannelInfo[0] != NULL) {
2382*e5436536SAndroid Build Coastguard Worker     self->pDrmBsBuffer = self->pAacDecoderChannelInfo[0]
2383*e5436536SAndroid Build Coastguard Worker                              ->pComStaticData->pWorkBufferCore1->DrmBsBuffer;
2384*e5436536SAndroid Build Coastguard Worker     self->drmBsBufferSize = DRM_BS_BUFFER_SIZE;
2385*e5436536SAndroid Build Coastguard Worker   }
2386*e5436536SAndroid Build Coastguard Worker 
2387*e5436536SAndroid Build Coastguard Worker   /* Update structures */
2388*e5436536SAndroid Build Coastguard Worker   if (*configChanged) {
2389*e5436536SAndroid Build Coastguard Worker     /* Things to be done for each channel, which do not involve allocating
2390*e5436536SAndroid Build Coastguard Worker        memory. Doing these things only on the channels needed for the current
2391*e5436536SAndroid Build Coastguard Worker        configuration (ascChannels) could lead to memory access violation later
2392*e5436536SAndroid Build Coastguard Worker        (error concealment). */
2393*e5436536SAndroid Build Coastguard Worker     int ch = 0;
2394*e5436536SAndroid Build Coastguard Worker     int chIdx = 0;
2395*e5436536SAndroid Build Coastguard Worker     for (int _ch = 0; _ch < self->ascChannels[streamIndex]; _ch++) {
2396*e5436536SAndroid Build Coastguard Worker       switch (self->streamInfo.aot) {
2397*e5436536SAndroid Build Coastguard Worker         case AOT_ER_AAC_ELD:
2398*e5436536SAndroid Build Coastguard Worker         case AOT_ER_AAC_LD:
2399*e5436536SAndroid Build Coastguard Worker           self->pAacDecoderChannelInfo[ch]->granuleLength =
2400*e5436536SAndroid Build Coastguard Worker               self->streamInfo.aacSamplesPerFrame;
2401*e5436536SAndroid Build Coastguard Worker           break;
2402*e5436536SAndroid Build Coastguard Worker         default:
2403*e5436536SAndroid Build Coastguard Worker           self->pAacDecoderChannelInfo[ch]->granuleLength =
2404*e5436536SAndroid Build Coastguard Worker               self->streamInfo.aacSamplesPerFrame / 8;
2405*e5436536SAndroid Build Coastguard Worker           break;
2406*e5436536SAndroid Build Coastguard Worker       }
2407*e5436536SAndroid Build Coastguard Worker       self->pAacDecoderChannelInfo[ch]->renderMode = initRenderMode;
2408*e5436536SAndroid Build Coastguard Worker 
2409*e5436536SAndroid Build Coastguard Worker       mdct_init(&self->pAacDecoderStaticChannelInfo[ch]->IMdct,
2410*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer,
2411*e5436536SAndroid Build Coastguard Worker                 OverlapBufferSize);
2412*e5436536SAndroid Build Coastguard Worker 
2413*e5436536SAndroid Build Coastguard Worker       self->pAacDecoderStaticChannelInfo[ch]->last_core_mode = FD_LONG;
2414*e5436536SAndroid Build Coastguard Worker       self->pAacDecoderStaticChannelInfo[ch]->last_lpd_mode = 255;
2415*e5436536SAndroid Build Coastguard Worker 
2416*e5436536SAndroid Build Coastguard Worker       self->pAacDecoderStaticChannelInfo[ch]->last_tcx_pitch = L_DIV;
2417*e5436536SAndroid Build Coastguard Worker 
2418*e5436536SAndroid Build Coastguard Worker       /* Reset DRC control data for this channel */
2419*e5436536SAndroid Build Coastguard Worker       aacDecoder_drcInitChannelData(
2420*e5436536SAndroid Build Coastguard Worker           &self->pAacDecoderStaticChannelInfo[ch]->drcData);
2421*e5436536SAndroid Build Coastguard Worker 
2422*e5436536SAndroid Build Coastguard Worker       /* Delete mixdown metadata from the past */
2423*e5436536SAndroid Build Coastguard Worker       pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA);
2424*e5436536SAndroid Build Coastguard Worker 
2425*e5436536SAndroid Build Coastguard Worker       /* Reset concealment only if ASC changed. Otherwise it will be done with
2426*e5436536SAndroid Build Coastguard Worker          any config callback. E.g. every time the LATM SMC is present. */
2427*e5436536SAndroid Build Coastguard Worker       CConcealment_InitChannelData(
2428*e5436536SAndroid Build Coastguard Worker           &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
2429*e5436536SAndroid Build Coastguard Worker           &self->concealCommonData, initRenderMode,
2430*e5436536SAndroid Build Coastguard Worker           self->streamInfo.aacSamplesPerFrame);
2431*e5436536SAndroid Build Coastguard Worker       ch++;
2432*e5436536SAndroid Build Coastguard Worker       chIdx++;
2433*e5436536SAndroid Build Coastguard Worker     }
2434*e5436536SAndroid Build Coastguard Worker   }
2435*e5436536SAndroid Build Coastguard Worker 
2436*e5436536SAndroid Build Coastguard Worker   if (*configChanged) {
2437*e5436536SAndroid Build Coastguard Worker     int drcDecSampleRate, drcDecFrameSize;
2438*e5436536SAndroid Build Coastguard Worker 
2439*e5436536SAndroid Build Coastguard Worker     if (self->streamInfo.extSamplingRate != 0) {
2440*e5436536SAndroid Build Coastguard Worker       drcDecSampleRate = self->streamInfo.extSamplingRate;
2441*e5436536SAndroid Build Coastguard Worker       drcDecFrameSize = (self->streamInfo.aacSamplesPerFrame *
2442*e5436536SAndroid Build Coastguard Worker                          self->streamInfo.extSamplingRate) /
2443*e5436536SAndroid Build Coastguard Worker                         self->streamInfo.aacSampleRate;
2444*e5436536SAndroid Build Coastguard Worker     } else {
2445*e5436536SAndroid Build Coastguard Worker       drcDecSampleRate = self->streamInfo.aacSampleRate;
2446*e5436536SAndroid Build Coastguard Worker       drcDecFrameSize = self->streamInfo.aacSamplesPerFrame;
2447*e5436536SAndroid Build Coastguard Worker     }
2448*e5436536SAndroid Build Coastguard Worker 
2449*e5436536SAndroid Build Coastguard Worker     if (FDK_drcDec_Init(self->hUniDrcDecoder, drcDecFrameSize, drcDecSampleRate,
2450*e5436536SAndroid Build Coastguard Worker                         self->aacChannels) != 0)
2451*e5436536SAndroid Build Coastguard Worker       goto bail;
2452*e5436536SAndroid Build Coastguard Worker   }
2453*e5436536SAndroid Build Coastguard Worker 
2454*e5436536SAndroid Build Coastguard Worker   if (*configChanged) {
2455*e5436536SAndroid Build Coastguard Worker     if (asc->m_aot == AOT_USAC) {
2456*e5436536SAndroid Build Coastguard Worker       aacDecoder_drcDisable(self->hDrcInfo);
2457*e5436536SAndroid Build Coastguard Worker     }
2458*e5436536SAndroid Build Coastguard Worker   }
2459*e5436536SAndroid Build Coastguard Worker 
2460*e5436536SAndroid Build Coastguard Worker   if (asc->m_aot == AOT_USAC) {
2461*e5436536SAndroid Build Coastguard Worker     pcmLimiter_SetAttack(self->hLimiter, (5));
2462*e5436536SAndroid Build Coastguard Worker     pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f));
2463*e5436536SAndroid Build Coastguard Worker   }
2464*e5436536SAndroid Build Coastguard Worker 
2465*e5436536SAndroid Build Coastguard Worker   CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex,
2466*e5436536SAndroid Build Coastguard Worker                           elementOffset);
2467*e5436536SAndroid Build Coastguard Worker   self->sbrEnabled = sbrEnabled;
2468*e5436536SAndroid Build Coastguard Worker   self->sbrEnabledPrev = sbrEnabledPrev;
2469*e5436536SAndroid Build Coastguard Worker   self->mpsEnableCurr = mpsEnableCurr;
2470*e5436536SAndroid Build Coastguard Worker 
2471*e5436536SAndroid Build Coastguard Worker   /* Update externally visible copy of flags */
2472*e5436536SAndroid Build Coastguard Worker   self->streamInfo.flags = self->flags[0];
2473*e5436536SAndroid Build Coastguard Worker 
2474*e5436536SAndroid Build Coastguard Worker   return err;
2475*e5436536SAndroid Build Coastguard Worker 
2476*e5436536SAndroid Build Coastguard Worker bail:
2477*e5436536SAndroid Build Coastguard Worker   CAacDecoder_DeInit(self, 0);
2478*e5436536SAndroid Build Coastguard Worker   return AAC_DEC_OUT_OF_MEMORY;
2479*e5436536SAndroid Build Coastguard Worker }
2480*e5436536SAndroid Build Coastguard Worker 
CAacDecoder_DecodeFrame(HANDLE_AACDECODER self,const UINT flags,PCM_DEC * pTimeData,const INT timeDataSize,const int timeDataChannelOffset)2481*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
2482*e5436536SAndroid Build Coastguard Worker     HANDLE_AACDECODER self, const UINT flags, PCM_DEC *pTimeData,
2483*e5436536SAndroid Build Coastguard Worker     const INT timeDataSize, const int timeDataChannelOffset) {
2484*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
2485*e5436536SAndroid Build Coastguard Worker 
2486*e5436536SAndroid Build Coastguard Worker   CProgramConfig *pce;
2487*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM bs = transportDec_GetBitstream(self->hInput, 0);
2488*e5436536SAndroid Build Coastguard Worker 
2489*e5436536SAndroid Build Coastguard Worker   MP4_ELEMENT_ID type = ID_NONE; /* Current element type */
2490*e5436536SAndroid Build Coastguard Worker   INT aacChannels = 0; /* Channel counter for channels found in the bitstream */
2491*e5436536SAndroid Build Coastguard Worker   const int streamIndex = 0; /* index of the current substream */
2492*e5436536SAndroid Build Coastguard Worker 
2493*e5436536SAndroid Build Coastguard Worker   INT auStartAnchor = (INT)FDKgetValidBits(
2494*e5436536SAndroid Build Coastguard Worker       bs); /* AU start bit buffer position for AU byte alignment */
2495*e5436536SAndroid Build Coastguard Worker 
2496*e5436536SAndroid Build Coastguard Worker   INT checkSampleRate = self->streamInfo.aacSampleRate;
2497*e5436536SAndroid Build Coastguard Worker 
2498*e5436536SAndroid Build Coastguard Worker   INT CConceal_TDFading_Applied[(8)] = {
2499*e5436536SAndroid Build Coastguard Worker       0}; /* Initialize status of Time Domain fading */
2500*e5436536SAndroid Build Coastguard Worker 
2501*e5436536SAndroid Build Coastguard Worker   if (self->aacChannels <= 0) {
2502*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
2503*e5436536SAndroid Build Coastguard Worker   }
2504*e5436536SAndroid Build Coastguard Worker 
2505*e5436536SAndroid Build Coastguard Worker   /* Any supported base layer valid AU will require more than 16 bits. */
2506*e5436536SAndroid Build Coastguard Worker   if ((transportDec_GetAuBitsRemaining(self->hInput, 0) < 15) &&
2507*e5436536SAndroid Build Coastguard Worker       (flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) == 0) {
2508*e5436536SAndroid Build Coastguard Worker     self->frameOK = 0;
2509*e5436536SAndroid Build Coastguard Worker     ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
2510*e5436536SAndroid Build Coastguard Worker   }
2511*e5436536SAndroid Build Coastguard Worker 
2512*e5436536SAndroid Build Coastguard Worker   /* Reset Program Config structure */
2513*e5436536SAndroid Build Coastguard Worker   pce = &self->pce;
2514*e5436536SAndroid Build Coastguard Worker   CProgramConfig_Reset(pce);
2515*e5436536SAndroid Build Coastguard Worker 
2516*e5436536SAndroid Build Coastguard Worker   CAacDecoder_AncDataReset(&self->ancData);
2517*e5436536SAndroid Build Coastguard Worker   if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) &&
2518*e5436536SAndroid Build Coastguard Worker       !(self->flags[0] & (AC_USAC | AC_RSV603DA))) {
2519*e5436536SAndroid Build Coastguard Worker     int ch;
2520*e5436536SAndroid Build Coastguard Worker     if (self->streamInfo.channelConfig == 0) {
2521*e5436536SAndroid Build Coastguard Worker       /* Init Channel/Element mapping table */
2522*e5436536SAndroid Build Coastguard Worker       for (ch = 0; ch < (8); ch++) {
2523*e5436536SAndroid Build Coastguard Worker         self->chMapping[ch] = 255;
2524*e5436536SAndroid Build Coastguard Worker       }
2525*e5436536SAndroid Build Coastguard Worker       if (!CProgramConfig_IsValid(pce)) {
2526*e5436536SAndroid Build Coastguard Worker         int el;
2527*e5436536SAndroid Build Coastguard Worker         for (el = 0; el < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1);
2528*e5436536SAndroid Build Coastguard Worker              el++) {
2529*e5436536SAndroid Build Coastguard Worker           self->elements[el] = ID_NONE;
2530*e5436536SAndroid Build Coastguard Worker         }
2531*e5436536SAndroid Build Coastguard Worker       }
2532*e5436536SAndroid Build Coastguard Worker     }
2533*e5436536SAndroid Build Coastguard Worker   }
2534*e5436536SAndroid Build Coastguard Worker 
2535*e5436536SAndroid Build Coastguard Worker   if (self->downscaleFactor > 1 && (self->flags[0] & AC_ELD)) {
2536*e5436536SAndroid Build Coastguard Worker     self->flags[0] |= AC_ELD_DOWNSCALE;
2537*e5436536SAndroid Build Coastguard Worker   } else {
2538*e5436536SAndroid Build Coastguard Worker     self->flags[0] &= ~AC_ELD_DOWNSCALE;
2539*e5436536SAndroid Build Coastguard Worker   }
2540*e5436536SAndroid Build Coastguard Worker   /* unsupported dsf (aacSampleRate has not yet been divided by dsf) -> divide
2541*e5436536SAndroid Build Coastguard Worker    */
2542*e5436536SAndroid Build Coastguard Worker   if (self->downscaleFactorInBS > 1 &&
2543*e5436536SAndroid Build Coastguard Worker       (self->flags[0] & AC_ELD_DOWNSCALE) == 0) {
2544*e5436536SAndroid Build Coastguard Worker     checkSampleRate =
2545*e5436536SAndroid Build Coastguard Worker         self->streamInfo.aacSampleRate / self->downscaleFactorInBS;
2546*e5436536SAndroid Build Coastguard Worker   }
2547*e5436536SAndroid Build Coastguard Worker 
2548*e5436536SAndroid Build Coastguard Worker   /* Check sampling frequency  */
2549*e5436536SAndroid Build Coastguard Worker   if (self->streamInfo.aacSampleRate <= 0) {
2550*e5436536SAndroid Build Coastguard Worker     /* Instance maybe uninitialized! */
2551*e5436536SAndroid Build Coastguard Worker     return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
2552*e5436536SAndroid Build Coastguard Worker   }
2553*e5436536SAndroid Build Coastguard Worker   switch (checkSampleRate) {
2554*e5436536SAndroid Build Coastguard Worker     case 96000:
2555*e5436536SAndroid Build Coastguard Worker     case 88200:
2556*e5436536SAndroid Build Coastguard Worker     case 64000:
2557*e5436536SAndroid Build Coastguard Worker     case 16000:
2558*e5436536SAndroid Build Coastguard Worker     case 12000:
2559*e5436536SAndroid Build Coastguard Worker     case 11025:
2560*e5436536SAndroid Build Coastguard Worker     case 8000:
2561*e5436536SAndroid Build Coastguard Worker     case 7350:
2562*e5436536SAndroid Build Coastguard Worker     case 48000:
2563*e5436536SAndroid Build Coastguard Worker     case 44100:
2564*e5436536SAndroid Build Coastguard Worker     case 32000:
2565*e5436536SAndroid Build Coastguard Worker     case 24000:
2566*e5436536SAndroid Build Coastguard Worker     case 22050:
2567*e5436536SAndroid Build Coastguard Worker       break;
2568*e5436536SAndroid Build Coastguard Worker     default:
2569*e5436536SAndroid Build Coastguard Worker       if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) {
2570*e5436536SAndroid Build Coastguard Worker         return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
2571*e5436536SAndroid Build Coastguard Worker       }
2572*e5436536SAndroid Build Coastguard Worker       break;
2573*e5436536SAndroid Build Coastguard Worker   }
2574*e5436536SAndroid Build Coastguard Worker 
2575*e5436536SAndroid Build Coastguard Worker   if (flags & AACDEC_CLRHIST) {
2576*e5436536SAndroid Build Coastguard Worker     if (!(self->flags[0] & AC_USAC)) {
2577*e5436536SAndroid Build Coastguard Worker       int ch;
2578*e5436536SAndroid Build Coastguard Worker       /* Clear history */
2579*e5436536SAndroid Build Coastguard Worker       for (ch = 0; ch < self->aacChannels; ch++) {
2580*e5436536SAndroid Build Coastguard Worker         /* Reset concealment */
2581*e5436536SAndroid Build Coastguard Worker         CConcealment_InitChannelData(
2582*e5436536SAndroid Build Coastguard Worker             &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
2583*e5436536SAndroid Build Coastguard Worker             &self->concealCommonData,
2584*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderChannelInfo[0]->renderMode,
2585*e5436536SAndroid Build Coastguard Worker             self->streamInfo.aacSamplesPerFrame);
2586*e5436536SAndroid Build Coastguard Worker         /* Clear overlap-add buffers to avoid clicks. */
2587*e5436536SAndroid Build Coastguard Worker         FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer,
2588*e5436536SAndroid Build Coastguard Worker                     OverlapBufferSize * sizeof(FIXP_DBL));
2589*e5436536SAndroid Build Coastguard Worker       }
2590*e5436536SAndroid Build Coastguard Worker       if (self->streamInfo.channelConfig > 0) {
2591*e5436536SAndroid Build Coastguard Worker         /* Declare the possibly adopted old PCE (with outdated metadata)
2592*e5436536SAndroid Build Coastguard Worker          * invalid. */
2593*e5436536SAndroid Build Coastguard Worker         CProgramConfig_Init(pce);
2594*e5436536SAndroid Build Coastguard Worker       }
2595*e5436536SAndroid Build Coastguard Worker     }
2596*e5436536SAndroid Build Coastguard Worker   }
2597*e5436536SAndroid Build Coastguard Worker 
2598*e5436536SAndroid Build Coastguard Worker   int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */
2599*e5436536SAndroid Build Coastguard Worker 
2600*e5436536SAndroid Build Coastguard Worker   INT hdaacDecoded = 0;
2601*e5436536SAndroid Build Coastguard Worker   MP4_ELEMENT_ID previous_element =
2602*e5436536SAndroid Build Coastguard Worker       ID_END; /* Last element ID (required for extension payload mapping */
2603*e5436536SAndroid Build Coastguard Worker   UCHAR previous_element_index = 0; /* Canonical index of last element */
2604*e5436536SAndroid Build Coastguard Worker   int element_count =
2605*e5436536SAndroid Build Coastguard Worker       0; /* Element counter for elements found in the bitstream */
2606*e5436536SAndroid Build Coastguard Worker   int channel_element_count = 0; /* Channel element counter */
2607*e5436536SAndroid Build Coastguard Worker   MP4_ELEMENT_ID
2608*e5436536SAndroid Build Coastguard Worker   channel_elements[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) +
2609*e5436536SAndroid Build Coastguard Worker                     1)];     /* Channel elements in bit stream order. */
2610*e5436536SAndroid Build Coastguard Worker   int el_cnt[ID_LAST] = {0}; /* element counter ( robustness ) */
2611*e5436536SAndroid Build Coastguard Worker   int element_count_prev_streams =
2612*e5436536SAndroid Build Coastguard Worker       0; /* Element count of all previous sub streams. */
2613*e5436536SAndroid Build Coastguard Worker 
2614*e5436536SAndroid Build Coastguard Worker   while ((type != ID_END) && (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) &&
2615*e5436536SAndroid Build Coastguard Worker          self->frameOK) {
2616*e5436536SAndroid Build Coastguard Worker     int el_channels;
2617*e5436536SAndroid Build Coastguard Worker 
2618*e5436536SAndroid Build Coastguard Worker     if (!(self->flags[0] &
2619*e5436536SAndroid Build Coastguard Worker           (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_ELD | AC_SCALABLE | AC_ER)))
2620*e5436536SAndroid Build Coastguard Worker       type = (MP4_ELEMENT_ID)FDKreadBits(bs, 3);
2621*e5436536SAndroid Build Coastguard Worker     else {
2622*e5436536SAndroid Build Coastguard Worker       if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
2623*e5436536SAndroid Build Coastguard Worker         self->frameOK = 0;
2624*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_PARSE_ERROR;
2625*e5436536SAndroid Build Coastguard Worker         break;
2626*e5436536SAndroid Build Coastguard Worker       }
2627*e5436536SAndroid Build Coastguard Worker       type = self->elements[element_count];
2628*e5436536SAndroid Build Coastguard Worker     }
2629*e5436536SAndroid Build Coastguard Worker 
2630*e5436536SAndroid Build Coastguard Worker     if ((self->flags[streamIndex] & (AC_USAC | AC_RSVD50) &&
2631*e5436536SAndroid Build Coastguard Worker          element_count == 0) ||
2632*e5436536SAndroid Build Coastguard Worker         (self->flags[streamIndex] & AC_RSV603DA)) {
2633*e5436536SAndroid Build Coastguard Worker       self->flags[streamIndex] &= ~AC_INDEP;
2634*e5436536SAndroid Build Coastguard Worker 
2635*e5436536SAndroid Build Coastguard Worker       if (FDKreadBit(bs)) {
2636*e5436536SAndroid Build Coastguard Worker         self->flags[streamIndex] |= AC_INDEP;
2637*e5436536SAndroid Build Coastguard Worker       }
2638*e5436536SAndroid Build Coastguard Worker 
2639*e5436536SAndroid Build Coastguard Worker       int ch = aacChannels;
2640*e5436536SAndroid Build Coastguard Worker       for (int chIdx = aacChannels; chIdx < self->ascChannels[streamIndex];
2641*e5436536SAndroid Build Coastguard Worker            chIdx++) {
2642*e5436536SAndroid Build Coastguard Worker         {
2643*e5436536SAndroid Build Coastguard Worker           /* Robustness check */
2644*e5436536SAndroid Build Coastguard Worker           if (ch >= self->aacChannels) {
2645*e5436536SAndroid Build Coastguard Worker             return AAC_DEC_UNKNOWN;
2646*e5436536SAndroid Build Coastguard Worker           }
2647*e5436536SAndroid Build Coastguard Worker 
2648*e5436536SAndroid Build Coastguard Worker           /* if last frame was broken and this frame is no independent frame,
2649*e5436536SAndroid Build Coastguard Worker            * correct decoding is impossible we need to trigger concealment */
2650*e5436536SAndroid Build Coastguard Worker           if ((CConcealment_GetLastFrameOk(
2651*e5436536SAndroid Build Coastguard Worker                    &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
2652*e5436536SAndroid Build Coastguard Worker                    1) == 0) &&
2653*e5436536SAndroid Build Coastguard Worker               !(self->flags[streamIndex] & AC_INDEP)) {
2654*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2655*e5436536SAndroid Build Coastguard Worker           }
2656*e5436536SAndroid Build Coastguard Worker           ch++;
2657*e5436536SAndroid Build Coastguard Worker         }
2658*e5436536SAndroid Build Coastguard Worker       }
2659*e5436536SAndroid Build Coastguard Worker     }
2660*e5436536SAndroid Build Coastguard Worker 
2661*e5436536SAndroid Build Coastguard Worker     if ((INT)FDKgetValidBits(bs) < 0) {
2662*e5436536SAndroid Build Coastguard Worker       self->frameOK = 0;
2663*e5436536SAndroid Build Coastguard Worker     }
2664*e5436536SAndroid Build Coastguard Worker 
2665*e5436536SAndroid Build Coastguard Worker     switch (type) {
2666*e5436536SAndroid Build Coastguard Worker       case ID_SCE:
2667*e5436536SAndroid Build Coastguard Worker       case ID_CPE:
2668*e5436536SAndroid Build Coastguard Worker       case ID_LFE:
2669*e5436536SAndroid Build Coastguard Worker       case ID_USAC_SCE:
2670*e5436536SAndroid Build Coastguard Worker       case ID_USAC_CPE:
2671*e5436536SAndroid Build Coastguard Worker       case ID_USAC_LFE:
2672*e5436536SAndroid Build Coastguard Worker         if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
2673*e5436536SAndroid Build Coastguard Worker           self->frameOK = 0;
2674*e5436536SAndroid Build Coastguard Worker           ErrorStatus = AAC_DEC_PARSE_ERROR;
2675*e5436536SAndroid Build Coastguard Worker           break;
2676*e5436536SAndroid Build Coastguard Worker         }
2677*e5436536SAndroid Build Coastguard Worker 
2678*e5436536SAndroid Build Coastguard Worker         el_channels = CAacDecoder_GetELChannels(
2679*e5436536SAndroid Build Coastguard Worker             type, self->usacStereoConfigIndex[element_count]);
2680*e5436536SAndroid Build Coastguard Worker 
2681*e5436536SAndroid Build Coastguard Worker         /*
2682*e5436536SAndroid Build Coastguard Worker           Consistency check
2683*e5436536SAndroid Build Coastguard Worker          */
2684*e5436536SAndroid Build Coastguard Worker         {
2685*e5436536SAndroid Build Coastguard Worker           int totalAscChannels = 0;
2686*e5436536SAndroid Build Coastguard Worker 
2687*e5436536SAndroid Build Coastguard Worker           for (int i = 0; i < (1 * 1); i++) {
2688*e5436536SAndroid Build Coastguard Worker             totalAscChannels += self->ascChannels[i];
2689*e5436536SAndroid Build Coastguard Worker           }
2690*e5436536SAndroid Build Coastguard Worker           if ((el_cnt[type] >= (totalAscChannels >> (el_channels - 1))) ||
2691*e5436536SAndroid Build Coastguard Worker               (aacChannels > (totalAscChannels - el_channels))) {
2692*e5436536SAndroid Build Coastguard Worker             ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
2693*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2694*e5436536SAndroid Build Coastguard Worker             break;
2695*e5436536SAndroid Build Coastguard Worker           }
2696*e5436536SAndroid Build Coastguard Worker         }
2697*e5436536SAndroid Build Coastguard Worker 
2698*e5436536SAndroid Build Coastguard Worker         if (!(self->flags[streamIndex] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) {
2699*e5436536SAndroid Build Coastguard Worker           int ch;
2700*e5436536SAndroid Build Coastguard Worker           for (ch = 0; ch < el_channels; ch += 1) {
2701*e5436536SAndroid Build Coastguard Worker             CPns_ResetData(&self->pAacDecoderChannelInfo[aacChannels + ch]
2702*e5436536SAndroid Build Coastguard Worker                                 ->data.aac.PnsData,
2703*e5436536SAndroid Build Coastguard Worker                            &self->pAacDecoderChannelInfo[aacChannels + ch]
2704*e5436536SAndroid Build Coastguard Worker                                 ->pComData->pnsInterChannelData);
2705*e5436536SAndroid Build Coastguard Worker           }
2706*e5436536SAndroid Build Coastguard Worker         }
2707*e5436536SAndroid Build Coastguard Worker 
2708*e5436536SAndroid Build Coastguard Worker         if (self->frameOK) {
2709*e5436536SAndroid Build Coastguard Worker           ErrorStatus = CChannelElement_Read(
2710*e5436536SAndroid Build Coastguard Worker               bs, &self->pAacDecoderChannelInfo[aacChannels],
2711*e5436536SAndroid Build Coastguard Worker               &self->pAacDecoderStaticChannelInfo[aacChannels],
2712*e5436536SAndroid Build Coastguard Worker               self->streamInfo.aot, &self->samplingRateInfo[streamIndex],
2713*e5436536SAndroid Build Coastguard Worker               self->flags[streamIndex], self->elFlags[element_count],
2714*e5436536SAndroid Build Coastguard Worker               self->streamInfo.aacSamplesPerFrame, el_channels,
2715*e5436536SAndroid Build Coastguard Worker               self->streamInfo.epConfig, self->hInput);
2716*e5436536SAndroid Build Coastguard Worker           if (ErrorStatus != AAC_DEC_OK) {
2717*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2718*e5436536SAndroid Build Coastguard Worker           }
2719*e5436536SAndroid Build Coastguard Worker         }
2720*e5436536SAndroid Build Coastguard Worker 
2721*e5436536SAndroid Build Coastguard Worker         if (self->frameOK) {
2722*e5436536SAndroid Build Coastguard Worker           /* Lookup the element and decode it only if it belongs to the current
2723*e5436536SAndroid Build Coastguard Worker            * program */
2724*e5436536SAndroid Build Coastguard Worker           if (CProgramConfig_LookupElement(
2725*e5436536SAndroid Build Coastguard Worker                   pce, self->streamInfo.channelConfig,
2726*e5436536SAndroid Build Coastguard Worker                   self->pAacDecoderChannelInfo[aacChannels]->ElementInstanceTag,
2727*e5436536SAndroid Build Coastguard Worker                   aacChannels, self->chMapping, self->channelType,
2728*e5436536SAndroid Build Coastguard Worker                   self->channelIndices, (8), &previous_element_index,
2729*e5436536SAndroid Build Coastguard Worker                   self->elements, type)) {
2730*e5436536SAndroid Build Coastguard Worker             channel_elements[channel_element_count++] = type;
2731*e5436536SAndroid Build Coastguard Worker             aacChannels += el_channels;
2732*e5436536SAndroid Build Coastguard Worker           } else {
2733*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2734*e5436536SAndroid Build Coastguard Worker           }
2735*e5436536SAndroid Build Coastguard Worker           /* Create SBR element for SBR for upsampling for LFE elements,
2736*e5436536SAndroid Build Coastguard Worker              and if SBR was implicitly signaled, because the first frame(s)
2737*e5436536SAndroid Build Coastguard Worker              may not contain SBR payload (broken encoder, bit errors). */
2738*e5436536SAndroid Build Coastguard Worker           if (self->frameOK &&
2739*e5436536SAndroid Build Coastguard Worker               ((self->flags[streamIndex] & AC_SBR_PRESENT) ||
2740*e5436536SAndroid Build Coastguard Worker                (self->sbrEnabled == 1)) &&
2741*e5436536SAndroid Build Coastguard Worker               !(self->flags[streamIndex] &
2742*e5436536SAndroid Build Coastguard Worker                 AC_USAC) /* Is done during explicit config set up */
2743*e5436536SAndroid Build Coastguard Worker           ) {
2744*e5436536SAndroid Build Coastguard Worker             SBR_ERROR sbrError;
2745*e5436536SAndroid Build Coastguard Worker             UCHAR configMode = 0;
2746*e5436536SAndroid Build Coastguard Worker             UCHAR configChanged = 0;
2747*e5436536SAndroid Build Coastguard Worker             configMode |= AC_CM_ALLOC_MEM;
2748*e5436536SAndroid Build Coastguard Worker 
2749*e5436536SAndroid Build Coastguard Worker             sbrError = sbrDecoder_InitElement(
2750*e5436536SAndroid Build Coastguard Worker                 self->hSbrDecoder, self->streamInfo.aacSampleRate,
2751*e5436536SAndroid Build Coastguard Worker                 self->streamInfo.extSamplingRate,
2752*e5436536SAndroid Build Coastguard Worker                 self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot, type,
2753*e5436536SAndroid Build Coastguard Worker                 previous_element_index, 2, /* Signalize that harmonicSBR shall
2754*e5436536SAndroid Build Coastguard Worker                                               be ignored in the config change
2755*e5436536SAndroid Build Coastguard Worker                                               detection */
2756*e5436536SAndroid Build Coastguard Worker                 0, configMode, &configChanged, self->downscaleFactor);
2757*e5436536SAndroid Build Coastguard Worker             if (sbrError != SBRDEC_OK) {
2758*e5436536SAndroid Build Coastguard Worker               /* Do not try to apply SBR because initializing the element
2759*e5436536SAndroid Build Coastguard Worker                * failed. */
2760*e5436536SAndroid Build Coastguard Worker               self->sbrEnabled = 0;
2761*e5436536SAndroid Build Coastguard Worker             }
2762*e5436536SAndroid Build Coastguard Worker           }
2763*e5436536SAndroid Build Coastguard Worker         }
2764*e5436536SAndroid Build Coastguard Worker 
2765*e5436536SAndroid Build Coastguard Worker         el_cnt[type]++;
2766*e5436536SAndroid Build Coastguard Worker         if (self->frameOK && (self->flags[streamIndex] & AC_USAC) &&
2767*e5436536SAndroid Build Coastguard Worker             (type == ID_USAC_CPE || type == ID_USAC_SCE)) {
2768*e5436536SAndroid Build Coastguard Worker           ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr(
2769*e5436536SAndroid Build Coastguard Worker               self, bs, previous_element, previous_element_index, element_count,
2770*e5436536SAndroid Build Coastguard Worker               el_cnt);
2771*e5436536SAndroid Build Coastguard Worker           if (ErrorStatus != AAC_DEC_OK) {
2772*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2773*e5436536SAndroid Build Coastguard Worker           }
2774*e5436536SAndroid Build Coastguard Worker         }
2775*e5436536SAndroid Build Coastguard Worker         break;
2776*e5436536SAndroid Build Coastguard Worker 
2777*e5436536SAndroid Build Coastguard Worker       case ID_CCE:
2778*e5436536SAndroid Build Coastguard Worker         /*
2779*e5436536SAndroid Build Coastguard Worker           Consistency check
2780*e5436536SAndroid Build Coastguard Worker         */
2781*e5436536SAndroid Build Coastguard Worker         if (el_cnt[type] > self->ascChannels[streamIndex]) {
2782*e5436536SAndroid Build Coastguard Worker           ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
2783*e5436536SAndroid Build Coastguard Worker           self->frameOK = 0;
2784*e5436536SAndroid Build Coastguard Worker           break;
2785*e5436536SAndroid Build Coastguard Worker         }
2786*e5436536SAndroid Build Coastguard Worker 
2787*e5436536SAndroid Build Coastguard Worker         if (self->frameOK) {
2788*e5436536SAndroid Build Coastguard Worker           CAacDecoderCommonData commonData;
2789*e5436536SAndroid Build Coastguard Worker           CAacDecoderCommonStaticData commonStaticData;
2790*e5436536SAndroid Build Coastguard Worker           CWorkBufferCore1 workBufferCore1;
2791*e5436536SAndroid Build Coastguard Worker           commonStaticData.pWorkBufferCore1 = &workBufferCore1;
2792*e5436536SAndroid Build Coastguard Worker           /* memory for spectral lines temporal on scratch */
2793*e5436536SAndroid Build Coastguard Worker           C_AALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024);
2794*e5436536SAndroid Build Coastguard Worker 
2795*e5436536SAndroid Build Coastguard Worker           /* create dummy channel for CCE parsing on stack */
2796*e5436536SAndroid Build Coastguard Worker           CAacDecoderChannelInfo tmpAacDecoderChannelInfo,
2797*e5436536SAndroid Build Coastguard Worker               *pTmpAacDecoderChannelInfo;
2798*e5436536SAndroid Build Coastguard Worker 
2799*e5436536SAndroid Build Coastguard Worker           FDKmemclear(mdctSpec, 1024 * sizeof(FIXP_DBL));
2800*e5436536SAndroid Build Coastguard Worker 
2801*e5436536SAndroid Build Coastguard Worker           tmpAacDecoderChannelInfo.pDynData = commonData.pAacDecoderDynamicData;
2802*e5436536SAndroid Build Coastguard Worker           tmpAacDecoderChannelInfo.pComData = &commonData;
2803*e5436536SAndroid Build Coastguard Worker           tmpAacDecoderChannelInfo.pComStaticData = &commonStaticData;
2804*e5436536SAndroid Build Coastguard Worker           tmpAacDecoderChannelInfo.pSpectralCoefficient =
2805*e5436536SAndroid Build Coastguard Worker               (SPECTRAL_PTR)mdctSpec;
2806*e5436536SAndroid Build Coastguard Worker           /* Assume AAC-LC */
2807*e5436536SAndroid Build Coastguard Worker           tmpAacDecoderChannelInfo.granuleLength =
2808*e5436536SAndroid Build Coastguard Worker               self->streamInfo.aacSamplesPerFrame / 8;
2809*e5436536SAndroid Build Coastguard Worker           /* Reset PNS data. */
2810*e5436536SAndroid Build Coastguard Worker           CPns_ResetData(
2811*e5436536SAndroid Build Coastguard Worker               &tmpAacDecoderChannelInfo.data.aac.PnsData,
2812*e5436536SAndroid Build Coastguard Worker               &tmpAacDecoderChannelInfo.pComData->pnsInterChannelData);
2813*e5436536SAndroid Build Coastguard Worker           pTmpAacDecoderChannelInfo = &tmpAacDecoderChannelInfo;
2814*e5436536SAndroid Build Coastguard Worker           /* do CCE parsing */
2815*e5436536SAndroid Build Coastguard Worker           ErrorStatus = CChannelElement_Read(
2816*e5436536SAndroid Build Coastguard Worker               bs, &pTmpAacDecoderChannelInfo, NULL, self->streamInfo.aot,
2817*e5436536SAndroid Build Coastguard Worker               &self->samplingRateInfo[streamIndex], self->flags[streamIndex],
2818*e5436536SAndroid Build Coastguard Worker               AC_EL_GA_CCE, self->streamInfo.aacSamplesPerFrame, 1,
2819*e5436536SAndroid Build Coastguard Worker               self->streamInfo.epConfig, self->hInput);
2820*e5436536SAndroid Build Coastguard Worker 
2821*e5436536SAndroid Build Coastguard Worker           C_AALLOC_SCRATCH_END(mdctSpec, FIXP_DBL, 1024);
2822*e5436536SAndroid Build Coastguard Worker 
2823*e5436536SAndroid Build Coastguard Worker           if (ErrorStatus) {
2824*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2825*e5436536SAndroid Build Coastguard Worker           }
2826*e5436536SAndroid Build Coastguard Worker 
2827*e5436536SAndroid Build Coastguard Worker           if (self->frameOK) {
2828*e5436536SAndroid Build Coastguard Worker             /* Lookup the element and decode it only if it belongs to the
2829*e5436536SAndroid Build Coastguard Worker              * current program */
2830*e5436536SAndroid Build Coastguard Worker             if (CProgramConfig_LookupElement(
2831*e5436536SAndroid Build Coastguard Worker                     pce, self->streamInfo.channelConfig,
2832*e5436536SAndroid Build Coastguard Worker                     pTmpAacDecoderChannelInfo->ElementInstanceTag, 0,
2833*e5436536SAndroid Build Coastguard Worker                     self->chMapping, self->channelType, self->channelIndices,
2834*e5436536SAndroid Build Coastguard Worker                     (8), &previous_element_index, self->elements, type)) {
2835*e5436536SAndroid Build Coastguard Worker               /* decoding of CCE not supported */
2836*e5436536SAndroid Build Coastguard Worker             } else {
2837*e5436536SAndroid Build Coastguard Worker               self->frameOK = 0;
2838*e5436536SAndroid Build Coastguard Worker             }
2839*e5436536SAndroid Build Coastguard Worker           }
2840*e5436536SAndroid Build Coastguard Worker         }
2841*e5436536SAndroid Build Coastguard Worker         el_cnt[type]++;
2842*e5436536SAndroid Build Coastguard Worker         break;
2843*e5436536SAndroid Build Coastguard Worker 
2844*e5436536SAndroid Build Coastguard Worker       case ID_DSE: {
2845*e5436536SAndroid Build Coastguard Worker         UCHAR element_instance_tag;
2846*e5436536SAndroid Build Coastguard Worker 
2847*e5436536SAndroid Build Coastguard Worker         CDataStreamElement_Read(self, bs, &element_instance_tag, auStartAnchor);
2848*e5436536SAndroid Build Coastguard Worker 
2849*e5436536SAndroid Build Coastguard Worker         if (!CProgramConfig_LookupElement(
2850*e5436536SAndroid Build Coastguard Worker                 pce, self->streamInfo.channelConfig, element_instance_tag, 0,
2851*e5436536SAndroid Build Coastguard Worker                 self->chMapping, self->channelType, self->channelIndices, (8),
2852*e5436536SAndroid Build Coastguard Worker                 &previous_element_index, self->elements, type)) {
2853*e5436536SAndroid Build Coastguard Worker           /* most likely an error in bitstream occured */
2854*e5436536SAndroid Build Coastguard Worker           // self->frameOK = 0;
2855*e5436536SAndroid Build Coastguard Worker         }
2856*e5436536SAndroid Build Coastguard Worker       } break;
2857*e5436536SAndroid Build Coastguard Worker 
2858*e5436536SAndroid Build Coastguard Worker       case ID_PCE: {
2859*e5436536SAndroid Build Coastguard Worker         int result = CProgramConfigElement_Read(bs, self->hInput, pce,
2860*e5436536SAndroid Build Coastguard Worker                                                 self->streamInfo.channelConfig,
2861*e5436536SAndroid Build Coastguard Worker                                                 auStartAnchor);
2862*e5436536SAndroid Build Coastguard Worker         if (result < 0) {
2863*e5436536SAndroid Build Coastguard Worker           /* Something went wrong */
2864*e5436536SAndroid Build Coastguard Worker           ErrorStatus = AAC_DEC_PARSE_ERROR;
2865*e5436536SAndroid Build Coastguard Worker           self->frameOK = 0;
2866*e5436536SAndroid Build Coastguard Worker         } else if (result > 1) {
2867*e5436536SAndroid Build Coastguard Worker           /* Built element table */
2868*e5436536SAndroid Build Coastguard Worker           int elIdx = CProgramConfig_GetElementTable(
2869*e5436536SAndroid Build Coastguard Worker               pce, self->elements, (((8)) + (8)), &self->chMapIndex);
2870*e5436536SAndroid Build Coastguard Worker           /* Reset the remaining tabs */
2871*e5436536SAndroid Build Coastguard Worker           for (; elIdx < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1);
2872*e5436536SAndroid Build Coastguard Worker                elIdx++) {
2873*e5436536SAndroid Build Coastguard Worker             self->elements[elIdx] = ID_NONE;
2874*e5436536SAndroid Build Coastguard Worker           }
2875*e5436536SAndroid Build Coastguard Worker           /* Make new number of channel persistent */
2876*e5436536SAndroid Build Coastguard Worker           self->ascChannels[streamIndex] = pce->NumChannels;
2877*e5436536SAndroid Build Coastguard Worker           /* If PCE is not first element conceal this frame to avoid
2878*e5436536SAndroid Build Coastguard Worker            * inconsistencies */
2879*e5436536SAndroid Build Coastguard Worker           if (element_count != 0) {
2880*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2881*e5436536SAndroid Build Coastguard Worker           }
2882*e5436536SAndroid Build Coastguard Worker         }
2883*e5436536SAndroid Build Coastguard Worker         pceRead = (result >= 0) ? 1 : 0;
2884*e5436536SAndroid Build Coastguard Worker       } break;
2885*e5436536SAndroid Build Coastguard Worker 
2886*e5436536SAndroid Build Coastguard Worker       case ID_FIL: {
2887*e5436536SAndroid Build Coastguard Worker         int bitCnt = FDKreadBits(bs, 4); /* bs_count */
2888*e5436536SAndroid Build Coastguard Worker 
2889*e5436536SAndroid Build Coastguard Worker         if (bitCnt == 15) {
2890*e5436536SAndroid Build Coastguard Worker           int esc_count = FDKreadBits(bs, 8); /* bs_esc_count */
2891*e5436536SAndroid Build Coastguard Worker           bitCnt = esc_count + 14;
2892*e5436536SAndroid Build Coastguard Worker         }
2893*e5436536SAndroid Build Coastguard Worker 
2894*e5436536SAndroid Build Coastguard Worker         /* Convert to bits */
2895*e5436536SAndroid Build Coastguard Worker         bitCnt <<= 3;
2896*e5436536SAndroid Build Coastguard Worker 
2897*e5436536SAndroid Build Coastguard Worker         while (bitCnt > 0) {
2898*e5436536SAndroid Build Coastguard Worker           ErrorStatus = CAacDecoder_ExtPayloadParse(
2899*e5436536SAndroid Build Coastguard Worker               self, bs, &bitCnt, previous_element, previous_element_index, 1);
2900*e5436536SAndroid Build Coastguard Worker           if (ErrorStatus != AAC_DEC_OK) {
2901*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
2902*e5436536SAndroid Build Coastguard Worker             break;
2903*e5436536SAndroid Build Coastguard Worker           }
2904*e5436536SAndroid Build Coastguard Worker         }
2905*e5436536SAndroid Build Coastguard Worker       } break;
2906*e5436536SAndroid Build Coastguard Worker 
2907*e5436536SAndroid Build Coastguard Worker       case ID_EXT:
2908*e5436536SAndroid Build Coastguard Worker         if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
2909*e5436536SAndroid Build Coastguard Worker           self->frameOK = 0;
2910*e5436536SAndroid Build Coastguard Worker           ErrorStatus = AAC_DEC_PARSE_ERROR;
2911*e5436536SAndroid Build Coastguard Worker           break;
2912*e5436536SAndroid Build Coastguard Worker         }
2913*e5436536SAndroid Build Coastguard Worker 
2914*e5436536SAndroid Build Coastguard Worker         ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr(
2915*e5436536SAndroid Build Coastguard Worker             self, bs, previous_element, previous_element_index, element_count,
2916*e5436536SAndroid Build Coastguard Worker             el_cnt);
2917*e5436536SAndroid Build Coastguard Worker         break;
2918*e5436536SAndroid Build Coastguard Worker 
2919*e5436536SAndroid Build Coastguard Worker       case ID_USAC_EXT: {
2920*e5436536SAndroid Build Coastguard Worker         if ((element_count - element_count_prev_streams) >=
2921*e5436536SAndroid Build Coastguard Worker             TP_USAC_MAX_ELEMENTS) {
2922*e5436536SAndroid Build Coastguard Worker           self->frameOK = 0;
2923*e5436536SAndroid Build Coastguard Worker           ErrorStatus = AAC_DEC_PARSE_ERROR;
2924*e5436536SAndroid Build Coastguard Worker           break;
2925*e5436536SAndroid Build Coastguard Worker         }
2926*e5436536SAndroid Build Coastguard Worker         /* parse extension element payload
2927*e5436536SAndroid Build Coastguard Worker            q.v. rsv603daExtElement() ISO/IEC DIS 23008-3  Table 30
2928*e5436536SAndroid Build Coastguard Worker            or   UsacExElement() ISO/IEC FDIS 23003-3:2011(E)  Table 21
2929*e5436536SAndroid Build Coastguard Worker          */
2930*e5436536SAndroid Build Coastguard Worker         int usacExtElementPayloadLength;
2931*e5436536SAndroid Build Coastguard Worker         /* int usacExtElementStart, usacExtElementStop; */
2932*e5436536SAndroid Build Coastguard Worker 
2933*e5436536SAndroid Build Coastguard Worker         if (FDKreadBit(bs)) {   /* usacExtElementPresent */
2934*e5436536SAndroid Build Coastguard Worker           if (FDKreadBit(bs)) { /* usacExtElementUseDefaultLength */
2935*e5436536SAndroid Build Coastguard Worker             usacExtElementPayloadLength =
2936*e5436536SAndroid Build Coastguard Worker                 self->pUsacConfig[streamIndex]
2937*e5436536SAndroid Build Coastguard Worker                     ->element[element_count - element_count_prev_streams]
2938*e5436536SAndroid Build Coastguard Worker                     .extElement.usacExtElementDefaultLength;
2939*e5436536SAndroid Build Coastguard Worker           } else {
2940*e5436536SAndroid Build Coastguard Worker             usacExtElementPayloadLength = FDKreadBits(bs, 8);
2941*e5436536SAndroid Build Coastguard Worker             if (usacExtElementPayloadLength == (UINT)(1 << 8) - 1) {
2942*e5436536SAndroid Build Coastguard Worker               UINT valueAdd = FDKreadBits(bs, 16);
2943*e5436536SAndroid Build Coastguard Worker               usacExtElementPayloadLength += (INT)valueAdd - 2;
2944*e5436536SAndroid Build Coastguard Worker             }
2945*e5436536SAndroid Build Coastguard Worker           }
2946*e5436536SAndroid Build Coastguard Worker           if (usacExtElementPayloadLength > 0) {
2947*e5436536SAndroid Build Coastguard Worker             int usacExtBitPos;
2948*e5436536SAndroid Build Coastguard Worker 
2949*e5436536SAndroid Build Coastguard Worker             if (self->pUsacConfig[streamIndex]
2950*e5436536SAndroid Build Coastguard Worker                     ->element[element_count - element_count_prev_streams]
2951*e5436536SAndroid Build Coastguard Worker                     .extElement.usacExtElementPayloadFrag) {
2952*e5436536SAndroid Build Coastguard Worker               /* usacExtElementStart = */ FDKreadBit(bs);
2953*e5436536SAndroid Build Coastguard Worker               /* usacExtElementStop = */ FDKreadBit(bs);
2954*e5436536SAndroid Build Coastguard Worker             } else {
2955*e5436536SAndroid Build Coastguard Worker               /* usacExtElementStart = 1; */
2956*e5436536SAndroid Build Coastguard Worker               /* usacExtElementStop = 1; */
2957*e5436536SAndroid Build Coastguard Worker             }
2958*e5436536SAndroid Build Coastguard Worker 
2959*e5436536SAndroid Build Coastguard Worker             usacExtBitPos = (INT)FDKgetValidBits(bs);
2960*e5436536SAndroid Build Coastguard Worker 
2961*e5436536SAndroid Build Coastguard Worker             USAC_EXT_ELEMENT_TYPE usacExtElementType =
2962*e5436536SAndroid Build Coastguard Worker                 self->pUsacConfig[streamIndex]
2963*e5436536SAndroid Build Coastguard Worker                     ->element[element_count - element_count_prev_streams]
2964*e5436536SAndroid Build Coastguard Worker                     .extElement.usacExtElementType;
2965*e5436536SAndroid Build Coastguard Worker 
2966*e5436536SAndroid Build Coastguard Worker             switch (usacExtElementType) {
2967*e5436536SAndroid Build Coastguard Worker               case ID_EXT_ELE_UNI_DRC: /* uniDrcGain() */
2968*e5436536SAndroid Build Coastguard Worker                 if (streamIndex == 0) {
2969*e5436536SAndroid Build Coastguard Worker                   int drcErr;
2970*e5436536SAndroid Build Coastguard Worker 
2971*e5436536SAndroid Build Coastguard Worker                   drcErr = FDK_drcDec_ReadUniDrcGain(self->hUniDrcDecoder, bs);
2972*e5436536SAndroid Build Coastguard Worker                   if (drcErr != 0) {
2973*e5436536SAndroid Build Coastguard Worker                     ErrorStatus = AAC_DEC_PARSE_ERROR;
2974*e5436536SAndroid Build Coastguard Worker                   }
2975*e5436536SAndroid Build Coastguard Worker                 }
2976*e5436536SAndroid Build Coastguard Worker                 break;
2977*e5436536SAndroid Build Coastguard Worker 
2978*e5436536SAndroid Build Coastguard Worker               default:
2979*e5436536SAndroid Build Coastguard Worker                 break;
2980*e5436536SAndroid Build Coastguard Worker             }
2981*e5436536SAndroid Build Coastguard Worker 
2982*e5436536SAndroid Build Coastguard Worker             /* Skip any remaining bits of extension payload */
2983*e5436536SAndroid Build Coastguard Worker             usacExtBitPos = (usacExtElementPayloadLength * 8) -
2984*e5436536SAndroid Build Coastguard Worker                             (usacExtBitPos - (INT)FDKgetValidBits(bs));
2985*e5436536SAndroid Build Coastguard Worker             if (usacExtBitPos < 0) {
2986*e5436536SAndroid Build Coastguard Worker               self->frameOK = 0;
2987*e5436536SAndroid Build Coastguard Worker               ErrorStatus = AAC_DEC_PARSE_ERROR;
2988*e5436536SAndroid Build Coastguard Worker             }
2989*e5436536SAndroid Build Coastguard Worker             FDKpushBiDirectional(bs, usacExtBitPos);
2990*e5436536SAndroid Build Coastguard Worker           }
2991*e5436536SAndroid Build Coastguard Worker         }
2992*e5436536SAndroid Build Coastguard Worker       } break;
2993*e5436536SAndroid Build Coastguard Worker       case ID_END:
2994*e5436536SAndroid Build Coastguard Worker       case ID_USAC_END:
2995*e5436536SAndroid Build Coastguard Worker         break;
2996*e5436536SAndroid Build Coastguard Worker 
2997*e5436536SAndroid Build Coastguard Worker       default:
2998*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
2999*e5436536SAndroid Build Coastguard Worker         self->frameOK = 0;
3000*e5436536SAndroid Build Coastguard Worker         break;
3001*e5436536SAndroid Build Coastguard Worker     }
3002*e5436536SAndroid Build Coastguard Worker 
3003*e5436536SAndroid Build Coastguard Worker     previous_element = type;
3004*e5436536SAndroid Build Coastguard Worker     element_count++;
3005*e5436536SAndroid Build Coastguard Worker 
3006*e5436536SAndroid Build Coastguard Worker   } /* while ( (type != ID_END) ... ) */
3007*e5436536SAndroid Build Coastguard Worker 
3008*e5436536SAndroid Build Coastguard Worker   if (!(self->flags[streamIndex] &
3009*e5436536SAndroid Build Coastguard Worker         (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_BSAC | AC_LD | AC_ELD | AC_ER |
3010*e5436536SAndroid Build Coastguard Worker          AC_SCALABLE)) &&
3011*e5436536SAndroid Build Coastguard Worker       (self->streamInfo.channelConfig == 0) && pce->isValid &&
3012*e5436536SAndroid Build Coastguard Worker       (ErrorStatus == AAC_DEC_OK) && self->frameOK &&
3013*e5436536SAndroid Build Coastguard Worker       !(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
3014*e5436536SAndroid Build Coastguard Worker     /* Check whether all PCE listed element instance tags are present in
3015*e5436536SAndroid Build Coastguard Worker      * raw_data_block() */
3016*e5436536SAndroid Build Coastguard Worker     if (!validateElementInstanceTags(
3017*e5436536SAndroid Build Coastguard Worker             &self->pce, self->pAacDecoderChannelInfo, aacChannels,
3018*e5436536SAndroid Build Coastguard Worker             channel_elements,
3019*e5436536SAndroid Build Coastguard Worker             fMin(channel_element_count, (int)(sizeof(channel_elements) /
3020*e5436536SAndroid Build Coastguard Worker                                               sizeof(*channel_elements))))) {
3021*e5436536SAndroid Build Coastguard Worker       ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
3022*e5436536SAndroid Build Coastguard Worker       self->frameOK = 0;
3023*e5436536SAndroid Build Coastguard Worker     }
3024*e5436536SAndroid Build Coastguard Worker   }
3025*e5436536SAndroid Build Coastguard Worker 
3026*e5436536SAndroid Build Coastguard Worker   if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
3027*e5436536SAndroid Build Coastguard Worker     /* float decoder checks if bitsLeft is in range 0-7; only prerollAUs are
3028*e5436536SAndroid Build Coastguard Worker      * byteAligned with respect to the first bit */
3029*e5436536SAndroid Build Coastguard Worker     /* Byte alignment with respect to the first bit of the raw_data_block(). */
3030*e5436536SAndroid Build Coastguard Worker     if (!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) ||
3031*e5436536SAndroid Build Coastguard Worker         (self->prerollAULength[self->accessUnit]) /* indicates preroll */
3032*e5436536SAndroid Build Coastguard Worker     ) {
3033*e5436536SAndroid Build Coastguard Worker       FDKbyteAlign(bs, auStartAnchor);
3034*e5436536SAndroid Build Coastguard Worker     }
3035*e5436536SAndroid Build Coastguard Worker 
3036*e5436536SAndroid Build Coastguard Worker     /* Check if all bits of the raw_data_block() have been read. */
3037*e5436536SAndroid Build Coastguard Worker     if (transportDec_GetAuBitsTotal(self->hInput, 0) > 0) {
3038*e5436536SAndroid Build Coastguard Worker       INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0);
3039*e5436536SAndroid Build Coastguard Worker       /* for pre-roll frames pre-roll length has to be used instead of total AU
3040*e5436536SAndroid Build Coastguard Worker        * lenght */
3041*e5436536SAndroid Build Coastguard Worker       /* unreadBits regarding preroll bounds */
3042*e5436536SAndroid Build Coastguard Worker       if (self->prerollAULength[self->accessUnit]) {
3043*e5436536SAndroid Build Coastguard Worker         unreadBits = unreadBits - transportDec_GetAuBitsTotal(self->hInput, 0) +
3044*e5436536SAndroid Build Coastguard Worker                      (INT)self->prerollAULength[self->accessUnit];
3045*e5436536SAndroid Build Coastguard Worker       }
3046*e5436536SAndroid Build Coastguard Worker       if (((self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) &&
3047*e5436536SAndroid Build Coastguard Worker            ((unreadBits < 0) || (unreadBits > 7)) &&
3048*e5436536SAndroid Build Coastguard Worker            !(self->prerollAULength[self->accessUnit])) ||
3049*e5436536SAndroid Build Coastguard Worker           ((!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) ||
3050*e5436536SAndroid Build Coastguard Worker             (self->prerollAULength[self->accessUnit])) &&
3051*e5436536SAndroid Build Coastguard Worker            (unreadBits != 0))) {
3052*e5436536SAndroid Build Coastguard Worker         if ((((unreadBits < 0) || (unreadBits > 7)) && self->frameOK) &&
3053*e5436536SAndroid Build Coastguard Worker             ((transportDec_GetFormat(self->hInput) == TT_DRM) &&
3054*e5436536SAndroid Build Coastguard Worker              (self->flags[streamIndex] & AC_USAC))) {
3055*e5436536SAndroid Build Coastguard Worker           /* Set frame OK because of fill bits. */
3056*e5436536SAndroid Build Coastguard Worker           self->frameOK = 1;
3057*e5436536SAndroid Build Coastguard Worker         } else {
3058*e5436536SAndroid Build Coastguard Worker           self->frameOK = 0;
3059*e5436536SAndroid Build Coastguard Worker         }
3060*e5436536SAndroid Build Coastguard Worker 
3061*e5436536SAndroid Build Coastguard Worker         /* Do not overwrite current error */
3062*e5436536SAndroid Build Coastguard Worker         if (ErrorStatus == AAC_DEC_OK && self->frameOK == 0) {
3063*e5436536SAndroid Build Coastguard Worker           ErrorStatus = AAC_DEC_PARSE_ERROR;
3064*e5436536SAndroid Build Coastguard Worker         }
3065*e5436536SAndroid Build Coastguard Worker         /* Always put the bitbuffer at the right position after the current
3066*e5436536SAndroid Build Coastguard Worker          * Access Unit. */
3067*e5436536SAndroid Build Coastguard Worker         FDKpushBiDirectional(bs, unreadBits);
3068*e5436536SAndroid Build Coastguard Worker       }
3069*e5436536SAndroid Build Coastguard Worker     }
3070*e5436536SAndroid Build Coastguard Worker 
3071*e5436536SAndroid Build Coastguard Worker     /* Check the last element. The terminator (ID_END) has to be the last one
3072*e5436536SAndroid Build Coastguard Worker      * (even if ER syntax is used). */
3073*e5436536SAndroid Build Coastguard Worker     if (self->frameOK && type != ID_END) {
3074*e5436536SAndroid Build Coastguard Worker       /* Do not overwrite current error */
3075*e5436536SAndroid Build Coastguard Worker       if (ErrorStatus == AAC_DEC_OK) {
3076*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_PARSE_ERROR;
3077*e5436536SAndroid Build Coastguard Worker       }
3078*e5436536SAndroid Build Coastguard Worker       self->frameOK = 0;
3079*e5436536SAndroid Build Coastguard Worker     }
3080*e5436536SAndroid Build Coastguard Worker   }
3081*e5436536SAndroid Build Coastguard Worker 
3082*e5436536SAndroid Build Coastguard Worker   if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) {
3083*e5436536SAndroid Build Coastguard Worker     channel_elements[channel_element_count++] = ID_END;
3084*e5436536SAndroid Build Coastguard Worker   }
3085*e5436536SAndroid Build Coastguard Worker   element_count = 0;
3086*e5436536SAndroid Build Coastguard Worker   aacChannels = 0;
3087*e5436536SAndroid Build Coastguard Worker   type = ID_NONE;
3088*e5436536SAndroid Build Coastguard Worker   previous_element_index = 0;
3089*e5436536SAndroid Build Coastguard Worker 
3090*e5436536SAndroid Build Coastguard Worker   while (type != ID_END &&
3091*e5436536SAndroid Build Coastguard Worker          element_count < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) {
3092*e5436536SAndroid Build Coastguard Worker     int el_channels;
3093*e5436536SAndroid Build Coastguard Worker 
3094*e5436536SAndroid Build Coastguard Worker     if ((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || !self->frameOK) {
3095*e5436536SAndroid Build Coastguard Worker       channel_elements[element_count] = self->elements[element_count];
3096*e5436536SAndroid Build Coastguard Worker       if (channel_elements[element_count] == ID_NONE) {
3097*e5436536SAndroid Build Coastguard Worker         channel_elements[element_count] = ID_END;
3098*e5436536SAndroid Build Coastguard Worker       }
3099*e5436536SAndroid Build Coastguard Worker     }
3100*e5436536SAndroid Build Coastguard Worker 
3101*e5436536SAndroid Build Coastguard Worker     if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) {
3102*e5436536SAndroid Build Coastguard Worker       type = self->elements[element_count];
3103*e5436536SAndroid Build Coastguard Worker     } else {
3104*e5436536SAndroid Build Coastguard Worker       type = channel_elements[element_count];
3105*e5436536SAndroid Build Coastguard Worker     }
3106*e5436536SAndroid Build Coastguard Worker 
3107*e5436536SAndroid Build Coastguard Worker     if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) {
3108*e5436536SAndroid Build Coastguard Worker       switch (type) {
3109*e5436536SAndroid Build Coastguard Worker         case ID_SCE:
3110*e5436536SAndroid Build Coastguard Worker         case ID_CPE:
3111*e5436536SAndroid Build Coastguard Worker         case ID_LFE:
3112*e5436536SAndroid Build Coastguard Worker         case ID_USAC_SCE:
3113*e5436536SAndroid Build Coastguard Worker         case ID_USAC_CPE:
3114*e5436536SAndroid Build Coastguard Worker         case ID_USAC_LFE:
3115*e5436536SAndroid Build Coastguard Worker 
3116*e5436536SAndroid Build Coastguard Worker           el_channels = CAacDecoder_GetELChannels(
3117*e5436536SAndroid Build Coastguard Worker               type, self->usacStereoConfigIndex[element_count]);
3118*e5436536SAndroid Build Coastguard Worker 
3119*e5436536SAndroid Build Coastguard Worker           if (!hdaacDecoded) {
3120*e5436536SAndroid Build Coastguard Worker             if (self->pAacDecoderStaticChannelInfo[aacChannels]
3121*e5436536SAndroid Build Coastguard Worker                     ->pCpeStaticData != NULL) {
3122*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderStaticChannelInfo[aacChannels]
3123*e5436536SAndroid Build Coastguard Worker                   ->pCpeStaticData->jointStereoPersistentData.scratchBuffer =
3124*e5436536SAndroid Build Coastguard Worker                   (FIXP_DBL *)pTimeData;
3125*e5436536SAndroid Build Coastguard Worker             }
3126*e5436536SAndroid Build Coastguard Worker             CChannelElement_Decode(
3127*e5436536SAndroid Build Coastguard Worker                 &self->pAacDecoderChannelInfo[aacChannels],
3128*e5436536SAndroid Build Coastguard Worker                 &self->pAacDecoderStaticChannelInfo[aacChannels],
3129*e5436536SAndroid Build Coastguard Worker                 &self->samplingRateInfo[streamIndex], self->flags[streamIndex],
3130*e5436536SAndroid Build Coastguard Worker                 self->elFlags[element_count], el_channels);
3131*e5436536SAndroid Build Coastguard Worker           }
3132*e5436536SAndroid Build Coastguard Worker           aacChannels += el_channels;
3133*e5436536SAndroid Build Coastguard Worker           break;
3134*e5436536SAndroid Build Coastguard Worker         case ID_NONE:
3135*e5436536SAndroid Build Coastguard Worker           type = ID_END;
3136*e5436536SAndroid Build Coastguard Worker           break;
3137*e5436536SAndroid Build Coastguard Worker         default:
3138*e5436536SAndroid Build Coastguard Worker           break;
3139*e5436536SAndroid Build Coastguard Worker       }
3140*e5436536SAndroid Build Coastguard Worker     }
3141*e5436536SAndroid Build Coastguard Worker     element_count++;
3142*e5436536SAndroid Build Coastguard Worker   }
3143*e5436536SAndroid Build Coastguard Worker 
3144*e5436536SAndroid Build Coastguard Worker   /* More AAC channels than specified by the ASC not allowed. */
3145*e5436536SAndroid Build Coastguard Worker   if ((aacChannels == 0 || aacChannels > self->aacChannels) &&
3146*e5436536SAndroid Build Coastguard Worker       !(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
3147*e5436536SAndroid Build Coastguard Worker     /* Do not overwrite current error */
3148*e5436536SAndroid Build Coastguard Worker     if (ErrorStatus == AAC_DEC_OK) {
3149*e5436536SAndroid Build Coastguard Worker       ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
3150*e5436536SAndroid Build Coastguard Worker     }
3151*e5436536SAndroid Build Coastguard Worker     self->frameOK = 0;
3152*e5436536SAndroid Build Coastguard Worker     aacChannels = 0;
3153*e5436536SAndroid Build Coastguard Worker   }
3154*e5436536SAndroid Build Coastguard Worker 
3155*e5436536SAndroid Build Coastguard Worker   if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
3156*e5436536SAndroid Build Coastguard Worker     if (TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput)) {
3157*e5436536SAndroid Build Coastguard Worker       ErrorStatus = AAC_DEC_CRC_ERROR;
3158*e5436536SAndroid Build Coastguard Worker       self->frameOK = 0;
3159*e5436536SAndroid Build Coastguard Worker     }
3160*e5436536SAndroid Build Coastguard Worker   }
3161*e5436536SAndroid Build Coastguard Worker 
3162*e5436536SAndroid Build Coastguard Worker   /* Ensure that in case of concealment a proper error status is set. */
3163*e5436536SAndroid Build Coastguard Worker   if ((self->frameOK == 0) && (ErrorStatus == AAC_DEC_OK)) {
3164*e5436536SAndroid Build Coastguard Worker     ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
3165*e5436536SAndroid Build Coastguard Worker   }
3166*e5436536SAndroid Build Coastguard Worker 
3167*e5436536SAndroid Build Coastguard Worker   if (self->frameOK && (flags & AACDEC_FLUSH)) {
3168*e5436536SAndroid Build Coastguard Worker     aacChannels = self->aacChannelsPrev;
3169*e5436536SAndroid Build Coastguard Worker     /* Because the downmix could be active, its necessary to restore the channel
3170*e5436536SAndroid Build Coastguard Worker      * type and indices. */
3171*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(self->channelType, self->channelTypePrev,
3172*e5436536SAndroid Build Coastguard Worker               (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */
3173*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(self->channelIndices, self->channelIndicesPrev,
3174*e5436536SAndroid Build Coastguard Worker               (8) * sizeof(UCHAR)); /* restore */
3175*e5436536SAndroid Build Coastguard Worker     self->sbrEnabled = self->sbrEnabledPrev;
3176*e5436536SAndroid Build Coastguard Worker   } else {
3177*e5436536SAndroid Build Coastguard Worker     /* store or restore the number of channels and the corresponding info */
3178*e5436536SAndroid Build Coastguard Worker     if (self->frameOK && !(flags & AACDEC_CONCEAL)) {
3179*e5436536SAndroid Build Coastguard Worker       self->aacChannelsPrev = aacChannels; /* store */
3180*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(self->channelTypePrev, self->channelType,
3181*e5436536SAndroid Build Coastguard Worker                 (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* store */
3182*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(self->channelIndicesPrev, self->channelIndices,
3183*e5436536SAndroid Build Coastguard Worker                 (8) * sizeof(UCHAR)); /* store */
3184*e5436536SAndroid Build Coastguard Worker       self->sbrEnabledPrev = self->sbrEnabled;
3185*e5436536SAndroid Build Coastguard Worker     } else {
3186*e5436536SAndroid Build Coastguard Worker       if (self->aacChannels > 0) {
3187*e5436536SAndroid Build Coastguard Worker         if ((self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON) ||
3188*e5436536SAndroid Build Coastguard Worker             (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON_IN_BAND) ||
3189*e5436536SAndroid Build Coastguard Worker             (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) {
3190*e5436536SAndroid Build Coastguard Worker           aacChannels = self->aacChannels;
3191*e5436536SAndroid Build Coastguard Worker           self->aacChannelsPrev = aacChannels; /* store */
3192*e5436536SAndroid Build Coastguard Worker         } else {
3193*e5436536SAndroid Build Coastguard Worker           aacChannels = self->aacChannelsPrev; /* restore */
3194*e5436536SAndroid Build Coastguard Worker         }
3195*e5436536SAndroid Build Coastguard Worker         FDKmemcpy(self->channelType, self->channelTypePrev,
3196*e5436536SAndroid Build Coastguard Worker                   (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */
3197*e5436536SAndroid Build Coastguard Worker         FDKmemcpy(self->channelIndices, self->channelIndicesPrev,
3198*e5436536SAndroid Build Coastguard Worker                   (8) * sizeof(UCHAR)); /* restore */
3199*e5436536SAndroid Build Coastguard Worker         self->sbrEnabled = self->sbrEnabledPrev;
3200*e5436536SAndroid Build Coastguard Worker       }
3201*e5436536SAndroid Build Coastguard Worker     }
3202*e5436536SAndroid Build Coastguard Worker   }
3203*e5436536SAndroid Build Coastguard Worker 
3204*e5436536SAndroid Build Coastguard Worker   /* Update number of output channels */
3205*e5436536SAndroid Build Coastguard Worker   self->streamInfo.aacNumChannels = aacChannels;
3206*e5436536SAndroid Build Coastguard Worker 
3207*e5436536SAndroid Build Coastguard Worker   /* Ensure consistency of IS_OUTPUT_VALID() macro. */
3208*e5436536SAndroid Build Coastguard Worker   if (aacChannels == 0) {
3209*e5436536SAndroid Build Coastguard Worker     ErrorStatus = AAC_DEC_UNKNOWN;
3210*e5436536SAndroid Build Coastguard Worker   }
3211*e5436536SAndroid Build Coastguard Worker 
3212*e5436536SAndroid Build Coastguard Worker   if (pceRead == 1 && CProgramConfig_IsValid(pce)) {
3213*e5436536SAndroid Build Coastguard Worker     /* Set matrix mixdown infos if available from PCE. */
3214*e5436536SAndroid Build Coastguard Worker     pcmDmx_SetMatrixMixdownFromPce(
3215*e5436536SAndroid Build Coastguard Worker         self->hPcmUtils, pce->MatrixMixdownIndexPresent,
3216*e5436536SAndroid Build Coastguard Worker         pce->MatrixMixdownIndex, pce->PseudoSurroundEnable);
3217*e5436536SAndroid Build Coastguard Worker     ;
3218*e5436536SAndroid Build Coastguard Worker   }
3219*e5436536SAndroid Build Coastguard Worker 
3220*e5436536SAndroid Build Coastguard Worker   /* If there is no valid data to transfrom into time domain, return. */
3221*e5436536SAndroid Build Coastguard Worker   if (!IS_OUTPUT_VALID(ErrorStatus)) {
3222*e5436536SAndroid Build Coastguard Worker     return ErrorStatus;
3223*e5436536SAndroid Build Coastguard Worker   }
3224*e5436536SAndroid Build Coastguard Worker 
3225*e5436536SAndroid Build Coastguard Worker   /* Setup the output channel mapping. The table below shows the three
3226*e5436536SAndroid Build Coastguard Worker    * possibilities: # | chCfg | PCE | chMapIndex
3227*e5436536SAndroid Build Coastguard Worker    *  ---+-------+-----+------------------
3228*e5436536SAndroid Build Coastguard Worker    *   1 |  > 0  |  no | chCfg
3229*e5436536SAndroid Build Coastguard Worker    *   2 |   0   | yes | cChCfg
3230*e5436536SAndroid Build Coastguard Worker    *   3 |   0   |  no | aacChannels || 0
3231*e5436536SAndroid Build Coastguard Worker    *  ---+-------+-----+--------+------------------
3232*e5436536SAndroid Build Coastguard Worker    *  Where chCfg is the channel configuration index from ASC and cChCfg is a
3233*e5436536SAndroid Build Coastguard Worker    * corresponding chCfg derived from a given PCE. The variable aacChannels
3234*e5436536SAndroid Build Coastguard Worker    * represents the number of channel found during bitstream decoding. Due to
3235*e5436536SAndroid Build Coastguard Worker    * the structure of the mapping table it can only be used for mapping if its
3236*e5436536SAndroid Build Coastguard Worker    * value is smaller than 7. Otherwise we use the fallback (0) which is a
3237*e5436536SAndroid Build Coastguard Worker    * simple pass-through. The possibility #3 should appear only with MPEG-2
3238*e5436536SAndroid Build Coastguard Worker    * (ADTS) streams. This is mode is called "implicit channel mapping".
3239*e5436536SAndroid Build Coastguard Worker    */
3240*e5436536SAndroid Build Coastguard Worker   if ((self->streamInfo.channelConfig == 0) && !pce->isValid) {
3241*e5436536SAndroid Build Coastguard Worker     self->chMapIndex = (aacChannels < 7) ? aacChannels : 0;
3242*e5436536SAndroid Build Coastguard Worker   }
3243*e5436536SAndroid Build Coastguard Worker 
3244*e5436536SAndroid Build Coastguard Worker   /*
3245*e5436536SAndroid Build Coastguard Worker     Inverse transform
3246*e5436536SAndroid Build Coastguard Worker   */
3247*e5436536SAndroid Build Coastguard Worker   {
3248*e5436536SAndroid Build Coastguard Worker     int c, cIdx;
3249*e5436536SAndroid Build Coastguard Worker     int mapped, fCopyChMap = 1;
3250*e5436536SAndroid Build Coastguard Worker     UCHAR drcChMap[(8)];
3251*e5436536SAndroid Build Coastguard Worker 
3252*e5436536SAndroid Build Coastguard Worker     if ((self->streamInfo.channelConfig == 0) && CProgramConfig_IsValid(pce)) {
3253*e5436536SAndroid Build Coastguard Worker       /* ISO/IEC 14496-3 says:
3254*e5436536SAndroid Build Coastguard Worker            If a PCE is present, the exclude_mask bits correspond to the audio
3255*e5436536SAndroid Build Coastguard Worker          channels in the SCE, CPE, CCE and LFE syntax elements in the order of
3256*e5436536SAndroid Build Coastguard Worker          their appearance in the PCE. In the case of a CPE, the first
3257*e5436536SAndroid Build Coastguard Worker          transmitted mask bit corresponds to the first channel in the CPE, the
3258*e5436536SAndroid Build Coastguard Worker          second transmitted mask bit to the second channel. In the case of a
3259*e5436536SAndroid Build Coastguard Worker          CCE, a mask bit is transmitted only if the coupling channel is
3260*e5436536SAndroid Build Coastguard Worker          specified to be an independently switched coupling channel. Thus we
3261*e5436536SAndroid Build Coastguard Worker          have to convert the internal channel mapping from "canonical" MPEG to
3262*e5436536SAndroid Build Coastguard Worker          PCE order: */
3263*e5436536SAndroid Build Coastguard Worker       UCHAR tmpChMap[(8)];
3264*e5436536SAndroid Build Coastguard Worker       if (CProgramConfig_GetPceChMap(pce, tmpChMap, (8)) == 0) {
3265*e5436536SAndroid Build Coastguard Worker         for (c = 0; c < aacChannels; c += 1) {
3266*e5436536SAndroid Build Coastguard Worker           drcChMap[c] =
3267*e5436536SAndroid Build Coastguard Worker               (self->chMapping[c] == 255) ? 255 : tmpChMap[self->chMapping[c]];
3268*e5436536SAndroid Build Coastguard Worker         }
3269*e5436536SAndroid Build Coastguard Worker         fCopyChMap = 0;
3270*e5436536SAndroid Build Coastguard Worker       }
3271*e5436536SAndroid Build Coastguard Worker     }
3272*e5436536SAndroid Build Coastguard Worker     if (fCopyChMap != 0) {
3273*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR));
3274*e5436536SAndroid Build Coastguard Worker     }
3275*e5436536SAndroid Build Coastguard Worker 
3276*e5436536SAndroid Build Coastguard Worker     /* Extract DRC control data and map it to channels (without bitstream delay)
3277*e5436536SAndroid Build Coastguard Worker      */
3278*e5436536SAndroid Build Coastguard Worker     mapped = aacDecoder_drcProlog(
3279*e5436536SAndroid Build Coastguard Worker         self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo,
3280*e5436536SAndroid Build Coastguard Worker         pce->ElementInstanceTag, drcChMap, aacChannels);
3281*e5436536SAndroid Build Coastguard Worker     if (mapped > 0) {
3282*e5436536SAndroid Build Coastguard Worker       if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) {
3283*e5436536SAndroid Build Coastguard Worker         /* If at least one DRC thread has been mapped to a channel there was DRC
3284*e5436536SAndroid Build Coastguard Worker          * data in the bitstream. */
3285*e5436536SAndroid Build Coastguard Worker         self->flags[streamIndex] |= AC_DRC_PRESENT;
3286*e5436536SAndroid Build Coastguard Worker       } else {
3287*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
3288*e5436536SAndroid Build Coastguard Worker       }
3289*e5436536SAndroid Build Coastguard Worker     }
3290*e5436536SAndroid Build Coastguard Worker     if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
3291*e5436536SAndroid Build Coastguard Worker       aacDecoder_drcDisable(self->hDrcInfo);
3292*e5436536SAndroid Build Coastguard Worker     }
3293*e5436536SAndroid Build Coastguard Worker 
3294*e5436536SAndroid Build Coastguard Worker     /* Create a reverse mapping table */
3295*e5436536SAndroid Build Coastguard Worker     UCHAR Reverse_chMapping[((8) * 2)];
3296*e5436536SAndroid Build Coastguard Worker     for (c = 0; c < aacChannels; c++) {
3297*e5436536SAndroid Build Coastguard Worker       int d;
3298*e5436536SAndroid Build Coastguard Worker       for (d = 0; d < aacChannels - 1; d++) {
3299*e5436536SAndroid Build Coastguard Worker         if (self->chMapping[d] == c) {
3300*e5436536SAndroid Build Coastguard Worker           break;
3301*e5436536SAndroid Build Coastguard Worker         }
3302*e5436536SAndroid Build Coastguard Worker       }
3303*e5436536SAndroid Build Coastguard Worker       Reverse_chMapping[c] = d;
3304*e5436536SAndroid Build Coastguard Worker     }
3305*e5436536SAndroid Build Coastguard Worker 
3306*e5436536SAndroid Build Coastguard Worker     int el;
3307*e5436536SAndroid Build Coastguard Worker     int el_channels;
3308*e5436536SAndroid Build Coastguard Worker     c = 0;
3309*e5436536SAndroid Build Coastguard Worker     cIdx = 0;
3310*e5436536SAndroid Build Coastguard Worker     el_channels = 0;
3311*e5436536SAndroid Build Coastguard Worker     for (el = 0; el < element_count; el++) {
3312*e5436536SAndroid Build Coastguard Worker       int frameOk_butConceal =
3313*e5436536SAndroid Build Coastguard Worker           0; /* Force frame concealment during mute release active state. */
3314*e5436536SAndroid Build Coastguard Worker       int concealApplyReturnCode;
3315*e5436536SAndroid Build Coastguard Worker 
3316*e5436536SAndroid Build Coastguard Worker       if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) {
3317*e5436536SAndroid Build Coastguard Worker         type = self->elements[el];
3318*e5436536SAndroid Build Coastguard Worker       } else {
3319*e5436536SAndroid Build Coastguard Worker         type = channel_elements[el];
3320*e5436536SAndroid Build Coastguard Worker       }
3321*e5436536SAndroid Build Coastguard Worker 
3322*e5436536SAndroid Build Coastguard Worker       {
3323*e5436536SAndroid Build Coastguard Worker         int nElementChannels;
3324*e5436536SAndroid Build Coastguard Worker 
3325*e5436536SAndroid Build Coastguard Worker         nElementChannels =
3326*e5436536SAndroid Build Coastguard Worker             CAacDecoder_GetELChannels(type, self->usacStereoConfigIndex[el]);
3327*e5436536SAndroid Build Coastguard Worker 
3328*e5436536SAndroid Build Coastguard Worker         el_channels += nElementChannels;
3329*e5436536SAndroid Build Coastguard Worker 
3330*e5436536SAndroid Build Coastguard Worker         if (nElementChannels == 0) {
3331*e5436536SAndroid Build Coastguard Worker           continue;
3332*e5436536SAndroid Build Coastguard Worker         }
3333*e5436536SAndroid Build Coastguard Worker       }
3334*e5436536SAndroid Build Coastguard Worker 
3335*e5436536SAndroid Build Coastguard Worker       int offset;
3336*e5436536SAndroid Build Coastguard Worker       int elCh = 0;
3337*e5436536SAndroid Build Coastguard Worker       /* "c" iterates in canonical MPEG channel order */
3338*e5436536SAndroid Build Coastguard Worker       for (; cIdx < el_channels; c++, cIdx++, elCh++) {
3339*e5436536SAndroid Build Coastguard Worker         /* Robustness check */
3340*e5436536SAndroid Build Coastguard Worker         if (c >= aacChannels) {
3341*e5436536SAndroid Build Coastguard Worker           return AAC_DEC_UNKNOWN;
3342*e5436536SAndroid Build Coastguard Worker         }
3343*e5436536SAndroid Build Coastguard Worker 
3344*e5436536SAndroid Build Coastguard Worker         CAacDecoderChannelInfo *pAacDecoderChannelInfo =
3345*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderChannelInfo[c];
3346*e5436536SAndroid Build Coastguard Worker         CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo =
3347*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderStaticChannelInfo[c];
3348*e5436536SAndroid Build Coastguard Worker 
3349*e5436536SAndroid Build Coastguard Worker         /* Setup offset for time buffer traversal. */
3350*e5436536SAndroid Build Coastguard Worker         {
3351*e5436536SAndroid Build Coastguard Worker           pAacDecoderStaticChannelInfo =
3352*e5436536SAndroid Build Coastguard Worker               self->pAacDecoderStaticChannelInfo[Reverse_chMapping[c]];
3353*e5436536SAndroid Build Coastguard Worker           offset =
3354*e5436536SAndroid Build Coastguard Worker               FDK_chMapDescr_getMapValue(
3355*e5436536SAndroid Build Coastguard Worker                   &self->mapDescr, Reverse_chMapping[cIdx], self->chMapIndex) *
3356*e5436536SAndroid Build Coastguard Worker               timeDataChannelOffset;
3357*e5436536SAndroid Build Coastguard Worker         }
3358*e5436536SAndroid Build Coastguard Worker 
3359*e5436536SAndroid Build Coastguard Worker         if (flags & AACDEC_FLUSH) {
3360*e5436536SAndroid Build Coastguard Worker           /* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with
3361*e5436536SAndroid Build Coastguard Worker            * AACDEC_FLUSH set it contains undefined data. */
3362*e5436536SAndroid Build Coastguard Worker           FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient,
3363*e5436536SAndroid Build Coastguard Worker                       sizeof(FIXP_DBL) * self->streamInfo.aacSamplesPerFrame);
3364*e5436536SAndroid Build Coastguard Worker         }
3365*e5436536SAndroid Build Coastguard Worker 
3366*e5436536SAndroid Build Coastguard Worker         /* if The ics info is not valid and it will be stored and used in the
3367*e5436536SAndroid Build Coastguard Worker          * following concealment method, mark the frame as erroneous */
3368*e5436536SAndroid Build Coastguard Worker         {
3369*e5436536SAndroid Build Coastguard Worker           CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
3370*e5436536SAndroid Build Coastguard Worker           CConcealmentInfo *hConcealmentInfo =
3371*e5436536SAndroid Build Coastguard Worker               &pAacDecoderStaticChannelInfo->concealmentInfo;
3372*e5436536SAndroid Build Coastguard Worker           const int mute_release_active =
3373*e5436536SAndroid Build Coastguard Worker               (self->frameOK && !(flags & AACDEC_CONCEAL)) &&
3374*e5436536SAndroid Build Coastguard Worker               ((hConcealmentInfo->concealState >= ConcealState_Mute) &&
3375*e5436536SAndroid Build Coastguard Worker                (hConcealmentInfo->cntValidFrames + 1 <=
3376*e5436536SAndroid Build Coastguard Worker                 hConcealmentInfo->pConcealParams->numMuteReleaseFrames));
3377*e5436536SAndroid Build Coastguard Worker           const int icsIsInvalid = (GetScaleFactorBandsTransmitted(pIcsInfo) >
3378*e5436536SAndroid Build Coastguard Worker                                     GetScaleFactorBandsTotal(pIcsInfo));
3379*e5436536SAndroid Build Coastguard Worker           const int icsInfoUsedinFadeOut =
3380*e5436536SAndroid Build Coastguard Worker               !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD &&
3381*e5436536SAndroid Build Coastguard Worker                 pAacDecoderStaticChannelInfo->last_lpd_mode == 0);
3382*e5436536SAndroid Build Coastguard Worker           if (icsInfoUsedinFadeOut && icsIsInvalid && !mute_release_active) {
3383*e5436536SAndroid Build Coastguard Worker             self->frameOK = 0;
3384*e5436536SAndroid Build Coastguard Worker           }
3385*e5436536SAndroid Build Coastguard Worker         }
3386*e5436536SAndroid Build Coastguard Worker 
3387*e5436536SAndroid Build Coastguard Worker         /*
3388*e5436536SAndroid Build Coastguard Worker           Conceal defective spectral data
3389*e5436536SAndroid Build Coastguard Worker         */
3390*e5436536SAndroid Build Coastguard Worker         {
3391*e5436536SAndroid Build Coastguard Worker           CAacDecoderChannelInfo **ppAacDecoderChannelInfo =
3392*e5436536SAndroid Build Coastguard Worker               &pAacDecoderChannelInfo;
3393*e5436536SAndroid Build Coastguard Worker           CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo =
3394*e5436536SAndroid Build Coastguard Worker               &pAacDecoderStaticChannelInfo;
3395*e5436536SAndroid Build Coastguard Worker           {
3396*e5436536SAndroid Build Coastguard Worker             concealApplyReturnCode = CConcealment_Apply(
3397*e5436536SAndroid Build Coastguard Worker                 &(*ppAacDecoderStaticChannelInfo)->concealmentInfo,
3398*e5436536SAndroid Build Coastguard Worker                 *ppAacDecoderChannelInfo, *ppAacDecoderStaticChannelInfo,
3399*e5436536SAndroid Build Coastguard Worker                 &self->samplingRateInfo[streamIndex],
3400*e5436536SAndroid Build Coastguard Worker                 self->streamInfo.aacSamplesPerFrame,
3401*e5436536SAndroid Build Coastguard Worker                 pAacDecoderStaticChannelInfo->last_lpd_mode,
3402*e5436536SAndroid Build Coastguard Worker                 (self->frameOK && !(flags & AACDEC_CONCEAL)),
3403*e5436536SAndroid Build Coastguard Worker                 self->flags[streamIndex]);
3404*e5436536SAndroid Build Coastguard Worker           }
3405*e5436536SAndroid Build Coastguard Worker         }
3406*e5436536SAndroid Build Coastguard Worker         if (concealApplyReturnCode == -1) {
3407*e5436536SAndroid Build Coastguard Worker           frameOk_butConceal = 1;
3408*e5436536SAndroid Build Coastguard Worker         }
3409*e5436536SAndroid Build Coastguard Worker 
3410*e5436536SAndroid Build Coastguard Worker         if (flags & (AACDEC_INTR)) {
3411*e5436536SAndroid Build Coastguard Worker           /* Reset DRC control data for this channel */
3412*e5436536SAndroid Build Coastguard Worker           aacDecoder_drcInitChannelData(&pAacDecoderStaticChannelInfo->drcData);
3413*e5436536SAndroid Build Coastguard Worker         }
3414*e5436536SAndroid Build Coastguard Worker         if (flags & (AACDEC_CLRHIST)) {
3415*e5436536SAndroid Build Coastguard Worker           if (!(self->flags[0] & AC_USAC)) {
3416*e5436536SAndroid Build Coastguard Worker             /* Reset DRC control data for this channel */
3417*e5436536SAndroid Build Coastguard Worker             aacDecoder_drcInitChannelData(
3418*e5436536SAndroid Build Coastguard Worker                 &pAacDecoderStaticChannelInfo->drcData);
3419*e5436536SAndroid Build Coastguard Worker           }
3420*e5436536SAndroid Build Coastguard Worker         }
3421*e5436536SAndroid Build Coastguard Worker 
3422*e5436536SAndroid Build Coastguard Worker         /* The DRC module demands to be called with the gain field holding the
3423*e5436536SAndroid Build Coastguard Worker          * gain scale. */
3424*e5436536SAndroid Build Coastguard Worker         self->extGain[0] = (FIXP_DBL)AACDEC_DRC_GAIN_SCALING;
3425*e5436536SAndroid Build Coastguard Worker 
3426*e5436536SAndroid Build Coastguard Worker         /* DRC processing */
3427*e5436536SAndroid Build Coastguard Worker         aacDecoder_drcApply(
3428*e5436536SAndroid Build Coastguard Worker             self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo,
3429*e5436536SAndroid Build Coastguard Worker             &pAacDecoderStaticChannelInfo->drcData, self->extGain, c,
3430*e5436536SAndroid Build Coastguard Worker             self->streamInfo.aacSamplesPerFrame, self->sbrEnabled
3431*e5436536SAndroid Build Coastguard Worker 
3432*e5436536SAndroid Build Coastguard Worker         );
3433*e5436536SAndroid Build Coastguard Worker 
3434*e5436536SAndroid Build Coastguard Worker         if (timeDataSize < timeDataChannelOffset * self->aacChannels) {
3435*e5436536SAndroid Build Coastguard Worker           ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
3436*e5436536SAndroid Build Coastguard Worker           break;
3437*e5436536SAndroid Build Coastguard Worker         }
3438*e5436536SAndroid Build Coastguard Worker         if (self->flushStatus && (self->flushCnt > 0) &&
3439*e5436536SAndroid Build Coastguard Worker             !(flags & AACDEC_CONCEAL)) {
3440*e5436536SAndroid Build Coastguard Worker           FDKmemclear(pTimeData + offset,
3441*e5436536SAndroid Build Coastguard Worker                       sizeof(PCM_DEC) * self->streamInfo.aacSamplesPerFrame);
3442*e5436536SAndroid Build Coastguard Worker         } else
3443*e5436536SAndroid Build Coastguard Worker           switch (pAacDecoderChannelInfo->renderMode) {
3444*e5436536SAndroid Build Coastguard Worker             case AACDEC_RENDER_IMDCT:
3445*e5436536SAndroid Build Coastguard Worker 
3446*e5436536SAndroid Build Coastguard Worker               CBlock_FrequencyToTime(
3447*e5436536SAndroid Build Coastguard Worker                   pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo,
3448*e5436536SAndroid Build Coastguard Worker                   pTimeData + offset, self->streamInfo.aacSamplesPerFrame,
3449*e5436536SAndroid Build Coastguard Worker                   (self->frameOK && !(flags & AACDEC_CONCEAL) &&
3450*e5436536SAndroid Build Coastguard Worker                    !frameOk_butConceal),
3451*e5436536SAndroid Build Coastguard Worker                   pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1
3452*e5436536SAndroid Build Coastguard Worker                       ->mdctOutTemp,
3453*e5436536SAndroid Build Coastguard Worker                   self->aacOutDataHeadroom, self->elFlags[el], elCh);
3454*e5436536SAndroid Build Coastguard Worker 
3455*e5436536SAndroid Build Coastguard Worker               self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
3456*e5436536SAndroid Build Coastguard Worker               break;
3457*e5436536SAndroid Build Coastguard Worker             case AACDEC_RENDER_ELDFB: {
3458*e5436536SAndroid Build Coastguard Worker               CBlock_FrequencyToTimeLowDelay(
3459*e5436536SAndroid Build Coastguard Worker                   pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo,
3460*e5436536SAndroid Build Coastguard Worker                   pTimeData + offset, self->streamInfo.aacSamplesPerFrame);
3461*e5436536SAndroid Build Coastguard Worker               self->extGainDelay =
3462*e5436536SAndroid Build Coastguard Worker                   (self->streamInfo.aacSamplesPerFrame * 2 -
3463*e5436536SAndroid Build Coastguard Worker                    self->streamInfo.aacSamplesPerFrame / 2 - 1) /
3464*e5436536SAndroid Build Coastguard Worker                   2;
3465*e5436536SAndroid Build Coastguard Worker             } break;
3466*e5436536SAndroid Build Coastguard Worker             case AACDEC_RENDER_LPD:
3467*e5436536SAndroid Build Coastguard Worker 
3468*e5436536SAndroid Build Coastguard Worker               CLpd_RenderTimeSignal(
3469*e5436536SAndroid Build Coastguard Worker                   pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo,
3470*e5436536SAndroid Build Coastguard Worker                   pTimeData + offset, self->streamInfo.aacSamplesPerFrame,
3471*e5436536SAndroid Build Coastguard Worker                   &self->samplingRateInfo[streamIndex],
3472*e5436536SAndroid Build Coastguard Worker                   (self->frameOK && !(flags & AACDEC_CONCEAL) &&
3473*e5436536SAndroid Build Coastguard Worker                    !frameOk_butConceal),
3474*e5436536SAndroid Build Coastguard Worker                   self->aacOutDataHeadroom, flags, self->flags[streamIndex]);
3475*e5436536SAndroid Build Coastguard Worker 
3476*e5436536SAndroid Build Coastguard Worker               self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
3477*e5436536SAndroid Build Coastguard Worker               break;
3478*e5436536SAndroid Build Coastguard Worker             default:
3479*e5436536SAndroid Build Coastguard Worker               ErrorStatus = AAC_DEC_UNKNOWN;
3480*e5436536SAndroid Build Coastguard Worker               break;
3481*e5436536SAndroid Build Coastguard Worker           }
3482*e5436536SAndroid Build Coastguard Worker         /* TimeDomainFading */
3483*e5436536SAndroid Build Coastguard Worker         if (!CConceal_TDFading_Applied[c]) {
3484*e5436536SAndroid Build Coastguard Worker           CConceal_TDFading_Applied[c] = CConcealment_TDFading(
3485*e5436536SAndroid Build Coastguard Worker               self->streamInfo.aacSamplesPerFrame,
3486*e5436536SAndroid Build Coastguard Worker               &self->pAacDecoderStaticChannelInfo[c], self->aacOutDataHeadroom,
3487*e5436536SAndroid Build Coastguard Worker               pTimeData + offset, 0);
3488*e5436536SAndroid Build Coastguard Worker           if (c + 1 < (8) && c < aacChannels - 1) {
3489*e5436536SAndroid Build Coastguard Worker             /* update next TDNoise Seed to avoid muting in case of Parametric
3490*e5436536SAndroid Build Coastguard Worker              * Stereo */
3491*e5436536SAndroid Build Coastguard Worker             self->pAacDecoderStaticChannelInfo[c + 1]
3492*e5436536SAndroid Build Coastguard Worker                 ->concealmentInfo.TDNoiseSeed =
3493*e5436536SAndroid Build Coastguard Worker                 self->pAacDecoderStaticChannelInfo[c]
3494*e5436536SAndroid Build Coastguard Worker                     ->concealmentInfo.TDNoiseSeed;
3495*e5436536SAndroid Build Coastguard Worker           }
3496*e5436536SAndroid Build Coastguard Worker         }
3497*e5436536SAndroid Build Coastguard Worker       }
3498*e5436536SAndroid Build Coastguard Worker     }
3499*e5436536SAndroid Build Coastguard Worker 
3500*e5436536SAndroid Build Coastguard Worker     if (self->flags[streamIndex] & AC_USAC) {
3501*e5436536SAndroid Build Coastguard Worker       int bsPseudoLr = 0;
3502*e5436536SAndroid Build Coastguard Worker       mpegSurroundDecoder_IsPseudoLR(
3503*e5436536SAndroid Build Coastguard Worker           (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, &bsPseudoLr);
3504*e5436536SAndroid Build Coastguard Worker       /* ISO/IEC 23003-3, 7.11.2.6 Modification of core decoder output (pseudo
3505*e5436536SAndroid Build Coastguard Worker        * LR) */
3506*e5436536SAndroid Build Coastguard Worker       if ((aacChannels == 2) && bsPseudoLr) {
3507*e5436536SAndroid Build Coastguard Worker         int i, offset2;
3508*e5436536SAndroid Build Coastguard Worker         const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f);
3509*e5436536SAndroid Build Coastguard Worker         PCM_DEC *pTD = pTimeData;
3510*e5436536SAndroid Build Coastguard Worker 
3511*e5436536SAndroid Build Coastguard Worker         offset2 = timeDataChannelOffset;
3512*e5436536SAndroid Build Coastguard Worker 
3513*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) {
3514*e5436536SAndroid Build Coastguard Worker           FIXP_DBL L = PCM_DEC2FIXP_DBL(pTD[0]);
3515*e5436536SAndroid Build Coastguard Worker           FIXP_DBL R = PCM_DEC2FIXP_DBL(pTD[offset2]);
3516*e5436536SAndroid Build Coastguard Worker           L = fMult(L, invSqrt2);
3517*e5436536SAndroid Build Coastguard Worker           R = fMult(R, invSqrt2);
3518*e5436536SAndroid Build Coastguard Worker           pTD[0] = L + R;
3519*e5436536SAndroid Build Coastguard Worker           pTD[offset2] = L - R;
3520*e5436536SAndroid Build Coastguard Worker           pTD++;
3521*e5436536SAndroid Build Coastguard Worker         }
3522*e5436536SAndroid Build Coastguard Worker       }
3523*e5436536SAndroid Build Coastguard Worker     }
3524*e5436536SAndroid Build Coastguard Worker 
3525*e5436536SAndroid Build Coastguard Worker     /* Extract DRC control data and map it to channels (with bitstream delay) */
3526*e5436536SAndroid Build Coastguard Worker     mapped = aacDecoder_drcEpilog(
3527*e5436536SAndroid Build Coastguard Worker         self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo,
3528*e5436536SAndroid Build Coastguard Worker         pce->ElementInstanceTag, drcChMap, aacChannels);
3529*e5436536SAndroid Build Coastguard Worker     if (mapped > 0) {
3530*e5436536SAndroid Build Coastguard Worker       if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) {
3531*e5436536SAndroid Build Coastguard Worker         /* If at least one DRC thread has been mapped to a channel there was DRC
3532*e5436536SAndroid Build Coastguard Worker          * data in the bitstream. */
3533*e5436536SAndroid Build Coastguard Worker         self->flags[streamIndex] |= AC_DRC_PRESENT;
3534*e5436536SAndroid Build Coastguard Worker       } else {
3535*e5436536SAndroid Build Coastguard Worker         ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
3536*e5436536SAndroid Build Coastguard Worker       }
3537*e5436536SAndroid Build Coastguard Worker     }
3538*e5436536SAndroid Build Coastguard Worker     if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
3539*e5436536SAndroid Build Coastguard Worker       aacDecoder_drcDisable(self->hDrcInfo);
3540*e5436536SAndroid Build Coastguard Worker     }
3541*e5436536SAndroid Build Coastguard Worker   }
3542*e5436536SAndroid Build Coastguard Worker 
3543*e5436536SAndroid Build Coastguard Worker   /* Add additional concealment delay */
3544*e5436536SAndroid Build Coastguard Worker   self->streamInfo.outputDelay +=
3545*e5436536SAndroid Build Coastguard Worker       CConcealment_GetDelay(&self->concealCommonData) *
3546*e5436536SAndroid Build Coastguard Worker       self->streamInfo.aacSamplesPerFrame;
3547*e5436536SAndroid Build Coastguard Worker 
3548*e5436536SAndroid Build Coastguard Worker   /* Map DRC data to StreamInfo structure */
3549*e5436536SAndroid Build Coastguard Worker   aacDecoder_drcGetInfo(self->hDrcInfo, &self->streamInfo.drcPresMode,
3550*e5436536SAndroid Build Coastguard Worker                         &self->streamInfo.drcProgRefLev);
3551*e5436536SAndroid Build Coastguard Worker 
3552*e5436536SAndroid Build Coastguard Worker   /* Reorder channel type information tables.  */
3553*e5436536SAndroid Build Coastguard Worker   if (!(self->flags[0] & AC_RSV603DA)) {
3554*e5436536SAndroid Build Coastguard Worker     AUDIO_CHANNEL_TYPE types[(8)];
3555*e5436536SAndroid Build Coastguard Worker     UCHAR idx[(8)];
3556*e5436536SAndroid Build Coastguard Worker     int c;
3557*e5436536SAndroid Build Coastguard Worker     int mapValue;
3558*e5436536SAndroid Build Coastguard Worker 
3559*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
3560*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx));
3561*e5436536SAndroid Build Coastguard Worker 
3562*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(types, self->channelType, sizeof(types));
3563*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(idx, self->channelIndices, sizeof(idx));
3564*e5436536SAndroid Build Coastguard Worker 
3565*e5436536SAndroid Build Coastguard Worker     for (c = 0; c < aacChannels; c++) {
3566*e5436536SAndroid Build Coastguard Worker       mapValue =
3567*e5436536SAndroid Build Coastguard Worker           FDK_chMapDescr_getMapValue(&self->mapDescr, c, self->chMapIndex);
3568*e5436536SAndroid Build Coastguard Worker       self->channelType[mapValue] = types[c];
3569*e5436536SAndroid Build Coastguard Worker       self->channelIndices[mapValue] = idx[c];
3570*e5436536SAndroid Build Coastguard Worker     }
3571*e5436536SAndroid Build Coastguard Worker   }
3572*e5436536SAndroid Build Coastguard Worker 
3573*e5436536SAndroid Build Coastguard Worker   self->blockNumber++;
3574*e5436536SAndroid Build Coastguard Worker 
3575*e5436536SAndroid Build Coastguard Worker   return ErrorStatus;
3576*e5436536SAndroid Build Coastguard Worker }
3577*e5436536SAndroid Build Coastguard Worker 
3578*e5436536SAndroid Build Coastguard Worker /*!
3579*e5436536SAndroid Build Coastguard Worker   \brief returns the streaminfo pointer
3580*e5436536SAndroid Build Coastguard Worker 
3581*e5436536SAndroid Build Coastguard Worker   The function hands back a pointer to the streaminfo structure
3582*e5436536SAndroid Build Coastguard Worker 
3583*e5436536SAndroid Build Coastguard Worker   \return pointer to the struct
3584*e5436536SAndroid Build Coastguard Worker */
CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self)3585*e5436536SAndroid Build Coastguard Worker LINKSPEC_CPP CStreamInfo *CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self) {
3586*e5436536SAndroid Build Coastguard Worker   if (!self) {
3587*e5436536SAndroid Build Coastguard Worker     return NULL;
3588*e5436536SAndroid Build Coastguard Worker   }
3589*e5436536SAndroid Build Coastguard Worker   return &self->streamInfo;
3590*e5436536SAndroid Build Coastguard Worker }
3591