xref: /aosp_15_r20/external/aac/libSBRdec/src/sbrdecoder.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 - 2021 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 /**************************** SBR decoder library ******************************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):
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   \file
105*e5436536SAndroid Build Coastguard Worker   \brief  SBR decoder frontend
106*e5436536SAndroid Build Coastguard Worker   This module provides a frontend to the SBR decoder. The function openSBR() is
107*e5436536SAndroid Build Coastguard Worker   called for initialization. The function sbrDecoder_Apply() is called for each
108*e5436536SAndroid Build Coastguard Worker   frame. sbr_Apply() will call the required functions to decode the raw SBR data
109*e5436536SAndroid Build Coastguard Worker   (provided by env_extr.cpp), to decode the envelope data and noise floor levels
110*e5436536SAndroid Build Coastguard Worker   [decodeSbrData()], and to finally apply SBR to the current frame [sbr_dec()].
111*e5436536SAndroid Build Coastguard Worker 
112*e5436536SAndroid Build Coastguard Worker   \sa sbrDecoder_Apply(), \ref documentationOverview
113*e5436536SAndroid Build Coastguard Worker */
114*e5436536SAndroid Build Coastguard Worker 
115*e5436536SAndroid Build Coastguard Worker /*!
116*e5436536SAndroid Build Coastguard Worker   \page documentationOverview Overview of important information resources and
117*e5436536SAndroid Build Coastguard Worker   source code documentation
118*e5436536SAndroid Build Coastguard Worker 
119*e5436536SAndroid Build Coastguard Worker   As part of this documentation you can find more extensive descriptions about
120*e5436536SAndroid Build Coastguard Worker   key concepts and algorithms at the following locations:
121*e5436536SAndroid Build Coastguard Worker 
122*e5436536SAndroid Build Coastguard Worker   <h2>Programming</h2>
123*e5436536SAndroid Build Coastguard Worker 
124*e5436536SAndroid Build Coastguard Worker   \li Buffer management: sbrDecoder_Apply() and sbr_dec()
125*e5436536SAndroid Build Coastguard Worker   \li Internal scale factors to maximize SNR on fixed point processors:
126*e5436536SAndroid Build Coastguard Worker   #QMF_SCALE_FACTOR \li Special mantissa-exponent format: Created in
127*e5436536SAndroid Build Coastguard Worker   requantizeEnvelopeData() and used in calculateSbrEnvelope()
128*e5436536SAndroid Build Coastguard Worker 
129*e5436536SAndroid Build Coastguard Worker   <h2>Algorithmic details</h2>
130*e5436536SAndroid Build Coastguard Worker   \li About the SBR data format: \ref SBR_HEADER_ELEMENT and \ref
131*e5436536SAndroid Build Coastguard Worker   SBR_STANDARD_ELEMENT \li Details about the bitstream decoder: env_extr.cpp \li
132*e5436536SAndroid Build Coastguard Worker   Details about the QMF filterbank and the provided polyphase implementation:
133*e5436536SAndroid Build Coastguard Worker   qmf_dec.cpp \li Details about the transposer: lpp_tran.cpp \li Details about
134*e5436536SAndroid Build Coastguard Worker   the envelope adjuster: env_calc.cpp
135*e5436536SAndroid Build Coastguard Worker 
136*e5436536SAndroid Build Coastguard Worker */
137*e5436536SAndroid Build Coastguard Worker 
138*e5436536SAndroid Build Coastguard Worker #include "sbrdecoder.h"
139*e5436536SAndroid Build Coastguard Worker 
140*e5436536SAndroid Build Coastguard Worker #include "FDK_bitstream.h"
141*e5436536SAndroid Build Coastguard Worker 
142*e5436536SAndroid Build Coastguard Worker #include "sbrdec_freq_sca.h"
143*e5436536SAndroid Build Coastguard Worker #include "env_extr.h"
144*e5436536SAndroid Build Coastguard Worker #include "sbr_dec.h"
145*e5436536SAndroid Build Coastguard Worker #include "env_dec.h"
146*e5436536SAndroid Build Coastguard Worker #include "FDK_crc.h"
147*e5436536SAndroid Build Coastguard Worker #include "sbr_ram.h"
148*e5436536SAndroid Build Coastguard Worker #include "sbr_rom.h"
149*e5436536SAndroid Build Coastguard Worker #include "lpp_tran.h"
150*e5436536SAndroid Build Coastguard Worker #include "transcendent.h"
151*e5436536SAndroid Build Coastguard Worker 
152*e5436536SAndroid Build Coastguard Worker #include "sbrdec_drc.h"
153*e5436536SAndroid Build Coastguard Worker 
154*e5436536SAndroid Build Coastguard Worker #include "psbitdec.h"
155*e5436536SAndroid Build Coastguard Worker 
156*e5436536SAndroid Build Coastguard Worker /* Decoder library info */
157*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_VL0 3
158*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_VL1 1
159*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_VL2 0
160*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_TITLE "SBR Decoder"
161*e5436536SAndroid Build Coastguard Worker #ifdef SUPPRESS_BUILD_DATE_INFO
162*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_BUILD_DATE ""
163*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_BUILD_TIME ""
164*e5436536SAndroid Build Coastguard Worker #else
165*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_BUILD_DATE __DATE__
166*e5436536SAndroid Build Coastguard Worker #define SBRDECODER_LIB_BUILD_TIME __TIME__
167*e5436536SAndroid Build Coastguard Worker #endif
168*e5436536SAndroid Build Coastguard Worker 
setFrameErrorFlag(SBR_DECODER_ELEMENT * pSbrElement,UCHAR value)169*e5436536SAndroid Build Coastguard Worker static void setFrameErrorFlag(SBR_DECODER_ELEMENT *pSbrElement, UCHAR value) {
170*e5436536SAndroid Build Coastguard Worker   if (pSbrElement != NULL) {
171*e5436536SAndroid Build Coastguard Worker     switch (value) {
172*e5436536SAndroid Build Coastguard Worker       case FRAME_ERROR_ALLSLOTS:
173*e5436536SAndroid Build Coastguard Worker         FDKmemset(pSbrElement->frameErrorFlag, FRAME_ERROR,
174*e5436536SAndroid Build Coastguard Worker                   sizeof(pSbrElement->frameErrorFlag));
175*e5436536SAndroid Build Coastguard Worker         break;
176*e5436536SAndroid Build Coastguard Worker       default:
177*e5436536SAndroid Build Coastguard Worker         pSbrElement->frameErrorFlag[pSbrElement->useFrameSlot] = value;
178*e5436536SAndroid Build Coastguard Worker     }
179*e5436536SAndroid Build Coastguard Worker   }
180*e5436536SAndroid Build Coastguard Worker }
181*e5436536SAndroid Build Coastguard Worker 
getHeaderSlot(UCHAR currentSlot,UCHAR hdrSlotUsage[(1)+1])182*e5436536SAndroid Build Coastguard Worker static UCHAR getHeaderSlot(UCHAR currentSlot, UCHAR hdrSlotUsage[(1) + 1]) {
183*e5436536SAndroid Build Coastguard Worker   UINT occupied = 0;
184*e5436536SAndroid Build Coastguard Worker   int s;
185*e5436536SAndroid Build Coastguard Worker   UCHAR slot = hdrSlotUsage[currentSlot];
186*e5436536SAndroid Build Coastguard Worker 
187*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT((1) + 1 < 32);
188*e5436536SAndroid Build Coastguard Worker 
189*e5436536SAndroid Build Coastguard Worker   for (s = 0; s < (1) + 1; s++) {
190*e5436536SAndroid Build Coastguard Worker     if ((hdrSlotUsage[s] == slot) && (s != slot)) {
191*e5436536SAndroid Build Coastguard Worker       occupied = 1;
192*e5436536SAndroid Build Coastguard Worker       break;
193*e5436536SAndroid Build Coastguard Worker     }
194*e5436536SAndroid Build Coastguard Worker   }
195*e5436536SAndroid Build Coastguard Worker 
196*e5436536SAndroid Build Coastguard Worker   if (occupied) {
197*e5436536SAndroid Build Coastguard Worker     occupied = 0;
198*e5436536SAndroid Build Coastguard Worker 
199*e5436536SAndroid Build Coastguard Worker     for (s = 0; s < (1) + 1; s++) {
200*e5436536SAndroid Build Coastguard Worker       occupied |= 1 << hdrSlotUsage[s];
201*e5436536SAndroid Build Coastguard Worker     }
202*e5436536SAndroid Build Coastguard Worker     for (s = 0; s < (1) + 1; s++) {
203*e5436536SAndroid Build Coastguard Worker       if (!(occupied & 0x1)) {
204*e5436536SAndroid Build Coastguard Worker         slot = s;
205*e5436536SAndroid Build Coastguard Worker         break;
206*e5436536SAndroid Build Coastguard Worker       }
207*e5436536SAndroid Build Coastguard Worker       occupied >>= 1;
208*e5436536SAndroid Build Coastguard Worker     }
209*e5436536SAndroid Build Coastguard Worker   }
210*e5436536SAndroid Build Coastguard Worker 
211*e5436536SAndroid Build Coastguard Worker   return slot;
212*e5436536SAndroid Build Coastguard Worker }
213*e5436536SAndroid Build Coastguard Worker 
copySbrHeader(HANDLE_SBR_HEADER_DATA hDst,const HANDLE_SBR_HEADER_DATA hSrc)214*e5436536SAndroid Build Coastguard Worker static void copySbrHeader(HANDLE_SBR_HEADER_DATA hDst,
215*e5436536SAndroid Build Coastguard Worker                           const HANDLE_SBR_HEADER_DATA hSrc) {
216*e5436536SAndroid Build Coastguard Worker   /* copy the whole header memory (including pointers) */
217*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(hDst, hSrc, sizeof(SBR_HEADER_DATA));
218*e5436536SAndroid Build Coastguard Worker 
219*e5436536SAndroid Build Coastguard Worker   /* update pointers */
220*e5436536SAndroid Build Coastguard Worker   hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo;
221*e5436536SAndroid Build Coastguard Worker   hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi;
222*e5436536SAndroid Build Coastguard Worker }
223*e5436536SAndroid Build Coastguard Worker 
compareSbrHeader(const HANDLE_SBR_HEADER_DATA hHdr1,const HANDLE_SBR_HEADER_DATA hHdr2)224*e5436536SAndroid Build Coastguard Worker static int compareSbrHeader(const HANDLE_SBR_HEADER_DATA hHdr1,
225*e5436536SAndroid Build Coastguard Worker                             const HANDLE_SBR_HEADER_DATA hHdr2) {
226*e5436536SAndroid Build Coastguard Worker   int result = 0;
227*e5436536SAndroid Build Coastguard Worker 
228*e5436536SAndroid Build Coastguard Worker   /* compare basic data */
229*e5436536SAndroid Build Coastguard Worker   result |= (hHdr1->syncState != hHdr2->syncState) ? 1 : 0;
230*e5436536SAndroid Build Coastguard Worker   result |= (hHdr1->status != hHdr2->status) ? 1 : 0;
231*e5436536SAndroid Build Coastguard Worker   result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0;
232*e5436536SAndroid Build Coastguard Worker   result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0;
233*e5436536SAndroid Build Coastguard Worker   result |=
234*e5436536SAndroid Build Coastguard Worker       (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0;
235*e5436536SAndroid Build Coastguard Worker   result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0;
236*e5436536SAndroid Build Coastguard Worker   result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0;
237*e5436536SAndroid Build Coastguard Worker 
238*e5436536SAndroid Build Coastguard Worker   /* compare bitstream data */
239*e5436536SAndroid Build Coastguard Worker   result |=
240*e5436536SAndroid Build Coastguard Worker       FDKmemcmp(&hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS));
241*e5436536SAndroid Build Coastguard Worker   result |=
242*e5436536SAndroid Build Coastguard Worker       FDKmemcmp(&hHdr1->bs_dflt, &hHdr2->bs_dflt, sizeof(SBR_HEADER_DATA_BS));
243*e5436536SAndroid Build Coastguard Worker   result |= FDKmemcmp(&hHdr1->bs_info, &hHdr2->bs_info,
244*e5436536SAndroid Build Coastguard Worker                       sizeof(SBR_HEADER_DATA_BS_INFO));
245*e5436536SAndroid Build Coastguard Worker 
246*e5436536SAndroid Build Coastguard Worker   /* compare frequency band data */
247*e5436536SAndroid Build Coastguard Worker   result |= FDKmemcmp(&hHdr1->freqBandData, &hHdr2->freqBandData,
248*e5436536SAndroid Build Coastguard Worker                       (8 + MAX_NUM_LIMITERS + 1) * sizeof(UCHAR));
249*e5436536SAndroid Build Coastguard Worker   result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableLo,
250*e5436536SAndroid Build Coastguard Worker                       hHdr2->freqBandData.freqBandTableLo,
251*e5436536SAndroid Build Coastguard Worker                       (MAX_FREQ_COEFFS / 2 + 1) * sizeof(UCHAR));
252*e5436536SAndroid Build Coastguard Worker   result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableHi,
253*e5436536SAndroid Build Coastguard Worker                       hHdr2->freqBandData.freqBandTableHi,
254*e5436536SAndroid Build Coastguard Worker                       (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR));
255*e5436536SAndroid Build Coastguard Worker   result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableNoise,
256*e5436536SAndroid Build Coastguard Worker                       hHdr2->freqBandData.freqBandTableNoise,
257*e5436536SAndroid Build Coastguard Worker                       (MAX_NOISE_COEFFS + 1) * sizeof(UCHAR));
258*e5436536SAndroid Build Coastguard Worker   result |=
259*e5436536SAndroid Build Coastguard Worker       FDKmemcmp(hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master,
260*e5436536SAndroid Build Coastguard Worker                 (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR));
261*e5436536SAndroid Build Coastguard Worker 
262*e5436536SAndroid Build Coastguard Worker   return result;
263*e5436536SAndroid Build Coastguard Worker }
264*e5436536SAndroid Build Coastguard Worker 
265*e5436536SAndroid Build Coastguard Worker /*!
266*e5436536SAndroid Build Coastguard Worker   \brief Reset SBR decoder.
267*e5436536SAndroid Build Coastguard Worker 
268*e5436536SAndroid Build Coastguard Worker   Reset should only be called if SBR has been sucessfully detected by
269*e5436536SAndroid Build Coastguard Worker   an appropriate checkForPayload() function.
270*e5436536SAndroid Build Coastguard Worker 
271*e5436536SAndroid Build Coastguard Worker   \return Error code.
272*e5436536SAndroid Build Coastguard Worker */
sbrDecoder_ResetElement(HANDLE_SBRDECODER self,int sampleRateIn,int sampleRateOut,int samplesPerFrame,const MP4_ELEMENT_ID elementID,const int elementIndex,const int overlap)273*e5436536SAndroid Build Coastguard Worker static SBR_ERROR sbrDecoder_ResetElement(HANDLE_SBRDECODER self,
274*e5436536SAndroid Build Coastguard Worker                                          int sampleRateIn, int sampleRateOut,
275*e5436536SAndroid Build Coastguard Worker                                          int samplesPerFrame,
276*e5436536SAndroid Build Coastguard Worker                                          const MP4_ELEMENT_ID elementID,
277*e5436536SAndroid Build Coastguard Worker                                          const int elementIndex,
278*e5436536SAndroid Build Coastguard Worker                                          const int overlap) {
279*e5436536SAndroid Build Coastguard Worker   SBR_ERROR sbrError = SBRDEC_OK;
280*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_HEADER_DATA hSbrHeader;
281*e5436536SAndroid Build Coastguard Worker   UINT qmfFlags = 0;
282*e5436536SAndroid Build Coastguard Worker 
283*e5436536SAndroid Build Coastguard Worker   int i, synDownsampleFac;
284*e5436536SAndroid Build Coastguard Worker 
285*e5436536SAndroid Build Coastguard Worker   /* USAC: assuming theoretical case 8 kHz output sample rate with 4:1 SBR */
286*e5436536SAndroid Build Coastguard Worker   const int sbr_min_sample_rate_in = IS_USAC(self->coreCodec) ? 2000 : 6400;
287*e5436536SAndroid Build Coastguard Worker 
288*e5436536SAndroid Build Coastguard Worker   /* Check in/out samplerates */
289*e5436536SAndroid Build Coastguard Worker   if (sampleRateIn < sbr_min_sample_rate_in || sampleRateIn > (96000)) {
290*e5436536SAndroid Build Coastguard Worker     sbrError = SBRDEC_UNSUPPORTED_CONFIG;
291*e5436536SAndroid Build Coastguard Worker     goto bail;
292*e5436536SAndroid Build Coastguard Worker   }
293*e5436536SAndroid Build Coastguard Worker 
294*e5436536SAndroid Build Coastguard Worker   if (sampleRateOut > (96000)) {
295*e5436536SAndroid Build Coastguard Worker     sbrError = SBRDEC_UNSUPPORTED_CONFIG;
296*e5436536SAndroid Build Coastguard Worker     goto bail;
297*e5436536SAndroid Build Coastguard Worker   }
298*e5436536SAndroid Build Coastguard Worker 
299*e5436536SAndroid Build Coastguard Worker   /* Set QMF mode flags */
300*e5436536SAndroid Build Coastguard Worker   if (self->flags & SBRDEC_LOW_POWER) qmfFlags |= QMF_FLAG_LP;
301*e5436536SAndroid Build Coastguard Worker 
302*e5436536SAndroid Build Coastguard Worker   if (self->coreCodec == AOT_ER_AAC_ELD) {
303*e5436536SAndroid Build Coastguard Worker     if (self->flags & SBRDEC_LD_MPS_QMF) {
304*e5436536SAndroid Build Coastguard Worker       qmfFlags |= QMF_FLAG_MPSLDFB;
305*e5436536SAndroid Build Coastguard Worker     } else {
306*e5436536SAndroid Build Coastguard Worker       qmfFlags |= QMF_FLAG_CLDFB;
307*e5436536SAndroid Build Coastguard Worker     }
308*e5436536SAndroid Build Coastguard Worker   }
309*e5436536SAndroid Build Coastguard Worker 
310*e5436536SAndroid Build Coastguard Worker   /* Set downsampling factor for synthesis filter bank */
311*e5436536SAndroid Build Coastguard Worker   if (sampleRateOut == 0) {
312*e5436536SAndroid Build Coastguard Worker     /* no single rate mode */
313*e5436536SAndroid Build Coastguard Worker     sampleRateOut =
314*e5436536SAndroid Build Coastguard Worker         sampleRateIn
315*e5436536SAndroid Build Coastguard Worker         << 1; /* In case of implicit signalling, assume dual rate SBR */
316*e5436536SAndroid Build Coastguard Worker   }
317*e5436536SAndroid Build Coastguard Worker 
318*e5436536SAndroid Build Coastguard Worker   if (sampleRateIn == sampleRateOut) {
319*e5436536SAndroid Build Coastguard Worker     synDownsampleFac = 2;
320*e5436536SAndroid Build Coastguard Worker     self->flags |= SBRDEC_DOWNSAMPLE;
321*e5436536SAndroid Build Coastguard Worker   } else {
322*e5436536SAndroid Build Coastguard Worker     synDownsampleFac = 1;
323*e5436536SAndroid Build Coastguard Worker     self->flags &= ~SBRDEC_DOWNSAMPLE;
324*e5436536SAndroid Build Coastguard Worker   }
325*e5436536SAndroid Build Coastguard Worker 
326*e5436536SAndroid Build Coastguard Worker   self->synDownsampleFac = synDownsampleFac;
327*e5436536SAndroid Build Coastguard Worker   self->sampleRateOut = sampleRateOut;
328*e5436536SAndroid Build Coastguard Worker 
329*e5436536SAndroid Build Coastguard Worker   {
330*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < (1) + 1; i++) {
331*e5436536SAndroid Build Coastguard Worker       int setDflt;
332*e5436536SAndroid Build Coastguard Worker       hSbrHeader = &(self->sbrHeader[elementIndex][i]);
333*e5436536SAndroid Build Coastguard Worker       setDflt = ((hSbrHeader->syncState == SBR_NOT_INITIALIZED) ||
334*e5436536SAndroid Build Coastguard Worker                  (self->flags & SBRDEC_FORCE_RESET))
335*e5436536SAndroid Build Coastguard Worker                     ? 1
336*e5436536SAndroid Build Coastguard Worker                     : 0;
337*e5436536SAndroid Build Coastguard Worker 
338*e5436536SAndroid Build Coastguard Worker       /* init a default header such that we can at least do upsampling later */
339*e5436536SAndroid Build Coastguard Worker       sbrError = initHeaderData(hSbrHeader, sampleRateIn, sampleRateOut,
340*e5436536SAndroid Build Coastguard Worker                                 self->downscaleFactor, samplesPerFrame,
341*e5436536SAndroid Build Coastguard Worker                                 self->flags, setDflt);
342*e5436536SAndroid Build Coastguard Worker 
343*e5436536SAndroid Build Coastguard Worker       /* Set synchState to UPSAMPLING in case it already is initialized */
344*e5436536SAndroid Build Coastguard Worker       hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING
345*e5436536SAndroid Build Coastguard Worker                                   ? UPSAMPLING
346*e5436536SAndroid Build Coastguard Worker                                   : hSbrHeader->syncState;
347*e5436536SAndroid Build Coastguard Worker     }
348*e5436536SAndroid Build Coastguard Worker   }
349*e5436536SAndroid Build Coastguard Worker 
350*e5436536SAndroid Build Coastguard Worker   if (sbrError != SBRDEC_OK) {
351*e5436536SAndroid Build Coastguard Worker     goto bail;
352*e5436536SAndroid Build Coastguard Worker   }
353*e5436536SAndroid Build Coastguard Worker 
354*e5436536SAndroid Build Coastguard Worker   if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) {
355*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.flags_requested |= qmfFlags;
356*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nBandsAnalysis_requested =
357*e5436536SAndroid Build Coastguard Worker         self->sbrHeader[elementIndex][0].numberOfAnalysisBands;
358*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nBandsSynthesis_requested =
359*e5436536SAndroid Build Coastguard Worker         (synDownsampleFac == 1) ? 64 : 32; /* may be overwritten by MPS */
360*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nBandsSynthesis_requested /=
361*e5436536SAndroid Build Coastguard Worker         self->downscaleFactor;
362*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nQmfTimeSlots_requested =
363*e5436536SAndroid Build Coastguard Worker         self->sbrHeader[elementIndex][0].numberTimeSlots *
364*e5436536SAndroid Build Coastguard Worker         self->sbrHeader[elementIndex][0].timeStep;
365*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nQmfOvTimeSlots_requested = overlap;
366*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nQmfProcBands_requested = 64; /* always 64 */
367*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nQmfProcChannels_requested =
368*e5436536SAndroid Build Coastguard Worker         1; /* may be overwritten by MPS */
369*e5436536SAndroid Build Coastguard Worker   }
370*e5436536SAndroid Build Coastguard Worker 
371*e5436536SAndroid Build Coastguard Worker   /* Init SBR channels going to be assigned to a SBR element */
372*e5436536SAndroid Build Coastguard Worker   {
373*e5436536SAndroid Build Coastguard Worker     int ch;
374*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < self->pSbrElement[elementIndex]->nChannels; ch++) {
375*e5436536SAndroid Build Coastguard Worker       int headerIndex =
376*e5436536SAndroid Build Coastguard Worker           getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
377*e5436536SAndroid Build Coastguard Worker                         self->pSbrElement[elementIndex]->useHeaderSlot);
378*e5436536SAndroid Build Coastguard Worker 
379*e5436536SAndroid Build Coastguard Worker       /* and create sbrDec */
380*e5436536SAndroid Build Coastguard Worker       sbrError =
381*e5436536SAndroid Build Coastguard Worker           createSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch],
382*e5436536SAndroid Build Coastguard Worker                        &self->sbrHeader[elementIndex][headerIndex],
383*e5436536SAndroid Build Coastguard Worker                        &self->pSbrElement[elementIndex]->transposerSettings,
384*e5436536SAndroid Build Coastguard Worker                        synDownsampleFac, qmfFlags, self->flags, overlap, ch,
385*e5436536SAndroid Build Coastguard Worker                        self->codecFrameSize);
386*e5436536SAndroid Build Coastguard Worker 
387*e5436536SAndroid Build Coastguard Worker       if (sbrError != SBRDEC_OK) {
388*e5436536SAndroid Build Coastguard Worker         goto bail;
389*e5436536SAndroid Build Coastguard Worker       }
390*e5436536SAndroid Build Coastguard Worker     }
391*e5436536SAndroid Build Coastguard Worker   }
392*e5436536SAndroid Build Coastguard Worker 
393*e5436536SAndroid Build Coastguard Worker   // FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer));
394*e5436536SAndroid Build Coastguard Worker 
395*e5436536SAndroid Build Coastguard Worker   if (self->numSbrElements == 1) {
396*e5436536SAndroid Build Coastguard Worker     switch (self->coreCodec) {
397*e5436536SAndroid Build Coastguard Worker       case AOT_AAC_LC:
398*e5436536SAndroid Build Coastguard Worker       case AOT_SBR:
399*e5436536SAndroid Build Coastguard Worker       case AOT_PS:
400*e5436536SAndroid Build Coastguard Worker       case AOT_ER_AAC_SCAL:
401*e5436536SAndroid Build Coastguard Worker       case AOT_DRM_AAC:
402*e5436536SAndroid Build Coastguard Worker       case AOT_DRM_SURROUND:
403*e5436536SAndroid Build Coastguard Worker         if (CreatePsDec(&self->hParametricStereoDec, samplesPerFrame)) {
404*e5436536SAndroid Build Coastguard Worker           sbrError = SBRDEC_CREATE_ERROR;
405*e5436536SAndroid Build Coastguard Worker           goto bail;
406*e5436536SAndroid Build Coastguard Worker         }
407*e5436536SAndroid Build Coastguard Worker         break;
408*e5436536SAndroid Build Coastguard Worker       default:
409*e5436536SAndroid Build Coastguard Worker         break;
410*e5436536SAndroid Build Coastguard Worker     }
411*e5436536SAndroid Build Coastguard Worker   }
412*e5436536SAndroid Build Coastguard Worker 
413*e5436536SAndroid Build Coastguard Worker   /* Init frame delay slot handling */
414*e5436536SAndroid Build Coastguard Worker   self->pSbrElement[elementIndex]->useFrameSlot = 0;
415*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < ((1) + 1); i++) {
416*e5436536SAndroid Build Coastguard Worker     self->pSbrElement[elementIndex]->useHeaderSlot[i] = i;
417*e5436536SAndroid Build Coastguard Worker   }
418*e5436536SAndroid Build Coastguard Worker 
419*e5436536SAndroid Build Coastguard Worker bail:
420*e5436536SAndroid Build Coastguard Worker 
421*e5436536SAndroid Build Coastguard Worker   return sbrError;
422*e5436536SAndroid Build Coastguard Worker }
423*e5436536SAndroid Build Coastguard Worker 
424*e5436536SAndroid Build Coastguard Worker /*!
425*e5436536SAndroid Build Coastguard Worker   \brief Assign QMF domain provided QMF channels to SBR channels.
426*e5436536SAndroid Build Coastguard Worker 
427*e5436536SAndroid Build Coastguard Worker   \return void
428*e5436536SAndroid Build Coastguard Worker */
sbrDecoder_AssignQmfChannels2SbrChannels(HANDLE_SBRDECODER self)429*e5436536SAndroid Build Coastguard Worker static void sbrDecoder_AssignQmfChannels2SbrChannels(HANDLE_SBRDECODER self) {
430*e5436536SAndroid Build Coastguard Worker   int ch, el, absCh_offset = 0;
431*e5436536SAndroid Build Coastguard Worker   for (el = 0; el < self->numSbrElements; el++) {
432*e5436536SAndroid Build Coastguard Worker     if (self->pSbrElement[el] != NULL) {
433*e5436536SAndroid Build Coastguard Worker       for (ch = 0; ch < self->pSbrElement[el]->nChannels; ch++) {
434*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(((absCh_offset + ch) < ((8) + (1))) &&
435*e5436536SAndroid Build Coastguard Worker                    ((absCh_offset + ch) < ((8) + (1))));
436*e5436536SAndroid Build Coastguard Worker         self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainInCh =
437*e5436536SAndroid Build Coastguard Worker             &self->pQmfDomain->QmfDomainIn[absCh_offset + ch];
438*e5436536SAndroid Build Coastguard Worker         self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainOutCh =
439*e5436536SAndroid Build Coastguard Worker             &self->pQmfDomain->QmfDomainOut[absCh_offset + ch];
440*e5436536SAndroid Build Coastguard Worker       }
441*e5436536SAndroid Build Coastguard Worker       absCh_offset += self->pSbrElement[el]->nChannels;
442*e5436536SAndroid Build Coastguard Worker     }
443*e5436536SAndroid Build Coastguard Worker   }
444*e5436536SAndroid Build Coastguard Worker }
445*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_Open(HANDLE_SBRDECODER * pSelf,HANDLE_FDK_QMF_DOMAIN pQmfDomain)446*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf,
447*e5436536SAndroid Build Coastguard Worker                           HANDLE_FDK_QMF_DOMAIN pQmfDomain) {
448*e5436536SAndroid Build Coastguard Worker   HANDLE_SBRDECODER self = NULL;
449*e5436536SAndroid Build Coastguard Worker   SBR_ERROR sbrError = SBRDEC_OK;
450*e5436536SAndroid Build Coastguard Worker   int elIdx;
451*e5436536SAndroid Build Coastguard Worker 
452*e5436536SAndroid Build Coastguard Worker   if ((pSelf == NULL) || (pQmfDomain == NULL)) {
453*e5436536SAndroid Build Coastguard Worker     return SBRDEC_INVALID_ARGUMENT;
454*e5436536SAndroid Build Coastguard Worker   }
455*e5436536SAndroid Build Coastguard Worker 
456*e5436536SAndroid Build Coastguard Worker   /* Get memory for this instance */
457*e5436536SAndroid Build Coastguard Worker   self = GetRam_SbrDecoder();
458*e5436536SAndroid Build Coastguard Worker   if (self == NULL) {
459*e5436536SAndroid Build Coastguard Worker     sbrError = SBRDEC_MEM_ALLOC_FAILED;
460*e5436536SAndroid Build Coastguard Worker     goto bail;
461*e5436536SAndroid Build Coastguard Worker   }
462*e5436536SAndroid Build Coastguard Worker 
463*e5436536SAndroid Build Coastguard Worker   self->pQmfDomain = pQmfDomain;
464*e5436536SAndroid Build Coastguard Worker 
465*e5436536SAndroid Build Coastguard Worker   /*
466*e5436536SAndroid Build Coastguard Worker   Already zero because of calloc
467*e5436536SAndroid Build Coastguard Worker   self->numSbrElements = 0;
468*e5436536SAndroid Build Coastguard Worker   self->numSbrChannels = 0;
469*e5436536SAndroid Build Coastguard Worker   self->codecFrameSize = 0;
470*e5436536SAndroid Build Coastguard Worker   */
471*e5436536SAndroid Build Coastguard Worker 
472*e5436536SAndroid Build Coastguard Worker   self->numDelayFrames = (1); /* set to the max value by default */
473*e5436536SAndroid Build Coastguard Worker 
474*e5436536SAndroid Build Coastguard Worker   /* Initialize header sync state */
475*e5436536SAndroid Build Coastguard Worker   for (elIdx = 0; elIdx < (8); elIdx += 1) {
476*e5436536SAndroid Build Coastguard Worker     int i;
477*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < (1) + 1; i += 1) {
478*e5436536SAndroid Build Coastguard Worker       self->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED;
479*e5436536SAndroid Build Coastguard Worker     }
480*e5436536SAndroid Build Coastguard Worker   }
481*e5436536SAndroid Build Coastguard Worker 
482*e5436536SAndroid Build Coastguard Worker   *pSelf = self;
483*e5436536SAndroid Build Coastguard Worker 
484*e5436536SAndroid Build Coastguard Worker bail:
485*e5436536SAndroid Build Coastguard Worker   return sbrError;
486*e5436536SAndroid Build Coastguard Worker }
487*e5436536SAndroid Build Coastguard Worker 
488*e5436536SAndroid Build Coastguard Worker /**
489*e5436536SAndroid Build Coastguard Worker  * \brief determine if the given core codec AOT can be processed or not.
490*e5436536SAndroid Build Coastguard Worker  * \param coreCodec core codec audio object type.
491*e5436536SAndroid Build Coastguard Worker  * \return 1 if SBR can be processed, 0 if SBR cannot be processed/applied.
492*e5436536SAndroid Build Coastguard Worker  */
sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec)493*e5436536SAndroid Build Coastguard Worker static int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) {
494*e5436536SAndroid Build Coastguard Worker   switch (coreCodec) {
495*e5436536SAndroid Build Coastguard Worker     case AOT_AAC_LC:
496*e5436536SAndroid Build Coastguard Worker     case AOT_SBR:
497*e5436536SAndroid Build Coastguard Worker     case AOT_PS:
498*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_SCAL:
499*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_ELD:
500*e5436536SAndroid Build Coastguard Worker     case AOT_DRM_AAC:
501*e5436536SAndroid Build Coastguard Worker     case AOT_DRM_SURROUND:
502*e5436536SAndroid Build Coastguard Worker     case AOT_USAC:
503*e5436536SAndroid Build Coastguard Worker       return 1;
504*e5436536SAndroid Build Coastguard Worker     default:
505*e5436536SAndroid Build Coastguard Worker       return 0;
506*e5436536SAndroid Build Coastguard Worker   }
507*e5436536SAndroid Build Coastguard Worker }
508*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_DestroyElement(HANDLE_SBRDECODER self,const int elementIndex)509*e5436536SAndroid Build Coastguard Worker static void sbrDecoder_DestroyElement(HANDLE_SBRDECODER self,
510*e5436536SAndroid Build Coastguard Worker                                       const int elementIndex) {
511*e5436536SAndroid Build Coastguard Worker   if (self->pSbrElement[elementIndex] != NULL) {
512*e5436536SAndroid Build Coastguard Worker     int ch;
513*e5436536SAndroid Build Coastguard Worker 
514*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < SBRDEC_MAX_CH_PER_ELEMENT; ch++) {
515*e5436536SAndroid Build Coastguard Worker       if (self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) {
516*e5436536SAndroid Build Coastguard Worker         deleteSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch]);
517*e5436536SAndroid Build Coastguard Worker         FreeRam_SbrDecChannel(
518*e5436536SAndroid Build Coastguard Worker             &self->pSbrElement[elementIndex]->pSbrChannel[ch]);
519*e5436536SAndroid Build Coastguard Worker         self->numSbrChannels -= 1;
520*e5436536SAndroid Build Coastguard Worker       }
521*e5436536SAndroid Build Coastguard Worker     }
522*e5436536SAndroid Build Coastguard Worker     FreeRam_SbrDecElement(&self->pSbrElement[elementIndex]);
523*e5436536SAndroid Build Coastguard Worker     self->numSbrElements -= 1;
524*e5436536SAndroid Build Coastguard Worker   }
525*e5436536SAndroid Build Coastguard Worker }
526*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_InitElement(HANDLE_SBRDECODER self,const int sampleRateIn,const int sampleRateOut,const int samplesPerFrame,const AUDIO_OBJECT_TYPE coreCodec,const MP4_ELEMENT_ID elementID,const int elementIndex,const UCHAR harmonicSBR,const UCHAR stereoConfigIndex,const UCHAR configMode,UCHAR * configChanged,const INT downscaleFactor)527*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_InitElement(
528*e5436536SAndroid Build Coastguard Worker     HANDLE_SBRDECODER self, const int sampleRateIn, const int sampleRateOut,
529*e5436536SAndroid Build Coastguard Worker     const int samplesPerFrame, const AUDIO_OBJECT_TYPE coreCodec,
530*e5436536SAndroid Build Coastguard Worker     const MP4_ELEMENT_ID elementID, const int elementIndex,
531*e5436536SAndroid Build Coastguard Worker     const UCHAR harmonicSBR, const UCHAR stereoConfigIndex,
532*e5436536SAndroid Build Coastguard Worker     const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor) {
533*e5436536SAndroid Build Coastguard Worker   SBR_ERROR sbrError = SBRDEC_OK;
534*e5436536SAndroid Build Coastguard Worker   int chCnt = 0;
535*e5436536SAndroid Build Coastguard Worker   int nSbrElementsStart;
536*e5436536SAndroid Build Coastguard Worker   int nSbrChannelsStart;
537*e5436536SAndroid Build Coastguard Worker   if (self == NULL) {
538*e5436536SAndroid Build Coastguard Worker     return SBRDEC_INVALID_ARGUMENT;
539*e5436536SAndroid Build Coastguard Worker   }
540*e5436536SAndroid Build Coastguard Worker 
541*e5436536SAndroid Build Coastguard Worker   nSbrElementsStart = self->numSbrElements;
542*e5436536SAndroid Build Coastguard Worker   nSbrChannelsStart = self->numSbrChannels;
543*e5436536SAndroid Build Coastguard Worker 
544*e5436536SAndroid Build Coastguard Worker   /* Check core codec AOT */
545*e5436536SAndroid Build Coastguard Worker   if (!sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) {
546*e5436536SAndroid Build Coastguard Worker     sbrError = SBRDEC_UNSUPPORTED_CONFIG;
547*e5436536SAndroid Build Coastguard Worker     goto bail;
548*e5436536SAndroid Build Coastguard Worker   }
549*e5436536SAndroid Build Coastguard Worker 
550*e5436536SAndroid Build Coastguard Worker   if (elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE) {
551*e5436536SAndroid Build Coastguard Worker     sbrError = SBRDEC_UNSUPPORTED_CONFIG;
552*e5436536SAndroid Build Coastguard Worker     goto bail;
553*e5436536SAndroid Build Coastguard Worker   }
554*e5436536SAndroid Build Coastguard Worker 
555*e5436536SAndroid Build Coastguard Worker   if (self->sampleRateIn == sampleRateIn &&
556*e5436536SAndroid Build Coastguard Worker       self->codecFrameSize == samplesPerFrame && self->coreCodec == coreCodec &&
557*e5436536SAndroid Build Coastguard Worker       self->pSbrElement[elementIndex] != NULL &&
558*e5436536SAndroid Build Coastguard Worker       self->pSbrElement[elementIndex]->elementID == elementID &&
559*e5436536SAndroid Build Coastguard Worker       !(self->flags & SBRDEC_FORCE_RESET) &&
560*e5436536SAndroid Build Coastguard Worker       ((sampleRateOut == 0) ? 1 : (self->sampleRateOut == sampleRateOut)) &&
561*e5436536SAndroid Build Coastguard Worker       ((harmonicSBR == 2) ? 1
562*e5436536SAndroid Build Coastguard Worker                           : (self->harmonicSBR ==
563*e5436536SAndroid Build Coastguard Worker                              harmonicSBR)) /* The value 2 signalizes that
564*e5436536SAndroid Build Coastguard Worker                                               harmonicSBR shall be ignored in
565*e5436536SAndroid Build Coastguard Worker                                               the config change detection */
566*e5436536SAndroid Build Coastguard Worker   ) {
567*e5436536SAndroid Build Coastguard Worker     /* Nothing to do */
568*e5436536SAndroid Build Coastguard Worker     return SBRDEC_OK;
569*e5436536SAndroid Build Coastguard Worker   } else {
570*e5436536SAndroid Build Coastguard Worker     if (configMode & AC_CM_DET_CFG_CHANGE) {
571*e5436536SAndroid Build Coastguard Worker       *configChanged = 1;
572*e5436536SAndroid Build Coastguard Worker     }
573*e5436536SAndroid Build Coastguard Worker   }
574*e5436536SAndroid Build Coastguard Worker 
575*e5436536SAndroid Build Coastguard Worker   /* reaching this point the SBR-decoder gets (re-)configured */
576*e5436536SAndroid Build Coastguard Worker 
577*e5436536SAndroid Build Coastguard Worker   /* The flags field is used for all elements! */
578*e5436536SAndroid Build Coastguard Worker   self->flags &=
579*e5436536SAndroid Build Coastguard Worker       (SBRDEC_FORCE_RESET | SBRDEC_FLUSH); /* Keep the global flags. They will
580*e5436536SAndroid Build Coastguard Worker                                               be reset after decoding. */
581*e5436536SAndroid Build Coastguard Worker   self->flags |= (downscaleFactor > 1) ? SBRDEC_ELD_DOWNSCALE : 0;
582*e5436536SAndroid Build Coastguard Worker   self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0;
583*e5436536SAndroid Build Coastguard Worker   self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0;
584*e5436536SAndroid Build Coastguard Worker   self->flags |=
585*e5436536SAndroid Build Coastguard Worker       (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM : 0;
586*e5436536SAndroid Build Coastguard Worker   self->flags |= (coreCodec == AOT_DRM_SURROUND)
587*e5436536SAndroid Build Coastguard Worker                      ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM
588*e5436536SAndroid Build Coastguard Worker                      : 0;
589*e5436536SAndroid Build Coastguard Worker   self->flags |= (coreCodec == AOT_USAC) ? SBRDEC_SYNTAX_USAC : 0;
590*e5436536SAndroid Build Coastguard Worker   /* Robustness: Take integer division rounding into consideration. E.g. 22050
591*e5436536SAndroid Build Coastguard Worker    * Hz with 4:1 SBR => 5512 Hz core sampling rate. */
592*e5436536SAndroid Build Coastguard Worker   self->flags |= (sampleRateIn == sampleRateOut / 4) ? SBRDEC_QUAD_RATE : 0;
593*e5436536SAndroid Build Coastguard Worker   self->flags |= (harmonicSBR == 1) ? SBRDEC_USAC_HARMONICSBR : 0;
594*e5436536SAndroid Build Coastguard Worker 
595*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_DET_CFG_CHANGE) {
596*e5436536SAndroid Build Coastguard Worker     return SBRDEC_OK;
597*e5436536SAndroid Build Coastguard Worker   }
598*e5436536SAndroid Build Coastguard Worker 
599*e5436536SAndroid Build Coastguard Worker   self->sampleRateIn = sampleRateIn;
600*e5436536SAndroid Build Coastguard Worker   self->codecFrameSize = samplesPerFrame;
601*e5436536SAndroid Build Coastguard Worker   self->coreCodec = coreCodec;
602*e5436536SAndroid Build Coastguard Worker   self->harmonicSBR = harmonicSBR;
603*e5436536SAndroid Build Coastguard Worker   self->downscaleFactor = downscaleFactor;
604*e5436536SAndroid Build Coastguard Worker 
605*e5436536SAndroid Build Coastguard Worker   /* Init SBR elements */
606*e5436536SAndroid Build Coastguard Worker   {
607*e5436536SAndroid Build Coastguard Worker     int elChannels, ch;
608*e5436536SAndroid Build Coastguard Worker 
609*e5436536SAndroid Build Coastguard Worker     if (self->pSbrElement[elementIndex] == NULL) {
610*e5436536SAndroid Build Coastguard Worker       self->pSbrElement[elementIndex] = GetRam_SbrDecElement(elementIndex);
611*e5436536SAndroid Build Coastguard Worker       if (self->pSbrElement[elementIndex] == NULL) {
612*e5436536SAndroid Build Coastguard Worker         sbrError = SBRDEC_MEM_ALLOC_FAILED;
613*e5436536SAndroid Build Coastguard Worker         goto bail;
614*e5436536SAndroid Build Coastguard Worker       }
615*e5436536SAndroid Build Coastguard Worker       self->numSbrElements++;
616*e5436536SAndroid Build Coastguard Worker     } else {
617*e5436536SAndroid Build Coastguard Worker       self->numSbrChannels -= self->pSbrElement[elementIndex]->nChannels;
618*e5436536SAndroid Build Coastguard Worker     }
619*e5436536SAndroid Build Coastguard Worker 
620*e5436536SAndroid Build Coastguard Worker     /* Determine amount of channels for this element */
621*e5436536SAndroid Build Coastguard Worker     switch (elementID) {
622*e5436536SAndroid Build Coastguard Worker       case ID_NONE:
623*e5436536SAndroid Build Coastguard Worker       case ID_CPE:
624*e5436536SAndroid Build Coastguard Worker         elChannels = 2;
625*e5436536SAndroid Build Coastguard Worker         break;
626*e5436536SAndroid Build Coastguard Worker       case ID_LFE:
627*e5436536SAndroid Build Coastguard Worker       case ID_SCE:
628*e5436536SAndroid Build Coastguard Worker         elChannels = 1;
629*e5436536SAndroid Build Coastguard Worker         break;
630*e5436536SAndroid Build Coastguard Worker       default:
631*e5436536SAndroid Build Coastguard Worker         elChannels = 0;
632*e5436536SAndroid Build Coastguard Worker         break;
633*e5436536SAndroid Build Coastguard Worker     }
634*e5436536SAndroid Build Coastguard Worker 
635*e5436536SAndroid Build Coastguard Worker     /* Handle case of Parametric Stereo */
636*e5436536SAndroid Build Coastguard Worker     if (elementIndex == 0 && elementID == ID_SCE) {
637*e5436536SAndroid Build Coastguard Worker       switch (coreCodec) {
638*e5436536SAndroid Build Coastguard Worker         case AOT_AAC_LC:
639*e5436536SAndroid Build Coastguard Worker         case AOT_SBR:
640*e5436536SAndroid Build Coastguard Worker         case AOT_PS:
641*e5436536SAndroid Build Coastguard Worker         case AOT_ER_AAC_SCAL:
642*e5436536SAndroid Build Coastguard Worker         case AOT_DRM_AAC:
643*e5436536SAndroid Build Coastguard Worker         case AOT_DRM_SURROUND:
644*e5436536SAndroid Build Coastguard Worker           elChannels = 2;
645*e5436536SAndroid Build Coastguard Worker           break;
646*e5436536SAndroid Build Coastguard Worker         default:
647*e5436536SAndroid Build Coastguard Worker           break;
648*e5436536SAndroid Build Coastguard Worker       }
649*e5436536SAndroid Build Coastguard Worker     }
650*e5436536SAndroid Build Coastguard Worker 
651*e5436536SAndroid Build Coastguard Worker     /* Sanity check to avoid memory leaks */
652*e5436536SAndroid Build Coastguard Worker     if (elChannels < self->pSbrElement[elementIndex]->nChannels ||
653*e5436536SAndroid Build Coastguard Worker         (self->numSbrChannels + elChannels) > (8) + (1)) {
654*e5436536SAndroid Build Coastguard Worker       self->numSbrChannels += self->pSbrElement[elementIndex]->nChannels;
655*e5436536SAndroid Build Coastguard Worker       sbrError = SBRDEC_PARSE_ERROR;
656*e5436536SAndroid Build Coastguard Worker       goto bail;
657*e5436536SAndroid Build Coastguard Worker     }
658*e5436536SAndroid Build Coastguard Worker 
659*e5436536SAndroid Build Coastguard Worker     /* Save element ID for sanity checks and to have a fallback for concealment.
660*e5436536SAndroid Build Coastguard Worker      */
661*e5436536SAndroid Build Coastguard Worker     self->pSbrElement[elementIndex]->elementID = elementID;
662*e5436536SAndroid Build Coastguard Worker     self->pSbrElement[elementIndex]->nChannels = elChannels;
663*e5436536SAndroid Build Coastguard Worker 
664*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < elChannels; ch++) {
665*e5436536SAndroid Build Coastguard Worker       if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) {
666*e5436536SAndroid Build Coastguard Worker         self->pSbrElement[elementIndex]->pSbrChannel[ch] =
667*e5436536SAndroid Build Coastguard Worker             GetRam_SbrDecChannel(chCnt);
668*e5436536SAndroid Build Coastguard Worker         if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) {
669*e5436536SAndroid Build Coastguard Worker           sbrError = SBRDEC_MEM_ALLOC_FAILED;
670*e5436536SAndroid Build Coastguard Worker           goto bail;
671*e5436536SAndroid Build Coastguard Worker         }
672*e5436536SAndroid Build Coastguard Worker       }
673*e5436536SAndroid Build Coastguard Worker       self->numSbrChannels++;
674*e5436536SAndroid Build Coastguard Worker 
675*e5436536SAndroid Build Coastguard Worker       sbrDecoder_drcInitChannel(&self->pSbrElement[elementIndex]
676*e5436536SAndroid Build Coastguard Worker                                      ->pSbrChannel[ch]
677*e5436536SAndroid Build Coastguard Worker                                      ->SbrDec.sbrDrcChannel);
678*e5436536SAndroid Build Coastguard Worker 
679*e5436536SAndroid Build Coastguard Worker       chCnt++;
680*e5436536SAndroid Build Coastguard Worker     }
681*e5436536SAndroid Build Coastguard Worker   }
682*e5436536SAndroid Build Coastguard Worker 
683*e5436536SAndroid Build Coastguard Worker   if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) {
684*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nInputChannels_requested =
685*e5436536SAndroid Build Coastguard Worker         self->numSbrChannels;
686*e5436536SAndroid Build Coastguard Worker     self->pQmfDomain->globalConf.nOutputChannels_requested =
687*e5436536SAndroid Build Coastguard Worker         fMax((INT)self->numSbrChannels,
688*e5436536SAndroid Build Coastguard Worker              (INT)self->pQmfDomain->globalConf.nOutputChannels_requested);
689*e5436536SAndroid Build Coastguard Worker   }
690*e5436536SAndroid Build Coastguard Worker 
691*e5436536SAndroid Build Coastguard Worker   /* Make sure each SBR channel has one QMF channel assigned even if
692*e5436536SAndroid Build Coastguard Worker    * numSbrChannels or element set-up has changed. */
693*e5436536SAndroid Build Coastguard Worker   sbrDecoder_AssignQmfChannels2SbrChannels(self);
694*e5436536SAndroid Build Coastguard Worker 
695*e5436536SAndroid Build Coastguard Worker   /* clear error flags for all delay slots */
696*e5436536SAndroid Build Coastguard Worker   FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag,
697*e5436536SAndroid Build Coastguard Worker               ((1) + 1) * sizeof(UCHAR));
698*e5436536SAndroid Build Coastguard Worker 
699*e5436536SAndroid Build Coastguard Worker   {
700*e5436536SAndroid Build Coastguard Worker     int overlap;
701*e5436536SAndroid Build Coastguard Worker 
702*e5436536SAndroid Build Coastguard Worker     if (coreCodec == AOT_ER_AAC_ELD) {
703*e5436536SAndroid Build Coastguard Worker       overlap = 0;
704*e5436536SAndroid Build Coastguard Worker     } else if (self->flags & SBRDEC_QUAD_RATE) {
705*e5436536SAndroid Build Coastguard Worker       overlap = (3 * 4);
706*e5436536SAndroid Build Coastguard Worker     } else {
707*e5436536SAndroid Build Coastguard Worker       overlap = (3 * 2);
708*e5436536SAndroid Build Coastguard Worker     }
709*e5436536SAndroid Build Coastguard Worker     /* Initialize this instance */
710*e5436536SAndroid Build Coastguard Worker     sbrError = sbrDecoder_ResetElement(self, sampleRateIn, sampleRateOut,
711*e5436536SAndroid Build Coastguard Worker                                        samplesPerFrame, elementID, elementIndex,
712*e5436536SAndroid Build Coastguard Worker                                        overlap);
713*e5436536SAndroid Build Coastguard Worker   }
714*e5436536SAndroid Build Coastguard Worker 
715*e5436536SAndroid Build Coastguard Worker bail:
716*e5436536SAndroid Build Coastguard Worker   if (sbrError != SBRDEC_OK) {
717*e5436536SAndroid Build Coastguard Worker     if ((nSbrElementsStart < self->numSbrElements) ||
718*e5436536SAndroid Build Coastguard Worker         (nSbrChannelsStart < self->numSbrChannels)) {
719*e5436536SAndroid Build Coastguard Worker       /* Free the memory allocated for this element */
720*e5436536SAndroid Build Coastguard Worker       sbrDecoder_DestroyElement(self, elementIndex);
721*e5436536SAndroid Build Coastguard Worker     } else if ((elementIndex < (8)) &&
722*e5436536SAndroid Build Coastguard Worker                (self->pSbrElement[elementIndex] !=
723*e5436536SAndroid Build Coastguard Worker                 NULL)) { /* Set error flag to trigger concealment */
724*e5436536SAndroid Build Coastguard Worker       setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR);
725*e5436536SAndroid Build Coastguard Worker     }
726*e5436536SAndroid Build Coastguard Worker   }
727*e5436536SAndroid Build Coastguard Worker 
728*e5436536SAndroid Build Coastguard Worker   return sbrError;
729*e5436536SAndroid Build Coastguard Worker }
730*e5436536SAndroid Build Coastguard Worker 
731*e5436536SAndroid Build Coastguard Worker /**
732*e5436536SAndroid Build Coastguard Worker  * \brief Free config dependent SBR memory.
733*e5436536SAndroid Build Coastguard Worker  * \param self SBR decoder instance handle
734*e5436536SAndroid Build Coastguard Worker  */
sbrDecoder_FreeMem(HANDLE_SBRDECODER * self)735*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self) {
736*e5436536SAndroid Build Coastguard Worker   int i;
737*e5436536SAndroid Build Coastguard Worker   int elIdx;
738*e5436536SAndroid Build Coastguard Worker 
739*e5436536SAndroid Build Coastguard Worker   if (self != NULL && *self != NULL) {
740*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < (8); i++) {
741*e5436536SAndroid Build Coastguard Worker       sbrDecoder_DestroyElement(*self, i);
742*e5436536SAndroid Build Coastguard Worker     }
743*e5436536SAndroid Build Coastguard Worker 
744*e5436536SAndroid Build Coastguard Worker     for (elIdx = 0; elIdx < (8); elIdx += 1) {
745*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < (1) + 1; i += 1) {
746*e5436536SAndroid Build Coastguard Worker         (*self)->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED;
747*e5436536SAndroid Build Coastguard Worker       }
748*e5436536SAndroid Build Coastguard Worker     }
749*e5436536SAndroid Build Coastguard Worker   }
750*e5436536SAndroid Build Coastguard Worker 
751*e5436536SAndroid Build Coastguard Worker   return SBRDEC_OK;
752*e5436536SAndroid Build Coastguard Worker }
753*e5436536SAndroid Build Coastguard Worker 
754*e5436536SAndroid Build Coastguard Worker /**
755*e5436536SAndroid Build Coastguard Worker  * \brief Apply decoded SBR header for one element.
756*e5436536SAndroid Build Coastguard Worker  * \param self SBR decoder instance handle
757*e5436536SAndroid Build Coastguard Worker  * \param hSbrHeader SBR header handle to be processed.
758*e5436536SAndroid Build Coastguard Worker  * \param hSbrChannel pointer array to the SBR element channels corresponding to
759*e5436536SAndroid Build Coastguard Worker  * the SBR header.
760*e5436536SAndroid Build Coastguard Worker  * \param headerStatus header status value returned from SBR header parser.
761*e5436536SAndroid Build Coastguard Worker  * \param numElementChannels amount of channels for the SBR element whos header
762*e5436536SAndroid Build Coastguard Worker  * is to be processed.
763*e5436536SAndroid Build Coastguard Worker  */
sbrDecoder_HeaderUpdate(HANDLE_SBRDECODER self,HANDLE_SBR_HEADER_DATA hSbrHeader,SBR_HEADER_STATUS headerStatus,HANDLE_SBR_CHANNEL hSbrChannel[],const int numElementChannels)764*e5436536SAndroid Build Coastguard Worker static SBR_ERROR sbrDecoder_HeaderUpdate(HANDLE_SBRDECODER self,
765*e5436536SAndroid Build Coastguard Worker                                          HANDLE_SBR_HEADER_DATA hSbrHeader,
766*e5436536SAndroid Build Coastguard Worker                                          SBR_HEADER_STATUS headerStatus,
767*e5436536SAndroid Build Coastguard Worker                                          HANDLE_SBR_CHANNEL hSbrChannel[],
768*e5436536SAndroid Build Coastguard Worker                                          const int numElementChannels) {
769*e5436536SAndroid Build Coastguard Worker   SBR_ERROR errorStatus = SBRDEC_OK;
770*e5436536SAndroid Build Coastguard Worker 
771*e5436536SAndroid Build Coastguard Worker   /*
772*e5436536SAndroid Build Coastguard Worker     change of control data, reset decoder
773*e5436536SAndroid Build Coastguard Worker   */
774*e5436536SAndroid Build Coastguard Worker   errorStatus = resetFreqBandTables(hSbrHeader, self->flags);
775*e5436536SAndroid Build Coastguard Worker 
776*e5436536SAndroid Build Coastguard Worker   if (errorStatus == SBRDEC_OK) {
777*e5436536SAndroid Build Coastguard Worker     if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET) {
778*e5436536SAndroid Build Coastguard Worker #if (SBRDEC_MAX_HB_FADE_FRAMES > 0)
779*e5436536SAndroid Build Coastguard Worker       int ch;
780*e5436536SAndroid Build Coastguard Worker       for (ch = 0; ch < numElementChannels; ch += 1) {
781*e5436536SAndroid Build Coastguard Worker         hSbrChannel[ch]->SbrDec.highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES;
782*e5436536SAndroid Build Coastguard Worker       }
783*e5436536SAndroid Build Coastguard Worker 
784*e5436536SAndroid Build Coastguard Worker #endif
785*e5436536SAndroid Build Coastguard Worker       /* As the default header would limit the frequency range,
786*e5436536SAndroid Build Coastguard Worker          lowSubband and highSubband must be patched. */
787*e5436536SAndroid Build Coastguard Worker       hSbrHeader->freqBandData.lowSubband = hSbrHeader->numberOfAnalysisBands;
788*e5436536SAndroid Build Coastguard Worker       hSbrHeader->freqBandData.highSubband = hSbrHeader->numberOfAnalysisBands;
789*e5436536SAndroid Build Coastguard Worker     }
790*e5436536SAndroid Build Coastguard Worker 
791*e5436536SAndroid Build Coastguard Worker     /* Trigger a reset before processing this slot */
792*e5436536SAndroid Build Coastguard Worker     hSbrHeader->status |= SBRDEC_HDR_STAT_RESET;
793*e5436536SAndroid Build Coastguard Worker   }
794*e5436536SAndroid Build Coastguard Worker 
795*e5436536SAndroid Build Coastguard Worker   return errorStatus;
796*e5436536SAndroid Build Coastguard Worker }
797*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_Header(HANDLE_SBRDECODER self,HANDLE_FDK_BITSTREAM hBs,const INT sampleRateIn,const INT sampleRateOut,const INT samplesPerFrame,const AUDIO_OBJECT_TYPE coreCodec,const MP4_ELEMENT_ID elementID,const INT elementIndex,const UCHAR harmonicSBR,const UCHAR stereoConfigIndex,const UCHAR configMode,UCHAR * configChanged,const INT downscaleFactor)798*e5436536SAndroid Build Coastguard Worker INT sbrDecoder_Header(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs,
799*e5436536SAndroid Build Coastguard Worker                       const INT sampleRateIn, const INT sampleRateOut,
800*e5436536SAndroid Build Coastguard Worker                       const INT samplesPerFrame,
801*e5436536SAndroid Build Coastguard Worker                       const AUDIO_OBJECT_TYPE coreCodec,
802*e5436536SAndroid Build Coastguard Worker                       const MP4_ELEMENT_ID elementID, const INT elementIndex,
803*e5436536SAndroid Build Coastguard Worker                       const UCHAR harmonicSBR, const UCHAR stereoConfigIndex,
804*e5436536SAndroid Build Coastguard Worker                       const UCHAR configMode, UCHAR *configChanged,
805*e5436536SAndroid Build Coastguard Worker                       const INT downscaleFactor) {
806*e5436536SAndroid Build Coastguard Worker   SBR_HEADER_STATUS headerStatus;
807*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_HEADER_DATA hSbrHeader;
808*e5436536SAndroid Build Coastguard Worker   SBR_ERROR sbrError = SBRDEC_OK;
809*e5436536SAndroid Build Coastguard Worker   int headerIndex;
810*e5436536SAndroid Build Coastguard Worker   UINT flagsSaved =
811*e5436536SAndroid Build Coastguard Worker       0; /* flags should not be changed in AC_CM_DET_CFG_CHANGE - mode after
812*e5436536SAndroid Build Coastguard Worker             parsing */
813*e5436536SAndroid Build Coastguard Worker 
814*e5436536SAndroid Build Coastguard Worker   if (self == NULL || elementIndex >= (8)) {
815*e5436536SAndroid Build Coastguard Worker     return SBRDEC_UNSUPPORTED_CONFIG;
816*e5436536SAndroid Build Coastguard Worker   }
817*e5436536SAndroid Build Coastguard Worker 
818*e5436536SAndroid Build Coastguard Worker   if (!sbrDecoder_isCoreCodecValid(coreCodec)) {
819*e5436536SAndroid Build Coastguard Worker     return SBRDEC_UNSUPPORTED_CONFIG;
820*e5436536SAndroid Build Coastguard Worker   }
821*e5436536SAndroid Build Coastguard Worker 
822*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_DET_CFG_CHANGE) {
823*e5436536SAndroid Build Coastguard Worker     flagsSaved = self->flags; /* store */
824*e5436536SAndroid Build Coastguard Worker   }
825*e5436536SAndroid Build Coastguard Worker 
826*e5436536SAndroid Build Coastguard Worker   sbrError = sbrDecoder_InitElement(
827*e5436536SAndroid Build Coastguard Worker       self, sampleRateIn, sampleRateOut, samplesPerFrame, coreCodec, elementID,
828*e5436536SAndroid Build Coastguard Worker       elementIndex, harmonicSBR, stereoConfigIndex, configMode, configChanged,
829*e5436536SAndroid Build Coastguard Worker       downscaleFactor);
830*e5436536SAndroid Build Coastguard Worker 
831*e5436536SAndroid Build Coastguard Worker   if ((sbrError != SBRDEC_OK) || (elementID == ID_LFE)) {
832*e5436536SAndroid Build Coastguard Worker     goto bail;
833*e5436536SAndroid Build Coastguard Worker   }
834*e5436536SAndroid Build Coastguard Worker 
835*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_DET_CFG_CHANGE) {
836*e5436536SAndroid Build Coastguard Worker     hSbrHeader = NULL;
837*e5436536SAndroid Build Coastguard Worker   } else {
838*e5436536SAndroid Build Coastguard Worker     headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
839*e5436536SAndroid Build Coastguard Worker                                 self->pSbrElement[elementIndex]->useHeaderSlot);
840*e5436536SAndroid Build Coastguard Worker 
841*e5436536SAndroid Build Coastguard Worker     hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
842*e5436536SAndroid Build Coastguard Worker   }
843*e5436536SAndroid Build Coastguard Worker 
844*e5436536SAndroid Build Coastguard Worker   headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 0, configMode);
845*e5436536SAndroid Build Coastguard Worker 
846*e5436536SAndroid Build Coastguard Worker   if (coreCodec == AOT_USAC) {
847*e5436536SAndroid Build Coastguard Worker     if (configMode & AC_CM_DET_CFG_CHANGE) {
848*e5436536SAndroid Build Coastguard Worker       self->flags = flagsSaved; /* restore */
849*e5436536SAndroid Build Coastguard Worker     }
850*e5436536SAndroid Build Coastguard Worker     return sbrError;
851*e5436536SAndroid Build Coastguard Worker   }
852*e5436536SAndroid Build Coastguard Worker 
853*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_ALLOC_MEM) {
854*e5436536SAndroid Build Coastguard Worker     SBR_DECODER_ELEMENT *pSbrElement;
855*e5436536SAndroid Build Coastguard Worker 
856*e5436536SAndroid Build Coastguard Worker     pSbrElement = self->pSbrElement[elementIndex];
857*e5436536SAndroid Build Coastguard Worker 
858*e5436536SAndroid Build Coastguard Worker     /* Sanity check */
859*e5436536SAndroid Build Coastguard Worker     if (pSbrElement != NULL) {
860*e5436536SAndroid Build Coastguard Worker       if ((elementID == ID_CPE && pSbrElement->nChannels != 2) ||
861*e5436536SAndroid Build Coastguard Worker           (elementID != ID_CPE && pSbrElement->nChannels != 1)) {
862*e5436536SAndroid Build Coastguard Worker         return SBRDEC_UNSUPPORTED_CONFIG;
863*e5436536SAndroid Build Coastguard Worker       }
864*e5436536SAndroid Build Coastguard Worker       if (headerStatus == HEADER_RESET) {
865*e5436536SAndroid Build Coastguard Worker         sbrError = sbrDecoder_HeaderUpdate(self, hSbrHeader, headerStatus,
866*e5436536SAndroid Build Coastguard Worker                                            pSbrElement->pSbrChannel,
867*e5436536SAndroid Build Coastguard Worker                                            pSbrElement->nChannels);
868*e5436536SAndroid Build Coastguard Worker 
869*e5436536SAndroid Build Coastguard Worker         if (sbrError == SBRDEC_OK) {
870*e5436536SAndroid Build Coastguard Worker           hSbrHeader->syncState = SBR_HEADER;
871*e5436536SAndroid Build Coastguard Worker           hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
872*e5436536SAndroid Build Coastguard Worker         } else {
873*e5436536SAndroid Build Coastguard Worker           hSbrHeader->syncState = SBR_NOT_INITIALIZED;
874*e5436536SAndroid Build Coastguard Worker           hSbrHeader->status = HEADER_ERROR;
875*e5436536SAndroid Build Coastguard Worker         }
876*e5436536SAndroid Build Coastguard Worker       }
877*e5436536SAndroid Build Coastguard Worker     }
878*e5436536SAndroid Build Coastguard Worker   }
879*e5436536SAndroid Build Coastguard Worker bail:
880*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_DET_CFG_CHANGE) {
881*e5436536SAndroid Build Coastguard Worker     self->flags = flagsSaved; /* restore */
882*e5436536SAndroid Build Coastguard Worker   }
883*e5436536SAndroid Build Coastguard Worker   return sbrError;
884*e5436536SAndroid Build Coastguard Worker }
885*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_SetParam(HANDLE_SBRDECODER self,const SBRDEC_PARAM param,const INT value)886*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param,
887*e5436536SAndroid Build Coastguard Worker                               const INT value) {
888*e5436536SAndroid Build Coastguard Worker   SBR_ERROR errorStatus = SBRDEC_OK;
889*e5436536SAndroid Build Coastguard Worker 
890*e5436536SAndroid Build Coastguard Worker   /* configure the subsystems */
891*e5436536SAndroid Build Coastguard Worker   switch (param) {
892*e5436536SAndroid Build Coastguard Worker     case SBR_SYSTEM_BITSTREAM_DELAY:
893*e5436536SAndroid Build Coastguard Worker       if (value < 0 || value > (1)) {
894*e5436536SAndroid Build Coastguard Worker         errorStatus = SBRDEC_SET_PARAM_FAIL;
895*e5436536SAndroid Build Coastguard Worker         break;
896*e5436536SAndroid Build Coastguard Worker       }
897*e5436536SAndroid Build Coastguard Worker       if (self == NULL) {
898*e5436536SAndroid Build Coastguard Worker         errorStatus = SBRDEC_NOT_INITIALIZED;
899*e5436536SAndroid Build Coastguard Worker       } else {
900*e5436536SAndroid Build Coastguard Worker         self->numDelayFrames = (UCHAR)value;
901*e5436536SAndroid Build Coastguard Worker       }
902*e5436536SAndroid Build Coastguard Worker       break;
903*e5436536SAndroid Build Coastguard Worker     case SBR_QMF_MODE:
904*e5436536SAndroid Build Coastguard Worker       if (self == NULL) {
905*e5436536SAndroid Build Coastguard Worker         errorStatus = SBRDEC_NOT_INITIALIZED;
906*e5436536SAndroid Build Coastguard Worker       } else {
907*e5436536SAndroid Build Coastguard Worker         if (value == 1) {
908*e5436536SAndroid Build Coastguard Worker           self->flags |= SBRDEC_LOW_POWER;
909*e5436536SAndroid Build Coastguard Worker         } else {
910*e5436536SAndroid Build Coastguard Worker           self->flags &= ~SBRDEC_LOW_POWER;
911*e5436536SAndroid Build Coastguard Worker         }
912*e5436536SAndroid Build Coastguard Worker       }
913*e5436536SAndroid Build Coastguard Worker       break;
914*e5436536SAndroid Build Coastguard Worker     case SBR_LD_QMF_TIME_ALIGN:
915*e5436536SAndroid Build Coastguard Worker       if (self == NULL) {
916*e5436536SAndroid Build Coastguard Worker         errorStatus = SBRDEC_NOT_INITIALIZED;
917*e5436536SAndroid Build Coastguard Worker       } else {
918*e5436536SAndroid Build Coastguard Worker         if (value == 1) {
919*e5436536SAndroid Build Coastguard Worker           self->flags |= SBRDEC_LD_MPS_QMF;
920*e5436536SAndroid Build Coastguard Worker         } else {
921*e5436536SAndroid Build Coastguard Worker           self->flags &= ~SBRDEC_LD_MPS_QMF;
922*e5436536SAndroid Build Coastguard Worker         }
923*e5436536SAndroid Build Coastguard Worker       }
924*e5436536SAndroid Build Coastguard Worker       break;
925*e5436536SAndroid Build Coastguard Worker     case SBR_FLUSH_DATA:
926*e5436536SAndroid Build Coastguard Worker       if (value != 0) {
927*e5436536SAndroid Build Coastguard Worker         if (self == NULL) {
928*e5436536SAndroid Build Coastguard Worker           errorStatus = SBRDEC_NOT_INITIALIZED;
929*e5436536SAndroid Build Coastguard Worker         } else {
930*e5436536SAndroid Build Coastguard Worker           self->flags |= SBRDEC_FLUSH;
931*e5436536SAndroid Build Coastguard Worker         }
932*e5436536SAndroid Build Coastguard Worker       }
933*e5436536SAndroid Build Coastguard Worker       break;
934*e5436536SAndroid Build Coastguard Worker     case SBR_CLEAR_HISTORY:
935*e5436536SAndroid Build Coastguard Worker       if (value != 0) {
936*e5436536SAndroid Build Coastguard Worker         if (self == NULL) {
937*e5436536SAndroid Build Coastguard Worker           errorStatus = SBRDEC_NOT_INITIALIZED;
938*e5436536SAndroid Build Coastguard Worker         } else {
939*e5436536SAndroid Build Coastguard Worker           self->flags |= SBRDEC_FORCE_RESET;
940*e5436536SAndroid Build Coastguard Worker         }
941*e5436536SAndroid Build Coastguard Worker       }
942*e5436536SAndroid Build Coastguard Worker       break;
943*e5436536SAndroid Build Coastguard Worker     case SBR_BS_INTERRUPTION: {
944*e5436536SAndroid Build Coastguard Worker       int elementIndex;
945*e5436536SAndroid Build Coastguard Worker 
946*e5436536SAndroid Build Coastguard Worker       if (self == NULL) {
947*e5436536SAndroid Build Coastguard Worker         errorStatus = SBRDEC_NOT_INITIALIZED;
948*e5436536SAndroid Build Coastguard Worker         break;
949*e5436536SAndroid Build Coastguard Worker       }
950*e5436536SAndroid Build Coastguard Worker 
951*e5436536SAndroid Build Coastguard Worker       /* Loop over SBR elements */
952*e5436536SAndroid Build Coastguard Worker       for (elementIndex = 0; elementIndex < self->numSbrElements;
953*e5436536SAndroid Build Coastguard Worker            elementIndex++) {
954*e5436536SAndroid Build Coastguard Worker         if (self->pSbrElement[elementIndex] != NULL) {
955*e5436536SAndroid Build Coastguard Worker           HANDLE_SBR_HEADER_DATA hSbrHeader;
956*e5436536SAndroid Build Coastguard Worker           int headerIndex =
957*e5436536SAndroid Build Coastguard Worker               getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
958*e5436536SAndroid Build Coastguard Worker                             self->pSbrElement[elementIndex]->useHeaderSlot);
959*e5436536SAndroid Build Coastguard Worker 
960*e5436536SAndroid Build Coastguard Worker           hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
961*e5436536SAndroid Build Coastguard Worker 
962*e5436536SAndroid Build Coastguard Worker           /* Set sync state UPSAMPLING for the corresponding slot.
963*e5436536SAndroid Build Coastguard Worker              This switches off bitstream parsing until a new header arrives. */
964*e5436536SAndroid Build Coastguard Worker           if (hSbrHeader->syncState != SBR_NOT_INITIALIZED) {
965*e5436536SAndroid Build Coastguard Worker             hSbrHeader->syncState = UPSAMPLING;
966*e5436536SAndroid Build Coastguard Worker             hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
967*e5436536SAndroid Build Coastguard Worker           }
968*e5436536SAndroid Build Coastguard Worker         }
969*e5436536SAndroid Build Coastguard Worker       }
970*e5436536SAndroid Build Coastguard Worker     } break;
971*e5436536SAndroid Build Coastguard Worker 
972*e5436536SAndroid Build Coastguard Worker     case SBR_SKIP_QMF:
973*e5436536SAndroid Build Coastguard Worker       if (self == NULL) {
974*e5436536SAndroid Build Coastguard Worker         errorStatus = SBRDEC_NOT_INITIALIZED;
975*e5436536SAndroid Build Coastguard Worker       } else {
976*e5436536SAndroid Build Coastguard Worker         if (value == 1) {
977*e5436536SAndroid Build Coastguard Worker           self->flags |= SBRDEC_SKIP_QMF_ANA;
978*e5436536SAndroid Build Coastguard Worker         } else {
979*e5436536SAndroid Build Coastguard Worker           self->flags &= ~SBRDEC_SKIP_QMF_ANA;
980*e5436536SAndroid Build Coastguard Worker         }
981*e5436536SAndroid Build Coastguard Worker         if (value == 2) {
982*e5436536SAndroid Build Coastguard Worker           self->flags |= SBRDEC_SKIP_QMF_SYN;
983*e5436536SAndroid Build Coastguard Worker         } else {
984*e5436536SAndroid Build Coastguard Worker           self->flags &= ~SBRDEC_SKIP_QMF_SYN;
985*e5436536SAndroid Build Coastguard Worker         }
986*e5436536SAndroid Build Coastguard Worker       }
987*e5436536SAndroid Build Coastguard Worker       break;
988*e5436536SAndroid Build Coastguard Worker     default:
989*e5436536SAndroid Build Coastguard Worker       errorStatus = SBRDEC_SET_PARAM_FAIL;
990*e5436536SAndroid Build Coastguard Worker       break;
991*e5436536SAndroid Build Coastguard Worker   } /* switch(param) */
992*e5436536SAndroid Build Coastguard Worker 
993*e5436536SAndroid Build Coastguard Worker   return (errorStatus);
994*e5436536SAndroid Build Coastguard Worker }
995*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_drcGetChannel(const HANDLE_SBRDECODER self,const INT channel)996*e5436536SAndroid Build Coastguard Worker static SBRDEC_DRC_CHANNEL *sbrDecoder_drcGetChannel(
997*e5436536SAndroid Build Coastguard Worker     const HANDLE_SBRDECODER self, const INT channel) {
998*e5436536SAndroid Build Coastguard Worker   SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
999*e5436536SAndroid Build Coastguard Worker   int elementIndex, elChanIdx = 0, numCh = 0;
1000*e5436536SAndroid Build Coastguard Worker 
1001*e5436536SAndroid Build Coastguard Worker   for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel);
1002*e5436536SAndroid Build Coastguard Worker        elementIndex++) {
1003*e5436536SAndroid Build Coastguard Worker     SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex];
1004*e5436536SAndroid Build Coastguard Worker     int c, elChannels;
1005*e5436536SAndroid Build Coastguard Worker 
1006*e5436536SAndroid Build Coastguard Worker     elChanIdx = 0;
1007*e5436536SAndroid Build Coastguard Worker     if (pSbrElement == NULL) break;
1008*e5436536SAndroid Build Coastguard Worker 
1009*e5436536SAndroid Build Coastguard Worker     /* Determine amount of channels for this element */
1010*e5436536SAndroid Build Coastguard Worker     switch (pSbrElement->elementID) {
1011*e5436536SAndroid Build Coastguard Worker       case ID_CPE:
1012*e5436536SAndroid Build Coastguard Worker         elChannels = 2;
1013*e5436536SAndroid Build Coastguard Worker         break;
1014*e5436536SAndroid Build Coastguard Worker       case ID_LFE:
1015*e5436536SAndroid Build Coastguard Worker       case ID_SCE:
1016*e5436536SAndroid Build Coastguard Worker         elChannels = 1;
1017*e5436536SAndroid Build Coastguard Worker         break;
1018*e5436536SAndroid Build Coastguard Worker       case ID_NONE:
1019*e5436536SAndroid Build Coastguard Worker       default:
1020*e5436536SAndroid Build Coastguard Worker         elChannels = 0;
1021*e5436536SAndroid Build Coastguard Worker         break;
1022*e5436536SAndroid Build Coastguard Worker     }
1023*e5436536SAndroid Build Coastguard Worker 
1024*e5436536SAndroid Build Coastguard Worker     /* Limit with actual allocated element channels */
1025*e5436536SAndroid Build Coastguard Worker     elChannels = fMin(elChannels, pSbrElement->nChannels);
1026*e5436536SAndroid Build Coastguard Worker 
1027*e5436536SAndroid Build Coastguard Worker     for (c = 0; (c < elChannels) && (numCh <= channel); c++) {
1028*e5436536SAndroid Build Coastguard Worker       if (pSbrElement->pSbrChannel[elChanIdx] != NULL) {
1029*e5436536SAndroid Build Coastguard Worker         numCh++;
1030*e5436536SAndroid Build Coastguard Worker         elChanIdx++;
1031*e5436536SAndroid Build Coastguard Worker       }
1032*e5436536SAndroid Build Coastguard Worker     }
1033*e5436536SAndroid Build Coastguard Worker   }
1034*e5436536SAndroid Build Coastguard Worker   elementIndex -= 1;
1035*e5436536SAndroid Build Coastguard Worker   elChanIdx -= 1;
1036*e5436536SAndroid Build Coastguard Worker 
1037*e5436536SAndroid Build Coastguard Worker   if (elChanIdx < 0 || elementIndex < 0) {
1038*e5436536SAndroid Build Coastguard Worker     return NULL;
1039*e5436536SAndroid Build Coastguard Worker   }
1040*e5436536SAndroid Build Coastguard Worker 
1041*e5436536SAndroid Build Coastguard Worker   if (self->pSbrElement[elementIndex] != NULL) {
1042*e5436536SAndroid Build Coastguard Worker     if (self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL) {
1043*e5436536SAndroid Build Coastguard Worker       pSbrDrcChannelData = &self->pSbrElement[elementIndex]
1044*e5436536SAndroid Build Coastguard Worker                                 ->pSbrChannel[elChanIdx]
1045*e5436536SAndroid Build Coastguard Worker                                 ->SbrDec.sbrDrcChannel;
1046*e5436536SAndroid Build Coastguard Worker     }
1047*e5436536SAndroid Build Coastguard Worker   }
1048*e5436536SAndroid Build Coastguard Worker 
1049*e5436536SAndroid Build Coastguard Worker   return (pSbrDrcChannelData);
1050*e5436536SAndroid Build Coastguard Worker }
1051*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self,INT ch,UINT numBands,FIXP_DBL * pNextFact_mag,INT nextFact_exp,SHORT drcInterpolationScheme,UCHAR winSequence,USHORT * pBandTop)1052*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self, INT ch,
1053*e5436536SAndroid Build Coastguard Worker                                     UINT numBands, FIXP_DBL *pNextFact_mag,
1054*e5436536SAndroid Build Coastguard Worker                                     INT nextFact_exp,
1055*e5436536SAndroid Build Coastguard Worker                                     SHORT drcInterpolationScheme,
1056*e5436536SAndroid Build Coastguard Worker                                     UCHAR winSequence, USHORT *pBandTop) {
1057*e5436536SAndroid Build Coastguard Worker   SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
1058*e5436536SAndroid Build Coastguard Worker   int band, isValidData = 0;
1059*e5436536SAndroid Build Coastguard Worker 
1060*e5436536SAndroid Build Coastguard Worker   if (self == NULL) {
1061*e5436536SAndroid Build Coastguard Worker     return SBRDEC_NOT_INITIALIZED;
1062*e5436536SAndroid Build Coastguard Worker   }
1063*e5436536SAndroid Build Coastguard Worker   if (ch > (8) || pNextFact_mag == NULL) {
1064*e5436536SAndroid Build Coastguard Worker     return SBRDEC_SET_PARAM_FAIL;
1065*e5436536SAndroid Build Coastguard Worker   }
1066*e5436536SAndroid Build Coastguard Worker 
1067*e5436536SAndroid Build Coastguard Worker   /* Search for gain values different to 1.0f */
1068*e5436536SAndroid Build Coastguard Worker   for (band = 0; band < (int)numBands; band += 1) {
1069*e5436536SAndroid Build Coastguard Worker     if (!((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) &&
1070*e5436536SAndroid Build Coastguard Worker           (nextFact_exp == 1)) &&
1071*e5436536SAndroid Build Coastguard Worker         !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) &&
1072*e5436536SAndroid Build Coastguard Worker           (nextFact_exp == 0))) {
1073*e5436536SAndroid Build Coastguard Worker       isValidData = 1;
1074*e5436536SAndroid Build Coastguard Worker       break;
1075*e5436536SAndroid Build Coastguard Worker     }
1076*e5436536SAndroid Build Coastguard Worker   }
1077*e5436536SAndroid Build Coastguard Worker 
1078*e5436536SAndroid Build Coastguard Worker   /* Find the right SBR channel */
1079*e5436536SAndroid Build Coastguard Worker   pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch);
1080*e5436536SAndroid Build Coastguard Worker 
1081*e5436536SAndroid Build Coastguard Worker   if (pSbrDrcChannelData != NULL) {
1082*e5436536SAndroid Build Coastguard Worker     if (pSbrDrcChannelData->enable ||
1083*e5436536SAndroid Build Coastguard Worker         isValidData) { /* Activate processing only with real and valid data */
1084*e5436536SAndroid Build Coastguard Worker       int i;
1085*e5436536SAndroid Build Coastguard Worker 
1086*e5436536SAndroid Build Coastguard Worker       pSbrDrcChannelData->enable = 1;
1087*e5436536SAndroid Build Coastguard Worker       pSbrDrcChannelData->numBandsNext = numBands;
1088*e5436536SAndroid Build Coastguard Worker 
1089*e5436536SAndroid Build Coastguard Worker       pSbrDrcChannelData->winSequenceNext = winSequence;
1090*e5436536SAndroid Build Coastguard Worker       pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme;
1091*e5436536SAndroid Build Coastguard Worker       pSbrDrcChannelData->nextFact_exp = nextFact_exp;
1092*e5436536SAndroid Build Coastguard Worker 
1093*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < (int)numBands; i++) {
1094*e5436536SAndroid Build Coastguard Worker         pSbrDrcChannelData->bandTopNext[i] = pBandTop[i];
1095*e5436536SAndroid Build Coastguard Worker         pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i];
1096*e5436536SAndroid Build Coastguard Worker       }
1097*e5436536SAndroid Build Coastguard Worker     }
1098*e5436536SAndroid Build Coastguard Worker   }
1099*e5436536SAndroid Build Coastguard Worker 
1100*e5436536SAndroid Build Coastguard Worker   return SBRDEC_OK;
1101*e5436536SAndroid Build Coastguard Worker }
1102*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_drcDisable(HANDLE_SBRDECODER self,INT ch)1103*e5436536SAndroid Build Coastguard Worker void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch) {
1104*e5436536SAndroid Build Coastguard Worker   SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
1105*e5436536SAndroid Build Coastguard Worker 
1106*e5436536SAndroid Build Coastguard Worker   if ((self == NULL) || (ch > (8)) || (self->numSbrElements == 0) ||
1107*e5436536SAndroid Build Coastguard Worker       (self->numSbrChannels == 0)) {
1108*e5436536SAndroid Build Coastguard Worker     return;
1109*e5436536SAndroid Build Coastguard Worker   }
1110*e5436536SAndroid Build Coastguard Worker 
1111*e5436536SAndroid Build Coastguard Worker   /* Find the right SBR channel */
1112*e5436536SAndroid Build Coastguard Worker   pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch);
1113*e5436536SAndroid Build Coastguard Worker 
1114*e5436536SAndroid Build Coastguard Worker   if (pSbrDrcChannelData != NULL) {
1115*e5436536SAndroid Build Coastguard Worker     sbrDecoder_drcInitChannel(pSbrDrcChannelData);
1116*e5436536SAndroid Build Coastguard Worker   }
1117*e5436536SAndroid Build Coastguard Worker }
1118*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_Parse(HANDLE_SBRDECODER self,HANDLE_FDK_BITSTREAM hBs,UCHAR * pDrmBsBuffer,USHORT drmBsBufferSize,int * count,int bsPayLen,int crcFlag,MP4_ELEMENT_ID prevElement,int elementIndex,UINT acFlags,UINT acElFlags[])1119*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs,
1120*e5436536SAndroid Build Coastguard Worker                            UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize,
1121*e5436536SAndroid Build Coastguard Worker                            int *count, int bsPayLen, int crcFlag,
1122*e5436536SAndroid Build Coastguard Worker                            MP4_ELEMENT_ID prevElement, int elementIndex,
1123*e5436536SAndroid Build Coastguard Worker                            UINT acFlags, UINT acElFlags[]) {
1124*e5436536SAndroid Build Coastguard Worker   SBR_DECODER_ELEMENT *hSbrElement = NULL;
1125*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_HEADER_DATA hSbrHeader = NULL;
1126*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_CHANNEL *pSbrChannel;
1127*e5436536SAndroid Build Coastguard Worker 
1128*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_DATA *hFrameDataLeft = NULL;
1129*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_DATA *hFrameDataRight = NULL;
1130*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_DATA frameDataLeftCopy;
1131*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_DATA frameDataRightCopy;
1132*e5436536SAndroid Build Coastguard Worker 
1133*e5436536SAndroid Build Coastguard Worker   SBR_ERROR errorStatus = SBRDEC_OK;
1134*e5436536SAndroid Build Coastguard Worker   SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT;
1135*e5436536SAndroid Build Coastguard Worker 
1136*e5436536SAndroid Build Coastguard Worker   INT startPos = FDKgetValidBits(hBs);
1137*e5436536SAndroid Build Coastguard Worker   FDK_CRCINFO crcInfo;
1138*e5436536SAndroid Build Coastguard Worker   INT crcReg = 0;
1139*e5436536SAndroid Build Coastguard Worker   USHORT sbrCrc = 0;
1140*e5436536SAndroid Build Coastguard Worker   UINT crcPoly;
1141*e5436536SAndroid Build Coastguard Worker   UINT crcStartValue = 0;
1142*e5436536SAndroid Build Coastguard Worker   UINT crcLen;
1143*e5436536SAndroid Build Coastguard Worker 
1144*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBsOriginal = hBs;
1145*e5436536SAndroid Build Coastguard Worker   FDK_BITSTREAM bsBwd;
1146*e5436536SAndroid Build Coastguard Worker 
1147*e5436536SAndroid Build Coastguard Worker   const int fGlobalIndependencyFlag = acFlags & AC_INDEP;
1148*e5436536SAndroid Build Coastguard Worker   const int bs_pvc = acElFlags[elementIndex] & AC_EL_USAC_PVC;
1149*e5436536SAndroid Build Coastguard Worker   const int bs_interTes = acElFlags[elementIndex] & AC_EL_USAC_ITES;
1150*e5436536SAndroid Build Coastguard Worker   int stereo;
1151*e5436536SAndroid Build Coastguard Worker   int fDoDecodeSbrData = 1;
1152*e5436536SAndroid Build Coastguard Worker   int alignBits = 0;
1153*e5436536SAndroid Build Coastguard Worker 
1154*e5436536SAndroid Build Coastguard Worker   int lastSlot, lastHdrSlot = 0, thisHdrSlot = 0;
1155*e5436536SAndroid Build Coastguard Worker 
1156*e5436536SAndroid Build Coastguard Worker   if (*count <= 0) {
1157*e5436536SAndroid Build Coastguard Worker     setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR);
1158*e5436536SAndroid Build Coastguard Worker     return SBRDEC_OK;
1159*e5436536SAndroid Build Coastguard Worker   }
1160*e5436536SAndroid Build Coastguard Worker 
1161*e5436536SAndroid Build Coastguard Worker   /* SBR sanity checks */
1162*e5436536SAndroid Build Coastguard Worker   if (self == NULL) {
1163*e5436536SAndroid Build Coastguard Worker     errorStatus = SBRDEC_NOT_INITIALIZED;
1164*e5436536SAndroid Build Coastguard Worker     goto bail;
1165*e5436536SAndroid Build Coastguard Worker   }
1166*e5436536SAndroid Build Coastguard Worker 
1167*e5436536SAndroid Build Coastguard Worker   /* Reverse bits of DRM SBR payload */
1168*e5436536SAndroid Build Coastguard Worker   if ((self->flags & SBRDEC_SYNTAX_DRM) && *count > 0) {
1169*e5436536SAndroid Build Coastguard Worker     int dataBytes, dataBits;
1170*e5436536SAndroid Build Coastguard Worker 
1171*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(drmBsBufferSize >= (512));
1172*e5436536SAndroid Build Coastguard Worker     dataBits = *count;
1173*e5436536SAndroid Build Coastguard Worker 
1174*e5436536SAndroid Build Coastguard Worker     if (dataBits > ((512) * 8)) {
1175*e5436536SAndroid Build Coastguard Worker       /* do not flip more data than needed */
1176*e5436536SAndroid Build Coastguard Worker       dataBits = (512) * 8;
1177*e5436536SAndroid Build Coastguard Worker     }
1178*e5436536SAndroid Build Coastguard Worker 
1179*e5436536SAndroid Build Coastguard Worker     dataBytes = (dataBits + 7) >> 3;
1180*e5436536SAndroid Build Coastguard Worker 
1181*e5436536SAndroid Build Coastguard Worker     int j;
1182*e5436536SAndroid Build Coastguard Worker 
1183*e5436536SAndroid Build Coastguard Worker     if ((j = (int)FDKgetValidBits(hBs)) != 8) {
1184*e5436536SAndroid Build Coastguard Worker       FDKpushBiDirectional(hBs, (j - 8));
1185*e5436536SAndroid Build Coastguard Worker     }
1186*e5436536SAndroid Build Coastguard Worker 
1187*e5436536SAndroid Build Coastguard Worker     j = 0;
1188*e5436536SAndroid Build Coastguard Worker     for (; dataBytes > 0; dataBytes--) {
1189*e5436536SAndroid Build Coastguard Worker       int i;
1190*e5436536SAndroid Build Coastguard Worker       UCHAR tmpByte;
1191*e5436536SAndroid Build Coastguard Worker       UCHAR buffer = 0x00;
1192*e5436536SAndroid Build Coastguard Worker 
1193*e5436536SAndroid Build Coastguard Worker       tmpByte = (UCHAR)FDKreadBits(hBs, 8);
1194*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < 4; i++) {
1195*e5436536SAndroid Build Coastguard Worker         int shift = 2 * i + 1;
1196*e5436536SAndroid Build Coastguard Worker         buffer |= (tmpByte & (0x08 >> i)) << shift;
1197*e5436536SAndroid Build Coastguard Worker         buffer |= (tmpByte & (0x10 << i)) >> shift;
1198*e5436536SAndroid Build Coastguard Worker       }
1199*e5436536SAndroid Build Coastguard Worker       pDrmBsBuffer[j++] = buffer;
1200*e5436536SAndroid Build Coastguard Worker       FDKpushBack(hBs, 16);
1201*e5436536SAndroid Build Coastguard Worker     }
1202*e5436536SAndroid Build Coastguard Worker 
1203*e5436536SAndroid Build Coastguard Worker     FDKinitBitStream(&bsBwd, pDrmBsBuffer, (512), dataBits, BS_READER);
1204*e5436536SAndroid Build Coastguard Worker 
1205*e5436536SAndroid Build Coastguard Worker     /* Use reversed data */
1206*e5436536SAndroid Build Coastguard Worker     hBs = &bsBwd;
1207*e5436536SAndroid Build Coastguard Worker     bsPayLen = *count;
1208*e5436536SAndroid Build Coastguard Worker   }
1209*e5436536SAndroid Build Coastguard Worker 
1210*e5436536SAndroid Build Coastguard Worker   /* Remember start position of  SBR element */
1211*e5436536SAndroid Build Coastguard Worker   startPos = FDKgetValidBits(hBs);
1212*e5436536SAndroid Build Coastguard Worker 
1213*e5436536SAndroid Build Coastguard Worker   /* SBR sanity checks */
1214*e5436536SAndroid Build Coastguard Worker   if (self->pSbrElement[elementIndex] == NULL) {
1215*e5436536SAndroid Build Coastguard Worker     errorStatus = SBRDEC_NOT_INITIALIZED;
1216*e5436536SAndroid Build Coastguard Worker     goto bail;
1217*e5436536SAndroid Build Coastguard Worker   }
1218*e5436536SAndroid Build Coastguard Worker   hSbrElement = self->pSbrElement[elementIndex];
1219*e5436536SAndroid Build Coastguard Worker 
1220*e5436536SAndroid Build Coastguard Worker   lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot - 1
1221*e5436536SAndroid Build Coastguard Worker                                              : self->numDelayFrames;
1222*e5436536SAndroid Build Coastguard Worker   lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot];
1223*e5436536SAndroid Build Coastguard Worker   thisHdrSlot = getHeaderSlot(
1224*e5436536SAndroid Build Coastguard Worker       hSbrElement->useFrameSlot,
1225*e5436536SAndroid Build Coastguard Worker       hSbrElement->useHeaderSlot); /* Get a free header slot not used by
1226*e5436536SAndroid Build Coastguard Worker                                       frames not processed yet. */
1227*e5436536SAndroid Build Coastguard Worker 
1228*e5436536SAndroid Build Coastguard Worker   /* Assign the free slot to store a new header if there is one. */
1229*e5436536SAndroid Build Coastguard Worker   hSbrHeader = &self->sbrHeader[elementIndex][thisHdrSlot];
1230*e5436536SAndroid Build Coastguard Worker 
1231*e5436536SAndroid Build Coastguard Worker   pSbrChannel = hSbrElement->pSbrChannel;
1232*e5436536SAndroid Build Coastguard Worker   stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
1233*e5436536SAndroid Build Coastguard Worker 
1234*e5436536SAndroid Build Coastguard Worker   hFrameDataLeft = &self->pSbrElement[elementIndex]
1235*e5436536SAndroid Build Coastguard Worker                         ->pSbrChannel[0]
1236*e5436536SAndroid Build Coastguard Worker                         ->frameData[hSbrElement->useFrameSlot];
1237*e5436536SAndroid Build Coastguard Worker   if (stereo) {
1238*e5436536SAndroid Build Coastguard Worker     hFrameDataRight = &self->pSbrElement[elementIndex]
1239*e5436536SAndroid Build Coastguard Worker                            ->pSbrChannel[1]
1240*e5436536SAndroid Build Coastguard Worker                            ->frameData[hSbrElement->useFrameSlot];
1241*e5436536SAndroid Build Coastguard Worker   }
1242*e5436536SAndroid Build Coastguard Worker 
1243*e5436536SAndroid Build Coastguard Worker   /* store frameData; new parsed frameData possibly corrupted */
1244*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(&frameDataLeftCopy, hFrameDataLeft, sizeof(SBR_FRAME_DATA));
1245*e5436536SAndroid Build Coastguard Worker   if (stereo) {
1246*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(&frameDataRightCopy, hFrameDataRight, sizeof(SBR_FRAME_DATA));
1247*e5436536SAndroid Build Coastguard Worker   }
1248*e5436536SAndroid Build Coastguard Worker 
1249*e5436536SAndroid Build Coastguard Worker   /* reset PS flag; will be set after PS was found */
1250*e5436536SAndroid Build Coastguard Worker   self->flags &= ~SBRDEC_PS_DECODED;
1251*e5436536SAndroid Build Coastguard Worker 
1252*e5436536SAndroid Build Coastguard Worker   if (hSbrHeader->status & SBRDEC_HDR_STAT_UPDATE) {
1253*e5436536SAndroid Build Coastguard Worker     /* Got a new header from extern (e.g. from an ASC) */
1254*e5436536SAndroid Build Coastguard Worker     headerStatus = HEADER_OK;
1255*e5436536SAndroid Build Coastguard Worker     hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE;
1256*e5436536SAndroid Build Coastguard Worker   } else if (thisHdrSlot != lastHdrSlot) {
1257*e5436536SAndroid Build Coastguard Worker     /* Copy the last header into this slot otherwise the
1258*e5436536SAndroid Build Coastguard Worker        header compare will trigger more HEADER_RESETs than needed. */
1259*e5436536SAndroid Build Coastguard Worker     copySbrHeader(hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot]);
1260*e5436536SAndroid Build Coastguard Worker   }
1261*e5436536SAndroid Build Coastguard Worker 
1262*e5436536SAndroid Build Coastguard Worker   /*
1263*e5436536SAndroid Build Coastguard Worker      Check if bit stream data is valid and matches the element context
1264*e5436536SAndroid Build Coastguard Worker   */
1265*e5436536SAndroid Build Coastguard Worker   if (((prevElement != ID_SCE) && (prevElement != ID_CPE)) ||
1266*e5436536SAndroid Build Coastguard Worker       prevElement != hSbrElement->elementID) {
1267*e5436536SAndroid Build Coastguard Worker     /* In case of LFE we also land here, since there is no LFE SBR element (do
1268*e5436536SAndroid Build Coastguard Worker      * upsampling only) */
1269*e5436536SAndroid Build Coastguard Worker     fDoDecodeSbrData = 0;
1270*e5436536SAndroid Build Coastguard Worker   }
1271*e5436536SAndroid Build Coastguard Worker 
1272*e5436536SAndroid Build Coastguard Worker   if (fDoDecodeSbrData) {
1273*e5436536SAndroid Build Coastguard Worker     if ((INT)FDKgetValidBits(hBs) <= 0) {
1274*e5436536SAndroid Build Coastguard Worker       fDoDecodeSbrData = 0;
1275*e5436536SAndroid Build Coastguard Worker     }
1276*e5436536SAndroid Build Coastguard Worker   }
1277*e5436536SAndroid Build Coastguard Worker 
1278*e5436536SAndroid Build Coastguard Worker   /*
1279*e5436536SAndroid Build Coastguard Worker      SBR CRC-check
1280*e5436536SAndroid Build Coastguard Worker   */
1281*e5436536SAndroid Build Coastguard Worker   if (fDoDecodeSbrData) {
1282*e5436536SAndroid Build Coastguard Worker     if (crcFlag) {
1283*e5436536SAndroid Build Coastguard Worker       switch (self->coreCodec) {
1284*e5436536SAndroid Build Coastguard Worker         case AOT_DRM_AAC:
1285*e5436536SAndroid Build Coastguard Worker         case AOT_DRM_SURROUND:
1286*e5436536SAndroid Build Coastguard Worker           crcPoly = 0x001d;
1287*e5436536SAndroid Build Coastguard Worker           crcLen = 8;
1288*e5436536SAndroid Build Coastguard Worker           crcStartValue = 0x000000ff;
1289*e5436536SAndroid Build Coastguard Worker           break;
1290*e5436536SAndroid Build Coastguard Worker         default:
1291*e5436536SAndroid Build Coastguard Worker           crcPoly = 0x0633;
1292*e5436536SAndroid Build Coastguard Worker           crcLen = 10;
1293*e5436536SAndroid Build Coastguard Worker           crcStartValue = 0x00000000;
1294*e5436536SAndroid Build Coastguard Worker           break;
1295*e5436536SAndroid Build Coastguard Worker       }
1296*e5436536SAndroid Build Coastguard Worker       sbrCrc = (USHORT)FDKreadBits(hBs, crcLen);
1297*e5436536SAndroid Build Coastguard Worker       /* Setup CRC decoder */
1298*e5436536SAndroid Build Coastguard Worker       FDKcrcInit(&crcInfo, crcPoly, crcStartValue, crcLen);
1299*e5436536SAndroid Build Coastguard Worker       /* Start CRC region */
1300*e5436536SAndroid Build Coastguard Worker       crcReg = FDKcrcStartReg(&crcInfo, hBs, 0);
1301*e5436536SAndroid Build Coastguard Worker     }
1302*e5436536SAndroid Build Coastguard Worker   } /* if (fDoDecodeSbrData) */
1303*e5436536SAndroid Build Coastguard Worker 
1304*e5436536SAndroid Build Coastguard Worker   /*
1305*e5436536SAndroid Build Coastguard Worker      Read in the header data and issue a reset if change occured
1306*e5436536SAndroid Build Coastguard Worker   */
1307*e5436536SAndroid Build Coastguard Worker   if (fDoDecodeSbrData) {
1308*e5436536SAndroid Build Coastguard Worker     int sbrHeaderPresent;
1309*e5436536SAndroid Build Coastguard Worker 
1310*e5436536SAndroid Build Coastguard Worker     if (self->flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) {
1311*e5436536SAndroid Build Coastguard Worker       SBR_HEADER_DATA_BS_INFO newSbrInfo;
1312*e5436536SAndroid Build Coastguard Worker       int sbrInfoPresent;
1313*e5436536SAndroid Build Coastguard Worker 
1314*e5436536SAndroid Build Coastguard Worker       if (bs_interTes) {
1315*e5436536SAndroid Build Coastguard Worker         self->flags |= SBRDEC_USAC_ITES;
1316*e5436536SAndroid Build Coastguard Worker       } else {
1317*e5436536SAndroid Build Coastguard Worker         self->flags &= ~SBRDEC_USAC_ITES;
1318*e5436536SAndroid Build Coastguard Worker       }
1319*e5436536SAndroid Build Coastguard Worker 
1320*e5436536SAndroid Build Coastguard Worker       if (fGlobalIndependencyFlag) {
1321*e5436536SAndroid Build Coastguard Worker         self->flags |= SBRDEC_USAC_INDEP;
1322*e5436536SAndroid Build Coastguard Worker         sbrInfoPresent = 1;
1323*e5436536SAndroid Build Coastguard Worker         sbrHeaderPresent = 1;
1324*e5436536SAndroid Build Coastguard Worker       } else {
1325*e5436536SAndroid Build Coastguard Worker         self->flags &= ~SBRDEC_USAC_INDEP;
1326*e5436536SAndroid Build Coastguard Worker         sbrInfoPresent = FDKreadBit(hBs);
1327*e5436536SAndroid Build Coastguard Worker         if (sbrInfoPresent) {
1328*e5436536SAndroid Build Coastguard Worker           sbrHeaderPresent = FDKreadBit(hBs);
1329*e5436536SAndroid Build Coastguard Worker         } else {
1330*e5436536SAndroid Build Coastguard Worker           sbrHeaderPresent = 0;
1331*e5436536SAndroid Build Coastguard Worker         }
1332*e5436536SAndroid Build Coastguard Worker       }
1333*e5436536SAndroid Build Coastguard Worker 
1334*e5436536SAndroid Build Coastguard Worker       if (sbrInfoPresent) {
1335*e5436536SAndroid Build Coastguard Worker         newSbrInfo.ampResolution = FDKreadBit(hBs);
1336*e5436536SAndroid Build Coastguard Worker         newSbrInfo.xover_band = FDKreadBits(hBs, 4);
1337*e5436536SAndroid Build Coastguard Worker         newSbrInfo.sbr_preprocessing = FDKreadBit(hBs);
1338*e5436536SAndroid Build Coastguard Worker         if (bs_pvc) {
1339*e5436536SAndroid Build Coastguard Worker           newSbrInfo.pvc_mode = FDKreadBits(hBs, 2);
1340*e5436536SAndroid Build Coastguard Worker           /* bs_pvc_mode: 0 -> no PVC, 1 -> PVC mode 1, 2 -> PVC mode 2, 3 ->
1341*e5436536SAndroid Build Coastguard Worker            * reserved */
1342*e5436536SAndroid Build Coastguard Worker           if (newSbrInfo.pvc_mode > 2) {
1343*e5436536SAndroid Build Coastguard Worker             headerStatus = HEADER_ERROR;
1344*e5436536SAndroid Build Coastguard Worker           }
1345*e5436536SAndroid Build Coastguard Worker           if (stereo && newSbrInfo.pvc_mode > 0) {
1346*e5436536SAndroid Build Coastguard Worker             /* bs_pvc is always transmitted but pvc_mode is set to zero in case
1347*e5436536SAndroid Build Coastguard Worker              * of stereo SBR. The config might be wrong but we cannot tell for
1348*e5436536SAndroid Build Coastguard Worker              * sure. */
1349*e5436536SAndroid Build Coastguard Worker             newSbrInfo.pvc_mode = 0;
1350*e5436536SAndroid Build Coastguard Worker           }
1351*e5436536SAndroid Build Coastguard Worker         } else {
1352*e5436536SAndroid Build Coastguard Worker           newSbrInfo.pvc_mode = 0;
1353*e5436536SAndroid Build Coastguard Worker         }
1354*e5436536SAndroid Build Coastguard Worker         if (headerStatus != HEADER_ERROR) {
1355*e5436536SAndroid Build Coastguard Worker           if (FDKmemcmp(&hSbrHeader->bs_info, &newSbrInfo,
1356*e5436536SAndroid Build Coastguard Worker                         sizeof(SBR_HEADER_DATA_BS_INFO))) {
1357*e5436536SAndroid Build Coastguard Worker             /* in case of ampResolution and preprocessing change no full reset
1358*e5436536SAndroid Build Coastguard Worker              * required    */
1359*e5436536SAndroid Build Coastguard Worker             /* HEADER reset would trigger HBE transposer reset which breaks
1360*e5436536SAndroid Build Coastguard Worker              * eSbr_3_Eaa.mp4 */
1361*e5436536SAndroid Build Coastguard Worker             if ((hSbrHeader->bs_info.pvc_mode != newSbrInfo.pvc_mode) ||
1362*e5436536SAndroid Build Coastguard Worker                 (hSbrHeader->bs_info.xover_band != newSbrInfo.xover_band)) {
1363*e5436536SAndroid Build Coastguard Worker               headerStatus = HEADER_RESET;
1364*e5436536SAndroid Build Coastguard Worker             } else {
1365*e5436536SAndroid Build Coastguard Worker               headerStatus = HEADER_OK;
1366*e5436536SAndroid Build Coastguard Worker             }
1367*e5436536SAndroid Build Coastguard Worker 
1368*e5436536SAndroid Build Coastguard Worker             hSbrHeader->bs_info = newSbrInfo;
1369*e5436536SAndroid Build Coastguard Worker           } else {
1370*e5436536SAndroid Build Coastguard Worker             headerStatus = HEADER_OK;
1371*e5436536SAndroid Build Coastguard Worker           }
1372*e5436536SAndroid Build Coastguard Worker         }
1373*e5436536SAndroid Build Coastguard Worker       }
1374*e5436536SAndroid Build Coastguard Worker       if (headerStatus == HEADER_ERROR) {
1375*e5436536SAndroid Build Coastguard Worker         /* Corrupt SBR info data, do not decode and switch to UPSAMPLING */
1376*e5436536SAndroid Build Coastguard Worker         hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING
1377*e5436536SAndroid Build Coastguard Worker                                     ? UPSAMPLING
1378*e5436536SAndroid Build Coastguard Worker                                     : hSbrHeader->syncState;
1379*e5436536SAndroid Build Coastguard Worker         fDoDecodeSbrData = 0;
1380*e5436536SAndroid Build Coastguard Worker         sbrHeaderPresent = 0;
1381*e5436536SAndroid Build Coastguard Worker       }
1382*e5436536SAndroid Build Coastguard Worker 
1383*e5436536SAndroid Build Coastguard Worker       if (sbrHeaderPresent && fDoDecodeSbrData) {
1384*e5436536SAndroid Build Coastguard Worker         int useDfltHeader;
1385*e5436536SAndroid Build Coastguard Worker 
1386*e5436536SAndroid Build Coastguard Worker         useDfltHeader = FDKreadBit(hBs);
1387*e5436536SAndroid Build Coastguard Worker 
1388*e5436536SAndroid Build Coastguard Worker         if (useDfltHeader) {
1389*e5436536SAndroid Build Coastguard Worker           sbrHeaderPresent = 0;
1390*e5436536SAndroid Build Coastguard Worker           if (FDKmemcmp(&hSbrHeader->bs_data, &hSbrHeader->bs_dflt,
1391*e5436536SAndroid Build Coastguard Worker                         sizeof(SBR_HEADER_DATA_BS)) ||
1392*e5436536SAndroid Build Coastguard Worker               hSbrHeader->syncState != SBR_ACTIVE) {
1393*e5436536SAndroid Build Coastguard Worker             hSbrHeader->bs_data = hSbrHeader->bs_dflt;
1394*e5436536SAndroid Build Coastguard Worker             headerStatus = HEADER_RESET;
1395*e5436536SAndroid Build Coastguard Worker           }
1396*e5436536SAndroid Build Coastguard Worker         }
1397*e5436536SAndroid Build Coastguard Worker       }
1398*e5436536SAndroid Build Coastguard Worker     } else {
1399*e5436536SAndroid Build Coastguard Worker       sbrHeaderPresent = FDKreadBit(hBs);
1400*e5436536SAndroid Build Coastguard Worker     }
1401*e5436536SAndroid Build Coastguard Worker 
1402*e5436536SAndroid Build Coastguard Worker     if (sbrHeaderPresent) {
1403*e5436536SAndroid Build Coastguard Worker       headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 1, 0);
1404*e5436536SAndroid Build Coastguard Worker     }
1405*e5436536SAndroid Build Coastguard Worker 
1406*e5436536SAndroid Build Coastguard Worker     if (headerStatus == HEADER_RESET) {
1407*e5436536SAndroid Build Coastguard Worker       errorStatus = sbrDecoder_HeaderUpdate(
1408*e5436536SAndroid Build Coastguard Worker           self, hSbrHeader, headerStatus, pSbrChannel, hSbrElement->nChannels);
1409*e5436536SAndroid Build Coastguard Worker 
1410*e5436536SAndroid Build Coastguard Worker       if (errorStatus == SBRDEC_OK) {
1411*e5436536SAndroid Build Coastguard Worker         hSbrHeader->syncState = SBR_HEADER;
1412*e5436536SAndroid Build Coastguard Worker       } else {
1413*e5436536SAndroid Build Coastguard Worker         hSbrHeader->syncState = SBR_NOT_INITIALIZED;
1414*e5436536SAndroid Build Coastguard Worker         headerStatus = HEADER_ERROR;
1415*e5436536SAndroid Build Coastguard Worker       }
1416*e5436536SAndroid Build Coastguard Worker     }
1417*e5436536SAndroid Build Coastguard Worker 
1418*e5436536SAndroid Build Coastguard Worker     if (errorStatus != SBRDEC_OK) {
1419*e5436536SAndroid Build Coastguard Worker       fDoDecodeSbrData = 0;
1420*e5436536SAndroid Build Coastguard Worker     }
1421*e5436536SAndroid Build Coastguard Worker   } /* if (fDoDecodeSbrData) */
1422*e5436536SAndroid Build Coastguard Worker 
1423*e5436536SAndroid Build Coastguard Worker   /*
1424*e5436536SAndroid Build Coastguard Worker     Print debugging output only if state has changed
1425*e5436536SAndroid Build Coastguard Worker   */
1426*e5436536SAndroid Build Coastguard Worker 
1427*e5436536SAndroid Build Coastguard Worker   /* read frame data */
1428*e5436536SAndroid Build Coastguard Worker   if ((hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) {
1429*e5436536SAndroid Build Coastguard Worker     int sbrFrameOk;
1430*e5436536SAndroid Build Coastguard Worker     /* read the SBR element data */
1431*e5436536SAndroid Build Coastguard Worker     if (!stereo && (self->hParametricStereoDec != NULL)) {
1432*e5436536SAndroid Build Coastguard Worker       /* update slot index for PS bitstream parsing */
1433*e5436536SAndroid Build Coastguard Worker       self->hParametricStereoDec->bsLastSlot =
1434*e5436536SAndroid Build Coastguard Worker           self->hParametricStereoDec->bsReadSlot;
1435*e5436536SAndroid Build Coastguard Worker       self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot;
1436*e5436536SAndroid Build Coastguard Worker     }
1437*e5436536SAndroid Build Coastguard Worker     sbrFrameOk = sbrGetChannelElement(
1438*e5436536SAndroid Build Coastguard Worker         hSbrHeader, hFrameDataLeft, (stereo) ? hFrameDataRight : NULL,
1439*e5436536SAndroid Build Coastguard Worker         &pSbrChannel[0]->prevFrameData,
1440*e5436536SAndroid Build Coastguard Worker         pSbrChannel[0]->SbrDec.PvcStaticData.pvc_mode_last, hBs,
1441*e5436536SAndroid Build Coastguard Worker         (stereo) ? NULL : self->hParametricStereoDec, self->flags,
1442*e5436536SAndroid Build Coastguard Worker         self->pSbrElement[elementIndex]->transposerSettings.overlap);
1443*e5436536SAndroid Build Coastguard Worker 
1444*e5436536SAndroid Build Coastguard Worker     if (!sbrFrameOk) {
1445*e5436536SAndroid Build Coastguard Worker       fDoDecodeSbrData = 0;
1446*e5436536SAndroid Build Coastguard Worker     } else {
1447*e5436536SAndroid Build Coastguard Worker       INT valBits;
1448*e5436536SAndroid Build Coastguard Worker 
1449*e5436536SAndroid Build Coastguard Worker       if (bsPayLen > 0) {
1450*e5436536SAndroid Build Coastguard Worker         valBits = bsPayLen - ((INT)startPos - (INT)FDKgetValidBits(hBs));
1451*e5436536SAndroid Build Coastguard Worker       } else {
1452*e5436536SAndroid Build Coastguard Worker         valBits = (INT)FDKgetValidBits(hBs);
1453*e5436536SAndroid Build Coastguard Worker       }
1454*e5436536SAndroid Build Coastguard Worker 
1455*e5436536SAndroid Build Coastguard Worker       /* sanity check of remaining bits */
1456*e5436536SAndroid Build Coastguard Worker       if (valBits < 0) {
1457*e5436536SAndroid Build Coastguard Worker         fDoDecodeSbrData = 0;
1458*e5436536SAndroid Build Coastguard Worker       } else {
1459*e5436536SAndroid Build Coastguard Worker         switch (self->coreCodec) {
1460*e5436536SAndroid Build Coastguard Worker           case AOT_SBR:
1461*e5436536SAndroid Build Coastguard Worker           case AOT_PS:
1462*e5436536SAndroid Build Coastguard Worker           case AOT_AAC_LC: {
1463*e5436536SAndroid Build Coastguard Worker             /* This sanity check is only meaningful with General Audio
1464*e5436536SAndroid Build Coastguard Worker              * bitstreams */
1465*e5436536SAndroid Build Coastguard Worker             alignBits = valBits & 0x7;
1466*e5436536SAndroid Build Coastguard Worker 
1467*e5436536SAndroid Build Coastguard Worker             if (valBits > alignBits) {
1468*e5436536SAndroid Build Coastguard Worker               fDoDecodeSbrData = 0;
1469*e5436536SAndroid Build Coastguard Worker             }
1470*e5436536SAndroid Build Coastguard Worker           } break;
1471*e5436536SAndroid Build Coastguard Worker           default:
1472*e5436536SAndroid Build Coastguard Worker             /* No sanity check available */
1473*e5436536SAndroid Build Coastguard Worker             break;
1474*e5436536SAndroid Build Coastguard Worker         }
1475*e5436536SAndroid Build Coastguard Worker       }
1476*e5436536SAndroid Build Coastguard Worker     }
1477*e5436536SAndroid Build Coastguard Worker   } else {
1478*e5436536SAndroid Build Coastguard Worker     /* The returned bit count will not be the actual payload size since we did
1479*e5436536SAndroid Build Coastguard Worker        not parse the frame data. Return an error so that the caller can react
1480*e5436536SAndroid Build Coastguard Worker        respectively. */
1481*e5436536SAndroid Build Coastguard Worker     errorStatus = SBRDEC_PARSE_ERROR;
1482*e5436536SAndroid Build Coastguard Worker   }
1483*e5436536SAndroid Build Coastguard Worker 
1484*e5436536SAndroid Build Coastguard Worker   if (crcFlag && (hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) {
1485*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, alignBits);
1486*e5436536SAndroid Build Coastguard Worker     FDKcrcEndReg(&crcInfo, hBs, crcReg); /* End CRC region */
1487*e5436536SAndroid Build Coastguard Worker     FDKpushBack(hBs, alignBits);
1488*e5436536SAndroid Build Coastguard Worker     /* Check CRC */
1489*e5436536SAndroid Build Coastguard Worker     if ((FDKcrcGetCRC(&crcInfo) ^ crcStartValue) != sbrCrc) {
1490*e5436536SAndroid Build Coastguard Worker       fDoDecodeSbrData = 0;
1491*e5436536SAndroid Build Coastguard Worker       if (headerStatus != HEADER_NOT_PRESENT) {
1492*e5436536SAndroid Build Coastguard Worker         headerStatus = HEADER_ERROR;
1493*e5436536SAndroid Build Coastguard Worker         hSbrHeader->syncState = SBR_NOT_INITIALIZED;
1494*e5436536SAndroid Build Coastguard Worker       }
1495*e5436536SAndroid Build Coastguard Worker     }
1496*e5436536SAndroid Build Coastguard Worker   }
1497*e5436536SAndroid Build Coastguard Worker 
1498*e5436536SAndroid Build Coastguard Worker   if (!fDoDecodeSbrData) {
1499*e5436536SAndroid Build Coastguard Worker     /* Set error flag for this slot to trigger concealment */
1500*e5436536SAndroid Build Coastguard Worker     setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR);
1501*e5436536SAndroid Build Coastguard Worker     /* restore old frameData for concealment */
1502*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(hFrameDataLeft, &frameDataLeftCopy, sizeof(SBR_FRAME_DATA));
1503*e5436536SAndroid Build Coastguard Worker     if (stereo) {
1504*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(hFrameDataRight, &frameDataRightCopy, sizeof(SBR_FRAME_DATA));
1505*e5436536SAndroid Build Coastguard Worker     }
1506*e5436536SAndroid Build Coastguard Worker     errorStatus = SBRDEC_PARSE_ERROR;
1507*e5436536SAndroid Build Coastguard Worker   } else {
1508*e5436536SAndroid Build Coastguard Worker     /* Everything seems to be ok so clear the error flag */
1509*e5436536SAndroid Build Coastguard Worker     setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_OK);
1510*e5436536SAndroid Build Coastguard Worker   }
1511*e5436536SAndroid Build Coastguard Worker 
1512*e5436536SAndroid Build Coastguard Worker   if (!stereo) {
1513*e5436536SAndroid Build Coastguard Worker     /* Turn coupling off explicitely to avoid access to absent right frame data
1514*e5436536SAndroid Build Coastguard Worker        that might occur with corrupt bitstreams. */
1515*e5436536SAndroid Build Coastguard Worker     hFrameDataLeft->coupling = COUPLING_OFF;
1516*e5436536SAndroid Build Coastguard Worker   }
1517*e5436536SAndroid Build Coastguard Worker 
1518*e5436536SAndroid Build Coastguard Worker bail:
1519*e5436536SAndroid Build Coastguard Worker 
1520*e5436536SAndroid Build Coastguard Worker   if (self != NULL) {
1521*e5436536SAndroid Build Coastguard Worker     if (self->flags & SBRDEC_SYNTAX_DRM) {
1522*e5436536SAndroid Build Coastguard Worker       hBs = hBsOriginal;
1523*e5436536SAndroid Build Coastguard Worker     }
1524*e5436536SAndroid Build Coastguard Worker 
1525*e5436536SAndroid Build Coastguard Worker     if (errorStatus != SBRDEC_NOT_INITIALIZED) {
1526*e5436536SAndroid Build Coastguard Worker       int useOldHdr =
1527*e5436536SAndroid Build Coastguard Worker           ((headerStatus == HEADER_NOT_PRESENT) ||
1528*e5436536SAndroid Build Coastguard Worker            (headerStatus == HEADER_ERROR) ||
1529*e5436536SAndroid Build Coastguard Worker            (headerStatus == HEADER_RESET && errorStatus == SBRDEC_PARSE_ERROR))
1530*e5436536SAndroid Build Coastguard Worker               ? 1
1531*e5436536SAndroid Build Coastguard Worker               : 0;
1532*e5436536SAndroid Build Coastguard Worker 
1533*e5436536SAndroid Build Coastguard Worker       if (!useOldHdr && (thisHdrSlot != lastHdrSlot) && (hSbrHeader != NULL)) {
1534*e5436536SAndroid Build Coastguard Worker         useOldHdr |=
1535*e5436536SAndroid Build Coastguard Worker             (compareSbrHeader(hSbrHeader,
1536*e5436536SAndroid Build Coastguard Worker                               &self->sbrHeader[elementIndex][lastHdrSlot]) == 0)
1537*e5436536SAndroid Build Coastguard Worker                 ? 1
1538*e5436536SAndroid Build Coastguard Worker                 : 0;
1539*e5436536SAndroid Build Coastguard Worker       }
1540*e5436536SAndroid Build Coastguard Worker 
1541*e5436536SAndroid Build Coastguard Worker       if (hSbrElement != NULL) {
1542*e5436536SAndroid Build Coastguard Worker         if (useOldHdr != 0) {
1543*e5436536SAndroid Build Coastguard Worker           /* Use the old header for this frame */
1544*e5436536SAndroid Build Coastguard Worker           hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot;
1545*e5436536SAndroid Build Coastguard Worker         } else {
1546*e5436536SAndroid Build Coastguard Worker           /* Use the new header for this frame */
1547*e5436536SAndroid Build Coastguard Worker           hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot;
1548*e5436536SAndroid Build Coastguard Worker         }
1549*e5436536SAndroid Build Coastguard Worker 
1550*e5436536SAndroid Build Coastguard Worker         /* Move frame pointer to the next slot which is up to be decoded/applied
1551*e5436536SAndroid Build Coastguard Worker          * next */
1552*e5436536SAndroid Build Coastguard Worker         hSbrElement->useFrameSlot =
1553*e5436536SAndroid Build Coastguard Worker             (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1);
1554*e5436536SAndroid Build Coastguard Worker       }
1555*e5436536SAndroid Build Coastguard Worker     }
1556*e5436536SAndroid Build Coastguard Worker   }
1557*e5436536SAndroid Build Coastguard Worker 
1558*e5436536SAndroid Build Coastguard Worker   *count -= startPos - (INT)FDKgetValidBits(hBs);
1559*e5436536SAndroid Build Coastguard Worker 
1560*e5436536SAndroid Build Coastguard Worker   return errorStatus;
1561*e5436536SAndroid Build Coastguard Worker }
1562*e5436536SAndroid Build Coastguard Worker 
1563*e5436536SAndroid Build Coastguard Worker /**
1564*e5436536SAndroid Build Coastguard Worker  * \brief Render one SBR element into time domain signal.
1565*e5436536SAndroid Build Coastguard Worker  * \param self SBR decoder handle
1566*e5436536SAndroid Build Coastguard Worker  * \param timeData pointer to output buffer
1567*e5436536SAndroid Build Coastguard Worker  * \param channelMapping pointer to UCHAR array where next 2 channel offsets are
1568*e5436536SAndroid Build Coastguard Worker  * stored.
1569*e5436536SAndroid Build Coastguard Worker  * \param elementIndex enumerating index of the SBR element to render.
1570*e5436536SAndroid Build Coastguard Worker  * \param numInChannels number of channels from core coder.
1571*e5436536SAndroid Build Coastguard Worker  * \param numOutChannels pointer to a location to return number of output
1572*e5436536SAndroid Build Coastguard Worker  * channels.
1573*e5436536SAndroid Build Coastguard Worker  * \param psPossible flag indicating if PS is possible or not.
1574*e5436536SAndroid Build Coastguard Worker  * \return SBRDEC_OK if successfull, else error code
1575*e5436536SAndroid Build Coastguard Worker  */
sbrDecoder_DecodeElement(HANDLE_SBRDECODER self,LONG * input,LONG * timeData,const int timeDataSize,const FDK_channelMapDescr * const mapDescr,const int mapIdx,int channelIndex,const int elementIndex,const int numInChannels,int * numOutChannels,const int psPossible)1576*e5436536SAndroid Build Coastguard Worker static SBR_ERROR sbrDecoder_DecodeElement(
1577*e5436536SAndroid Build Coastguard Worker     HANDLE_SBRDECODER self, LONG *input, LONG *timeData, const int timeDataSize,
1578*e5436536SAndroid Build Coastguard Worker     const FDK_channelMapDescr *const mapDescr, const int mapIdx,
1579*e5436536SAndroid Build Coastguard Worker     int channelIndex, const int elementIndex, const int numInChannels,
1580*e5436536SAndroid Build Coastguard Worker     int *numOutChannels, const int psPossible) {
1581*e5436536SAndroid Build Coastguard Worker   SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex];
1582*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_CHANNEL *pSbrChannel =
1583*e5436536SAndroid Build Coastguard Worker       self->pSbrElement[elementIndex]->pSbrChannel;
1584*e5436536SAndroid Build Coastguard Worker   HANDLE_SBR_HEADER_DATA hSbrHeader =
1585*e5436536SAndroid Build Coastguard Worker       &self->sbrHeader[elementIndex]
1586*e5436536SAndroid Build Coastguard Worker                       [hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
1587*e5436536SAndroid Build Coastguard Worker   HANDLE_PS_DEC h_ps_d = self->hParametricStereoDec;
1588*e5436536SAndroid Build Coastguard Worker 
1589*e5436536SAndroid Build Coastguard Worker   /* get memory for frame data from scratch */
1590*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_DATA *hFrameDataLeft = NULL;
1591*e5436536SAndroid Build Coastguard Worker   SBR_FRAME_DATA *hFrameDataRight = NULL;
1592*e5436536SAndroid Build Coastguard Worker 
1593*e5436536SAndroid Build Coastguard Worker   SBR_ERROR errorStatus = SBRDEC_OK;
1594*e5436536SAndroid Build Coastguard Worker 
1595*e5436536SAndroid Build Coastguard Worker   INT strideOut, offset0 = 255, offset0_block = 0, offset1 = 255,
1596*e5436536SAndroid Build Coastguard Worker                  offset1_block = 0;
1597*e5436536SAndroid Build Coastguard Worker   INT codecFrameSize = self->codecFrameSize;
1598*e5436536SAndroid Build Coastguard Worker 
1599*e5436536SAndroid Build Coastguard Worker   int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
1600*e5436536SAndroid Build Coastguard Worker   int numElementChannels =
1601*e5436536SAndroid Build Coastguard Worker       hSbrElement
1602*e5436536SAndroid Build Coastguard Worker           ->nChannels; /* Number of channels of the current SBR element */
1603*e5436536SAndroid Build Coastguard Worker 
1604*e5436536SAndroid Build Coastguard Worker   hFrameDataLeft =
1605*e5436536SAndroid Build Coastguard Worker       &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
1606*e5436536SAndroid Build Coastguard Worker   if (stereo) {
1607*e5436536SAndroid Build Coastguard Worker     hFrameDataRight =
1608*e5436536SAndroid Build Coastguard Worker         &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
1609*e5436536SAndroid Build Coastguard Worker   }
1610*e5436536SAndroid Build Coastguard Worker 
1611*e5436536SAndroid Build Coastguard Worker   if (self->flags & SBRDEC_FLUSH) {
1612*e5436536SAndroid Build Coastguard Worker     if (self->numFlushedFrames > self->numDelayFrames) {
1613*e5436536SAndroid Build Coastguard Worker       int hdrIdx;
1614*e5436536SAndroid Build Coastguard Worker       /* No valid SBR payload available, hence switch to upsampling (in all
1615*e5436536SAndroid Build Coastguard Worker        * headers) */
1616*e5436536SAndroid Build Coastguard Worker       for (hdrIdx = 0; hdrIdx < ((1) + 1); hdrIdx += 1) {
1617*e5436536SAndroid Build Coastguard Worker         if (self->sbrHeader[elementIndex][hdrIdx].syncState > UPSAMPLING) {
1618*e5436536SAndroid Build Coastguard Worker           self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
1619*e5436536SAndroid Build Coastguard Worker         }
1620*e5436536SAndroid Build Coastguard Worker       }
1621*e5436536SAndroid Build Coastguard Worker     } else {
1622*e5436536SAndroid Build Coastguard Worker       /* Move frame pointer to the next slot which is up to be decoded/applied
1623*e5436536SAndroid Build Coastguard Worker        * next */
1624*e5436536SAndroid Build Coastguard Worker       hSbrElement->useFrameSlot =
1625*e5436536SAndroid Build Coastguard Worker           (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1);
1626*e5436536SAndroid Build Coastguard Worker       /* Update header and frame data pointer because they have already been set
1627*e5436536SAndroid Build Coastguard Worker        */
1628*e5436536SAndroid Build Coastguard Worker       hSbrHeader =
1629*e5436536SAndroid Build Coastguard Worker           &self->sbrHeader[elementIndex]
1630*e5436536SAndroid Build Coastguard Worker                           [hSbrElement
1631*e5436536SAndroid Build Coastguard Worker                                ->useHeaderSlot[hSbrElement->useFrameSlot]];
1632*e5436536SAndroid Build Coastguard Worker       hFrameDataLeft =
1633*e5436536SAndroid Build Coastguard Worker           &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
1634*e5436536SAndroid Build Coastguard Worker       if (stereo) {
1635*e5436536SAndroid Build Coastguard Worker         hFrameDataRight =
1636*e5436536SAndroid Build Coastguard Worker             &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
1637*e5436536SAndroid Build Coastguard Worker       }
1638*e5436536SAndroid Build Coastguard Worker     }
1639*e5436536SAndroid Build Coastguard Worker   }
1640*e5436536SAndroid Build Coastguard Worker 
1641*e5436536SAndroid Build Coastguard Worker   /* Update the header error flag */
1642*e5436536SAndroid Build Coastguard Worker   hSbrHeader->frameErrorFlag =
1643*e5436536SAndroid Build Coastguard Worker       hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot];
1644*e5436536SAndroid Build Coastguard Worker 
1645*e5436536SAndroid Build Coastguard Worker   /*
1646*e5436536SAndroid Build Coastguard Worker      Prepare filterbank for upsampling if no valid bit stream data is available.
1647*e5436536SAndroid Build Coastguard Worker    */
1648*e5436536SAndroid Build Coastguard Worker   if (hSbrHeader->syncState == SBR_NOT_INITIALIZED) {
1649*e5436536SAndroid Build Coastguard Worker     errorStatus =
1650*e5436536SAndroid Build Coastguard Worker         initHeaderData(hSbrHeader, self->sampleRateIn, self->sampleRateOut,
1651*e5436536SAndroid Build Coastguard Worker                        self->downscaleFactor, codecFrameSize, self->flags,
1652*e5436536SAndroid Build Coastguard Worker                        1 /* SET_DEFAULT_HDR */
1653*e5436536SAndroid Build Coastguard Worker         );
1654*e5436536SAndroid Build Coastguard Worker 
1655*e5436536SAndroid Build Coastguard Worker     if (errorStatus != SBRDEC_OK) {
1656*e5436536SAndroid Build Coastguard Worker       return errorStatus;
1657*e5436536SAndroid Build Coastguard Worker     }
1658*e5436536SAndroid Build Coastguard Worker 
1659*e5436536SAndroid Build Coastguard Worker     hSbrHeader->syncState = UPSAMPLING;
1660*e5436536SAndroid Build Coastguard Worker 
1661*e5436536SAndroid Build Coastguard Worker     errorStatus = sbrDecoder_HeaderUpdate(self, hSbrHeader, HEADER_NOT_PRESENT,
1662*e5436536SAndroid Build Coastguard Worker                                           pSbrChannel, hSbrElement->nChannels);
1663*e5436536SAndroid Build Coastguard Worker 
1664*e5436536SAndroid Build Coastguard Worker     if (errorStatus != SBRDEC_OK) {
1665*e5436536SAndroid Build Coastguard Worker       hSbrHeader->syncState = SBR_NOT_INITIALIZED;
1666*e5436536SAndroid Build Coastguard Worker       return errorStatus;
1667*e5436536SAndroid Build Coastguard Worker     }
1668*e5436536SAndroid Build Coastguard Worker   }
1669*e5436536SAndroid Build Coastguard Worker 
1670*e5436536SAndroid Build Coastguard Worker   /* reset */
1671*e5436536SAndroid Build Coastguard Worker   if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) {
1672*e5436536SAndroid Build Coastguard Worker     int ch;
1673*e5436536SAndroid Build Coastguard Worker     int applySbrProc = (hSbrHeader->syncState == SBR_ACTIVE ||
1674*e5436536SAndroid Build Coastguard Worker                         (hSbrHeader->frameErrorFlag == 0 &&
1675*e5436536SAndroid Build Coastguard Worker                          hSbrHeader->syncState == SBR_HEADER));
1676*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < numElementChannels; ch++) {
1677*e5436536SAndroid Build Coastguard Worker       SBR_ERROR errorStatusTmp = SBRDEC_OK;
1678*e5436536SAndroid Build Coastguard Worker 
1679*e5436536SAndroid Build Coastguard Worker       errorStatusTmp = resetSbrDec(
1680*e5436536SAndroid Build Coastguard Worker           &pSbrChannel[ch]->SbrDec, hSbrHeader, &pSbrChannel[ch]->prevFrameData,
1681*e5436536SAndroid Build Coastguard Worker           self->synDownsampleFac, self->flags, pSbrChannel[ch]->frameData);
1682*e5436536SAndroid Build Coastguard Worker 
1683*e5436536SAndroid Build Coastguard Worker       if (errorStatusTmp != SBRDEC_OK) {
1684*e5436536SAndroid Build Coastguard Worker         hSbrHeader->syncState = UPSAMPLING;
1685*e5436536SAndroid Build Coastguard Worker       }
1686*e5436536SAndroid Build Coastguard Worker     }
1687*e5436536SAndroid Build Coastguard Worker     if (applySbrProc) {
1688*e5436536SAndroid Build Coastguard Worker       hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET;
1689*e5436536SAndroid Build Coastguard Worker     }
1690*e5436536SAndroid Build Coastguard Worker   }
1691*e5436536SAndroid Build Coastguard Worker 
1692*e5436536SAndroid Build Coastguard Worker   /* decoding */
1693*e5436536SAndroid Build Coastguard Worker   if ((hSbrHeader->syncState == SBR_ACTIVE) ||
1694*e5436536SAndroid Build Coastguard Worker       ((hSbrHeader->syncState == SBR_HEADER) &&
1695*e5436536SAndroid Build Coastguard Worker        (hSbrHeader->frameErrorFlag == 0))) {
1696*e5436536SAndroid Build Coastguard Worker     errorStatus = SBRDEC_OK;
1697*e5436536SAndroid Build Coastguard Worker 
1698*e5436536SAndroid Build Coastguard Worker     decodeSbrData(hSbrHeader, hFrameDataLeft, &pSbrChannel[0]->prevFrameData,
1699*e5436536SAndroid Build Coastguard Worker                   (stereo) ? hFrameDataRight : NULL,
1700*e5436536SAndroid Build Coastguard Worker                   (stereo) ? &pSbrChannel[1]->prevFrameData : NULL);
1701*e5436536SAndroid Build Coastguard Worker 
1702*e5436536SAndroid Build Coastguard Worker     /* Now we have a full parameter set and can do parameter
1703*e5436536SAndroid Build Coastguard Worker        based concealment instead of plain upsampling. */
1704*e5436536SAndroid Build Coastguard Worker     hSbrHeader->syncState = SBR_ACTIVE;
1705*e5436536SAndroid Build Coastguard Worker   }
1706*e5436536SAndroid Build Coastguard Worker 
1707*e5436536SAndroid Build Coastguard Worker   if (timeDataSize <
1708*e5436536SAndroid Build Coastguard Worker       hSbrHeader->numberTimeSlots * hSbrHeader->timeStep *
1709*e5436536SAndroid Build Coastguard Worker           self->pQmfDomain->globalConf.nBandsSynthesis *
1710*e5436536SAndroid Build Coastguard Worker           (psPossible ? fMax(2, numInChannels) : numInChannels)) {
1711*e5436536SAndroid Build Coastguard Worker     return SBRDEC_OUTPUT_BUFFER_TOO_SMALL;
1712*e5436536SAndroid Build Coastguard Worker   }
1713*e5436536SAndroid Build Coastguard Worker 
1714*e5436536SAndroid Build Coastguard Worker   {
1715*e5436536SAndroid Build Coastguard Worker     self->flags &= ~SBRDEC_PS_DECODED;
1716*e5436536SAndroid Build Coastguard Worker     C_ALLOC_SCRATCH_START(pPsScratch, struct PS_DEC_COEFFICIENTS, 1)
1717*e5436536SAndroid Build Coastguard Worker 
1718*e5436536SAndroid Build Coastguard Worker     /* decode PS data if available */
1719*e5436536SAndroid Build Coastguard Worker     if (h_ps_d != NULL && psPossible && (hSbrHeader->syncState == SBR_ACTIVE)) {
1720*e5436536SAndroid Build Coastguard Worker       int applyPs = 1;
1721*e5436536SAndroid Build Coastguard Worker 
1722*e5436536SAndroid Build Coastguard Worker       /* define which frame delay line slot to process */
1723*e5436536SAndroid Build Coastguard Worker       h_ps_d->processSlot = hSbrElement->useFrameSlot;
1724*e5436536SAndroid Build Coastguard Worker 
1725*e5436536SAndroid Build Coastguard Worker       applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag, pPsScratch);
1726*e5436536SAndroid Build Coastguard Worker       self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0;
1727*e5436536SAndroid Build Coastguard Worker     }
1728*e5436536SAndroid Build Coastguard Worker 
1729*e5436536SAndroid Build Coastguard Worker     offset0 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex, mapIdx);
1730*e5436536SAndroid Build Coastguard Worker     offset0_block = offset0 * codecFrameSize;
1731*e5436536SAndroid Build Coastguard Worker     if (stereo || psPossible) {
1732*e5436536SAndroid Build Coastguard Worker       /* the value of offset1 only matters if the condition is true, however if
1733*e5436536SAndroid Build Coastguard Worker       it is not true channelIndex+1 may exceed the channel map resutling in an
1734*e5436536SAndroid Build Coastguard Worker       error, though the value of offset1 is actually meaningless. This is
1735*e5436536SAndroid Build Coastguard Worker       prevented here. */
1736*e5436536SAndroid Build Coastguard Worker       offset1 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex + 1, mapIdx);
1737*e5436536SAndroid Build Coastguard Worker       offset1_block = offset1 * codecFrameSize;
1738*e5436536SAndroid Build Coastguard Worker     }
1739*e5436536SAndroid Build Coastguard Worker     /* Set strides for reading and writing */
1740*e5436536SAndroid Build Coastguard Worker     if (psPossible)
1741*e5436536SAndroid Build Coastguard Worker       strideOut = (numInChannels < 2) ? 2 : numInChannels;
1742*e5436536SAndroid Build Coastguard Worker     else
1743*e5436536SAndroid Build Coastguard Worker       strideOut = numInChannels;
1744*e5436536SAndroid Build Coastguard Worker 
1745*e5436536SAndroid Build Coastguard Worker     /* use same buffers for left and right channel and apply PS per timeslot */
1746*e5436536SAndroid Build Coastguard Worker     /* Process left channel */
1747*e5436536SAndroid Build Coastguard Worker     sbr_dec(&pSbrChannel[0]->SbrDec, input + offset0_block, timeData + offset0,
1748*e5436536SAndroid Build Coastguard Worker             (self->flags & SBRDEC_PS_DECODED) ? &pSbrChannel[1]->SbrDec : NULL,
1749*e5436536SAndroid Build Coastguard Worker             timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft,
1750*e5436536SAndroid Build Coastguard Worker             &pSbrChannel[0]->prevFrameData,
1751*e5436536SAndroid Build Coastguard Worker             (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags,
1752*e5436536SAndroid Build Coastguard Worker             codecFrameSize, self->sbrInDataHeadroom);
1753*e5436536SAndroid Build Coastguard Worker 
1754*e5436536SAndroid Build Coastguard Worker     if (stereo) {
1755*e5436536SAndroid Build Coastguard Worker       /* Process right channel */
1756*e5436536SAndroid Build Coastguard Worker       sbr_dec(&pSbrChannel[1]->SbrDec, input + offset1_block,
1757*e5436536SAndroid Build Coastguard Worker               timeData + offset1, NULL, NULL, strideOut, hSbrHeader,
1758*e5436536SAndroid Build Coastguard Worker               hFrameDataRight, &pSbrChannel[1]->prevFrameData,
1759*e5436536SAndroid Build Coastguard Worker               (hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags,
1760*e5436536SAndroid Build Coastguard Worker               codecFrameSize, self->sbrInDataHeadroom);
1761*e5436536SAndroid Build Coastguard Worker     }
1762*e5436536SAndroid Build Coastguard Worker 
1763*e5436536SAndroid Build Coastguard Worker     C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1)
1764*e5436536SAndroid Build Coastguard Worker   }
1765*e5436536SAndroid Build Coastguard Worker 
1766*e5436536SAndroid Build Coastguard Worker   if (h_ps_d != NULL) {
1767*e5436536SAndroid Build Coastguard Worker     /* save PS status for next run */
1768*e5436536SAndroid Build Coastguard Worker     h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0;
1769*e5436536SAndroid Build Coastguard Worker   }
1770*e5436536SAndroid Build Coastguard Worker 
1771*e5436536SAndroid Build Coastguard Worker   if (psPossible && !(self->flags & SBRDEC_SKIP_QMF_SYN)) {
1772*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(strideOut > 1);
1773*e5436536SAndroid Build Coastguard Worker     if (!(self->flags & SBRDEC_PS_DECODED)) {
1774*e5436536SAndroid Build Coastguard Worker       /* A decoder which is able to decode PS has to produce a stereo output
1775*e5436536SAndroid Build Coastguard Worker        * even if no PS data is available. */
1776*e5436536SAndroid Build Coastguard Worker       /* So copy left channel to right channel. */
1777*e5436536SAndroid Build Coastguard Worker       int copyFrameSize =
1778*e5436536SAndroid Build Coastguard Worker           codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels;
1779*e5436536SAndroid Build Coastguard Worker       copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels;
1780*e5436536SAndroid Build Coastguard Worker       LONG *ptr;
1781*e5436536SAndroid Build Coastguard Worker       INT i;
1782*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT(strideOut == 2);
1783*e5436536SAndroid Build Coastguard Worker 
1784*e5436536SAndroid Build Coastguard Worker       ptr = timeData;
1785*e5436536SAndroid Build Coastguard Worker       for (i = copyFrameSize >> 1; i--;) {
1786*e5436536SAndroid Build Coastguard Worker         LONG tmp; /* This temporal variable is required because some compilers
1787*e5436536SAndroid Build Coastguard Worker                      can't do *ptr++ = *ptr++ correctly. */
1788*e5436536SAndroid Build Coastguard Worker         tmp = *ptr++;
1789*e5436536SAndroid Build Coastguard Worker         *ptr++ = tmp;
1790*e5436536SAndroid Build Coastguard Worker         tmp = *ptr++;
1791*e5436536SAndroid Build Coastguard Worker         *ptr++ = tmp;
1792*e5436536SAndroid Build Coastguard Worker       }
1793*e5436536SAndroid Build Coastguard Worker     }
1794*e5436536SAndroid Build Coastguard Worker     *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */
1795*e5436536SAndroid Build Coastguard Worker   }
1796*e5436536SAndroid Build Coastguard Worker 
1797*e5436536SAndroid Build Coastguard Worker   return errorStatus;
1798*e5436536SAndroid Build Coastguard Worker }
1799*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_Apply(HANDLE_SBRDECODER self,LONG * input,LONG * timeData,const int timeDataSize,int * numChannels,int * sampleRate,const FDK_channelMapDescr * const mapDescr,const int mapIdx,const int coreDecodedOk,UCHAR * psDecoded,const INT inDataHeadroom,INT * outDataHeadroom)1800*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, LONG *input, LONG *timeData,
1801*e5436536SAndroid Build Coastguard Worker                            const int timeDataSize, int *numChannels,
1802*e5436536SAndroid Build Coastguard Worker                            int *sampleRate,
1803*e5436536SAndroid Build Coastguard Worker                            const FDK_channelMapDescr *const mapDescr,
1804*e5436536SAndroid Build Coastguard Worker                            const int mapIdx, const int coreDecodedOk,
1805*e5436536SAndroid Build Coastguard Worker                            UCHAR *psDecoded, const INT inDataHeadroom,
1806*e5436536SAndroid Build Coastguard Worker                            INT *outDataHeadroom) {
1807*e5436536SAndroid Build Coastguard Worker   SBR_ERROR errorStatus = SBRDEC_OK;
1808*e5436536SAndroid Build Coastguard Worker 
1809*e5436536SAndroid Build Coastguard Worker   int psPossible;
1810*e5436536SAndroid Build Coastguard Worker   int sbrElementNum;
1811*e5436536SAndroid Build Coastguard Worker   int numCoreChannels;
1812*e5436536SAndroid Build Coastguard Worker   int numSbrChannels = 0;
1813*e5436536SAndroid Build Coastguard Worker 
1814*e5436536SAndroid Build Coastguard Worker   if ((self == NULL) || (timeData == NULL) || (numChannels == NULL) ||
1815*e5436536SAndroid Build Coastguard Worker       (sampleRate == NULL) || (psDecoded == NULL) ||
1816*e5436536SAndroid Build Coastguard Worker       !FDK_chMapDescr_isValid(mapDescr)) {
1817*e5436536SAndroid Build Coastguard Worker     return SBRDEC_INVALID_ARGUMENT;
1818*e5436536SAndroid Build Coastguard Worker   }
1819*e5436536SAndroid Build Coastguard Worker 
1820*e5436536SAndroid Build Coastguard Worker   psPossible = *psDecoded;
1821*e5436536SAndroid Build Coastguard Worker   numCoreChannels = *numChannels;
1822*e5436536SAndroid Build Coastguard Worker   if (numCoreChannels <= 0) {
1823*e5436536SAndroid Build Coastguard Worker     return SBRDEC_INVALID_ARGUMENT;
1824*e5436536SAndroid Build Coastguard Worker   }
1825*e5436536SAndroid Build Coastguard Worker 
1826*e5436536SAndroid Build Coastguard Worker   if (self->numSbrElements < 1) {
1827*e5436536SAndroid Build Coastguard Worker     /* exit immediately to avoid access violations */
1828*e5436536SAndroid Build Coastguard Worker     return SBRDEC_NOT_INITIALIZED;
1829*e5436536SAndroid Build Coastguard Worker   }
1830*e5436536SAndroid Build Coastguard Worker 
1831*e5436536SAndroid Build Coastguard Worker   /* Sanity check of allocated SBR elements. */
1832*e5436536SAndroid Build Coastguard Worker   for (sbrElementNum = 0; sbrElementNum < self->numSbrElements;
1833*e5436536SAndroid Build Coastguard Worker        sbrElementNum++) {
1834*e5436536SAndroid Build Coastguard Worker     if (self->pSbrElement[sbrElementNum] == NULL) {
1835*e5436536SAndroid Build Coastguard Worker       return SBRDEC_NOT_INITIALIZED;
1836*e5436536SAndroid Build Coastguard Worker     }
1837*e5436536SAndroid Build Coastguard Worker   }
1838*e5436536SAndroid Build Coastguard Worker 
1839*e5436536SAndroid Build Coastguard Worker   if (self->numSbrElements != 1 || self->pSbrElement[0]->elementID != ID_SCE) {
1840*e5436536SAndroid Build Coastguard Worker     psPossible = 0;
1841*e5436536SAndroid Build Coastguard Worker   }
1842*e5436536SAndroid Build Coastguard Worker 
1843*e5436536SAndroid Build Coastguard Worker   self->sbrInDataHeadroom = inDataHeadroom;
1844*e5436536SAndroid Build Coastguard Worker   *outDataHeadroom = (INT)(8);
1845*e5436536SAndroid Build Coastguard Worker 
1846*e5436536SAndroid Build Coastguard Worker   /* Make sure that even if no SBR data was found/parsed *psDecoded is returned
1847*e5436536SAndroid Build Coastguard Worker    * 1 if psPossible was 0. */
1848*e5436536SAndroid Build Coastguard Worker   if (psPossible == 0) {
1849*e5436536SAndroid Build Coastguard Worker     self->flags &= ~SBRDEC_PS_DECODED;
1850*e5436536SAndroid Build Coastguard Worker   }
1851*e5436536SAndroid Build Coastguard Worker 
1852*e5436536SAndroid Build Coastguard Worker   /* replaces channel based reset inside sbr_dec() */
1853*e5436536SAndroid Build Coastguard Worker   if (((self->flags & SBRDEC_LOW_POWER) ? 1 : 0) !=
1854*e5436536SAndroid Build Coastguard Worker       ((self->pQmfDomain->globalConf.flags & QMF_FLAG_LP) ? 1 : 0)) {
1855*e5436536SAndroid Build Coastguard Worker     if (self->flags & SBRDEC_LOW_POWER) {
1856*e5436536SAndroid Build Coastguard Worker       self->pQmfDomain->globalConf.flags |= QMF_FLAG_LP;
1857*e5436536SAndroid Build Coastguard Worker       self->pQmfDomain->globalConf.flags_requested |= QMF_FLAG_LP;
1858*e5436536SAndroid Build Coastguard Worker     } else {
1859*e5436536SAndroid Build Coastguard Worker       self->pQmfDomain->globalConf.flags &= ~QMF_FLAG_LP;
1860*e5436536SAndroid Build Coastguard Worker       self->pQmfDomain->globalConf.flags_requested &= ~QMF_FLAG_LP;
1861*e5436536SAndroid Build Coastguard Worker     }
1862*e5436536SAndroid Build Coastguard Worker     if (FDK_QmfDomain_InitFilterBank(self->pQmfDomain, QMF_FLAG_KEEP_STATES)) {
1863*e5436536SAndroid Build Coastguard Worker       return SBRDEC_UNSUPPORTED_CONFIG;
1864*e5436536SAndroid Build Coastguard Worker     }
1865*e5436536SAndroid Build Coastguard Worker   }
1866*e5436536SAndroid Build Coastguard Worker   if (self->numSbrChannels > self->pQmfDomain->globalConf.nInputChannels) {
1867*e5436536SAndroid Build Coastguard Worker     return SBRDEC_UNSUPPORTED_CONFIG;
1868*e5436536SAndroid Build Coastguard Worker   }
1869*e5436536SAndroid Build Coastguard Worker 
1870*e5436536SAndroid Build Coastguard Worker   if (self->flags & SBRDEC_FLUSH) {
1871*e5436536SAndroid Build Coastguard Worker     /* flushing is signalized, hence increment the flush frame counter */
1872*e5436536SAndroid Build Coastguard Worker     self->numFlushedFrames++;
1873*e5436536SAndroid Build Coastguard Worker   } else {
1874*e5436536SAndroid Build Coastguard Worker     /* no flushing is signalized, hence reset the flush frame counter */
1875*e5436536SAndroid Build Coastguard Worker     self->numFlushedFrames = 0;
1876*e5436536SAndroid Build Coastguard Worker   }
1877*e5436536SAndroid Build Coastguard Worker 
1878*e5436536SAndroid Build Coastguard Worker   /* Loop over SBR elements */
1879*e5436536SAndroid Build Coastguard Worker   for (sbrElementNum = 0; sbrElementNum < self->numSbrElements;
1880*e5436536SAndroid Build Coastguard Worker        sbrElementNum++) {
1881*e5436536SAndroid Build Coastguard Worker     int numElementChan;
1882*e5436536SAndroid Build Coastguard Worker 
1883*e5436536SAndroid Build Coastguard Worker     if (psPossible &&
1884*e5436536SAndroid Build Coastguard Worker         self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) {
1885*e5436536SAndroid Build Coastguard Worker       /* Disable PS and try decoding SBR mono. */
1886*e5436536SAndroid Build Coastguard Worker       psPossible = 0;
1887*e5436536SAndroid Build Coastguard Worker     }
1888*e5436536SAndroid Build Coastguard Worker 
1889*e5436536SAndroid Build Coastguard Worker     numElementChan =
1890*e5436536SAndroid Build Coastguard Worker         (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1;
1891*e5436536SAndroid Build Coastguard Worker 
1892*e5436536SAndroid Build Coastguard Worker     /* If core signal is bad then force upsampling */
1893*e5436536SAndroid Build Coastguard Worker     if (!coreDecodedOk) {
1894*e5436536SAndroid Build Coastguard Worker       setFrameErrorFlag(self->pSbrElement[sbrElementNum], FRAME_ERROR_ALLSLOTS);
1895*e5436536SAndroid Build Coastguard Worker     }
1896*e5436536SAndroid Build Coastguard Worker 
1897*e5436536SAndroid Build Coastguard Worker     errorStatus = sbrDecoder_DecodeElement(
1898*e5436536SAndroid Build Coastguard Worker         self, input, timeData, timeDataSize, mapDescr, mapIdx, numSbrChannels,
1899*e5436536SAndroid Build Coastguard Worker         sbrElementNum,
1900*e5436536SAndroid Build Coastguard Worker         numCoreChannels, /* is correct even for USC SCI==2 case */
1901*e5436536SAndroid Build Coastguard Worker         &numElementChan, psPossible);
1902*e5436536SAndroid Build Coastguard Worker 
1903*e5436536SAndroid Build Coastguard Worker     if (errorStatus != SBRDEC_OK) {
1904*e5436536SAndroid Build Coastguard Worker       goto bail;
1905*e5436536SAndroid Build Coastguard Worker     }
1906*e5436536SAndroid Build Coastguard Worker 
1907*e5436536SAndroid Build Coastguard Worker     numSbrChannels += numElementChan;
1908*e5436536SAndroid Build Coastguard Worker 
1909*e5436536SAndroid Build Coastguard Worker     if (numSbrChannels >= numCoreChannels) {
1910*e5436536SAndroid Build Coastguard Worker       break;
1911*e5436536SAndroid Build Coastguard Worker     }
1912*e5436536SAndroid Build Coastguard Worker   }
1913*e5436536SAndroid Build Coastguard Worker 
1914*e5436536SAndroid Build Coastguard Worker   /* Update numChannels and samplerate */
1915*e5436536SAndroid Build Coastguard Worker   /* Do not mess with output channels in case of USAC. numSbrChannels !=
1916*e5436536SAndroid Build Coastguard Worker    * numChannels for stereoConfigIndex == 2 */
1917*e5436536SAndroid Build Coastguard Worker   if (!(self->flags & SBRDEC_SYNTAX_USAC)) {
1918*e5436536SAndroid Build Coastguard Worker     *numChannels = numSbrChannels;
1919*e5436536SAndroid Build Coastguard Worker   }
1920*e5436536SAndroid Build Coastguard Worker   *sampleRate = self->sampleRateOut;
1921*e5436536SAndroid Build Coastguard Worker   *psDecoded = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0;
1922*e5436536SAndroid Build Coastguard Worker 
1923*e5436536SAndroid Build Coastguard Worker   /* Clear reset and flush flag because everything seems to be done
1924*e5436536SAndroid Build Coastguard Worker    * successfully. */
1925*e5436536SAndroid Build Coastguard Worker   self->flags &= ~SBRDEC_FORCE_RESET;
1926*e5436536SAndroid Build Coastguard Worker   self->flags &= ~SBRDEC_FLUSH;
1927*e5436536SAndroid Build Coastguard Worker 
1928*e5436536SAndroid Build Coastguard Worker bail:
1929*e5436536SAndroid Build Coastguard Worker 
1930*e5436536SAndroid Build Coastguard Worker   return errorStatus;
1931*e5436536SAndroid Build Coastguard Worker }
1932*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_Close(HANDLE_SBRDECODER * pSelf)1933*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *pSelf) {
1934*e5436536SAndroid Build Coastguard Worker   HANDLE_SBRDECODER self = *pSelf;
1935*e5436536SAndroid Build Coastguard Worker   int i;
1936*e5436536SAndroid Build Coastguard Worker 
1937*e5436536SAndroid Build Coastguard Worker   if (self != NULL) {
1938*e5436536SAndroid Build Coastguard Worker     if (self->hParametricStereoDec != NULL) {
1939*e5436536SAndroid Build Coastguard Worker       DeletePsDec(&self->hParametricStereoDec);
1940*e5436536SAndroid Build Coastguard Worker     }
1941*e5436536SAndroid Build Coastguard Worker 
1942*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < (8); i++) {
1943*e5436536SAndroid Build Coastguard Worker       sbrDecoder_DestroyElement(self, i);
1944*e5436536SAndroid Build Coastguard Worker     }
1945*e5436536SAndroid Build Coastguard Worker 
1946*e5436536SAndroid Build Coastguard Worker     FreeRam_SbrDecoder(pSelf);
1947*e5436536SAndroid Build Coastguard Worker   }
1948*e5436536SAndroid Build Coastguard Worker 
1949*e5436536SAndroid Build Coastguard Worker   return SBRDEC_OK;
1950*e5436536SAndroid Build Coastguard Worker }
1951*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_GetLibInfo(LIB_INFO * info)1952*e5436536SAndroid Build Coastguard Worker INT sbrDecoder_GetLibInfo(LIB_INFO *info) {
1953*e5436536SAndroid Build Coastguard Worker   int i;
1954*e5436536SAndroid Build Coastguard Worker 
1955*e5436536SAndroid Build Coastguard Worker   if (info == NULL) {
1956*e5436536SAndroid Build Coastguard Worker     return -1;
1957*e5436536SAndroid Build Coastguard Worker   }
1958*e5436536SAndroid Build Coastguard Worker 
1959*e5436536SAndroid Build Coastguard Worker   /* search for next free tab */
1960*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < FDK_MODULE_LAST; i++) {
1961*e5436536SAndroid Build Coastguard Worker     if (info[i].module_id == FDK_NONE) break;
1962*e5436536SAndroid Build Coastguard Worker   }
1963*e5436536SAndroid Build Coastguard Worker   if (i == FDK_MODULE_LAST) return -1;
1964*e5436536SAndroid Build Coastguard Worker   info += i;
1965*e5436536SAndroid Build Coastguard Worker 
1966*e5436536SAndroid Build Coastguard Worker   info->module_id = FDK_SBRDEC;
1967*e5436536SAndroid Build Coastguard Worker   info->version =
1968*e5436536SAndroid Build Coastguard Worker       LIB_VERSION(SBRDECODER_LIB_VL0, SBRDECODER_LIB_VL1, SBRDECODER_LIB_VL2);
1969*e5436536SAndroid Build Coastguard Worker   LIB_VERSION_STRING(info);
1970*e5436536SAndroid Build Coastguard Worker   info->build_date = SBRDECODER_LIB_BUILD_DATE;
1971*e5436536SAndroid Build Coastguard Worker   info->build_time = SBRDECODER_LIB_BUILD_TIME;
1972*e5436536SAndroid Build Coastguard Worker   info->title = SBRDECODER_LIB_TITLE;
1973*e5436536SAndroid Build Coastguard Worker 
1974*e5436536SAndroid Build Coastguard Worker   /* Set flags */
1975*e5436536SAndroid Build Coastguard Worker   info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_LP | CAPF_SBR_PS_MPEG |
1976*e5436536SAndroid Build Coastguard Worker                 CAPF_SBR_DRM_BS | CAPF_SBR_CONCEALMENT | CAPF_SBR_DRC |
1977*e5436536SAndroid Build Coastguard Worker                 CAPF_SBR_ELD_DOWNSCALE | CAPF_SBR_HBEHQ;
1978*e5436536SAndroid Build Coastguard Worker   /* End of flags */
1979*e5436536SAndroid Build Coastguard Worker 
1980*e5436536SAndroid Build Coastguard Worker   return 0;
1981*e5436536SAndroid Build Coastguard Worker }
1982*e5436536SAndroid Build Coastguard Worker 
sbrDecoder_GetDelay(const HANDLE_SBRDECODER self)1983*e5436536SAndroid Build Coastguard Worker UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self) {
1984*e5436536SAndroid Build Coastguard Worker   UINT outputDelay = 0;
1985*e5436536SAndroid Build Coastguard Worker 
1986*e5436536SAndroid Build Coastguard Worker   if (self != NULL) {
1987*e5436536SAndroid Build Coastguard Worker     UINT flags = self->flags;
1988*e5436536SAndroid Build Coastguard Worker 
1989*e5436536SAndroid Build Coastguard Worker     /* See chapter 1.6.7.2 of ISO/IEC 14496-3 for the GA-SBR figures below. */
1990*e5436536SAndroid Build Coastguard Worker 
1991*e5436536SAndroid Build Coastguard Worker     /* Are we initialized? */
1992*e5436536SAndroid Build Coastguard Worker     if ((self->numSbrChannels > 0) && (self->numSbrElements > 0)) {
1993*e5436536SAndroid Build Coastguard Worker       /* Add QMF synthesis delay */
1994*e5436536SAndroid Build Coastguard Worker       if ((flags & SBRDEC_ELD_GRID) && IS_LOWDELAY(self->coreCodec)) {
1995*e5436536SAndroid Build Coastguard Worker         /* Low delay SBR: */
1996*e5436536SAndroid Build Coastguard Worker         if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
1997*e5436536SAndroid Build Coastguard Worker           outputDelay +=
1998*e5436536SAndroid Build Coastguard Worker               (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */
1999*e5436536SAndroid Build Coastguard Worker           if (flags & SBRDEC_LD_MPS_QMF) {
2000*e5436536SAndroid Build Coastguard Worker             outputDelay += 32;
2001*e5436536SAndroid Build Coastguard Worker           }
2002*e5436536SAndroid Build Coastguard Worker         }
2003*e5436536SAndroid Build Coastguard Worker       } else if (!IS_USAC(self->coreCodec)) {
2004*e5436536SAndroid Build Coastguard Worker         /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...)
2005*e5436536SAndroid Build Coastguard Worker          * branch: */
2006*e5436536SAndroid Build Coastguard Worker         outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 481 : 962;
2007*e5436536SAndroid Build Coastguard Worker         if (flags & SBRDEC_SKIP_QMF_SYN) {
2008*e5436536SAndroid Build Coastguard Worker           outputDelay -= 257; /* QMF synthesis */
2009*e5436536SAndroid Build Coastguard Worker         }
2010*e5436536SAndroid Build Coastguard Worker       }
2011*e5436536SAndroid Build Coastguard Worker     }
2012*e5436536SAndroid Build Coastguard Worker   }
2013*e5436536SAndroid Build Coastguard Worker 
2014*e5436536SAndroid Build Coastguard Worker   return (outputDelay);
2015*e5436536SAndroid Build Coastguard Worker }
2016