xref: /aosp_15_r20/external/aac/libSACdec/src/sac_dec_lib.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 - 2020 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 /*********************** MPEG surround 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: SAC Decoder Library Interface
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "sac_dec_lib.h"
104*e5436536SAndroid Build Coastguard Worker #include "sac_dec_interface.h"
105*e5436536SAndroid Build Coastguard Worker #include "sac_dec.h"
106*e5436536SAndroid Build Coastguard Worker #include "sac_bitdec.h"
107*e5436536SAndroid Build Coastguard Worker #include "FDK_matrixCalloc.h"
108*e5436536SAndroid Build Coastguard Worker 
109*e5436536SAndroid Build Coastguard Worker #define MPS_DATA_BUFFER_SIZE (2048)
110*e5436536SAndroid Build Coastguard Worker 
111*e5436536SAndroid Build Coastguard Worker /**
112*e5436536SAndroid Build Coastguard Worker  * \brief MPEG Surround data indication.
113*e5436536SAndroid Build Coastguard Worker  **/
114*e5436536SAndroid Build Coastguard Worker typedef enum {
115*e5436536SAndroid Build Coastguard Worker   MPEGS_ANCTYPE_FRAME = 0, /*!< MPEG Surround frame, see ISO/IEC 23003-1 */
116*e5436536SAndroid Build Coastguard Worker   MPEGS_ANCTYPE_HEADER_AND_FRAME = 1, /*!< MPEG Surround header and MPEG
117*e5436536SAndroid Build Coastguard Worker                                          Surround frame, see ISO/IEC 23003-1 */
118*e5436536SAndroid Build Coastguard Worker   MPEGS_ANCTYPE_RESERVED_1 = 2,       /*!< reserved, see ISO/IEC 23003-1 */
119*e5436536SAndroid Build Coastguard Worker   MPEGS_ANCTYPE_RESERVED_2 = 3        /*!< reserved, see ISO/IEC 23003-1*/
120*e5436536SAndroid Build Coastguard Worker } MPEGS_ANCTYPE;
121*e5436536SAndroid Build Coastguard Worker 
122*e5436536SAndroid Build Coastguard Worker /**
123*e5436536SAndroid Build Coastguard Worker  * \brief MPEG Surround data segment indication.
124*e5436536SAndroid Build Coastguard Worker  **/
125*e5436536SAndroid Build Coastguard Worker typedef enum {
126*e5436536SAndroid Build Coastguard Worker   MPEGS_CONTINUE = 0, /*!< Indicates if data segment continues a data block. */
127*e5436536SAndroid Build Coastguard Worker   MPEGS_STOP = 1,     /*!< Indicates if data segment ends a data block. */
128*e5436536SAndroid Build Coastguard Worker   MPEGS_START = 2,    /*!< Indicates if data segment begins a data block. */
129*e5436536SAndroid Build Coastguard Worker   MPEGS_START_STOP =
130*e5436536SAndroid Build Coastguard Worker       3 /*!< Indicates if data segment begins and ends a data block. */
131*e5436536SAndroid Build Coastguard Worker } MPEGS_ANCSTARTSTOP;
132*e5436536SAndroid Build Coastguard Worker 
133*e5436536SAndroid Build Coastguard Worker /**
134*e5436536SAndroid Build Coastguard Worker  * \brief MPEG Surround synchronizaiton state.
135*e5436536SAndroid Build Coastguard Worker  *
136*e5436536SAndroid Build Coastguard Worker  *  CAUTION: Changing the enumeration values can break the sync mechanism
137*e5436536SAndroid Build Coastguard Worker  *because it is based on comparing the state values.
138*e5436536SAndroid Build Coastguard Worker  **/
139*e5436536SAndroid Build Coastguard Worker typedef enum {
140*e5436536SAndroid Build Coastguard Worker   MPEGS_SYNC_LOST =
141*e5436536SAndroid Build Coastguard Worker       0, /*!< Indicates lost sync because of current discontinuity. */
142*e5436536SAndroid Build Coastguard Worker   MPEGS_SYNC_FOUND = 1,   /*!< Parsed a valid header and (re)intialization was
143*e5436536SAndroid Build Coastguard Worker                              successfully completed. */
144*e5436536SAndroid Build Coastguard Worker   MPEGS_SYNC_COMPLETE = 2 /*!< In sync and continuous. Found an independent
145*e5436536SAndroid Build Coastguard Worker                              frame in addition to MPEGS_SYNC_FOUND.
146*e5436536SAndroid Build Coastguard Worker                                Precondition: MPEGS_SYNC_FOUND. */
147*e5436536SAndroid Build Coastguard Worker } MPEGS_SYNCSTATE;
148*e5436536SAndroid Build Coastguard Worker 
149*e5436536SAndroid Build Coastguard Worker /**
150*e5436536SAndroid Build Coastguard Worker  * \brief MPEG Surround operation mode.
151*e5436536SAndroid Build Coastguard Worker  **/
152*e5436536SAndroid Build Coastguard Worker typedef enum {
153*e5436536SAndroid Build Coastguard Worker   MPEGS_OPMODE_EMM = 0,           /*!< Mode: Enhanced Matrix Mode (Blind) */
154*e5436536SAndroid Build Coastguard Worker   MPEGS_OPMODE_MPS_PAYLOAD = 1,   /*!< Mode: Normal, Stereo or Binaural */
155*e5436536SAndroid Build Coastguard Worker   MPEGS_OPMODE_NO_MPS_PAYLOAD = 2 /*!< Mode: no MPEG Surround payload */
156*e5436536SAndroid Build Coastguard Worker } MPEGS_OPMODE;
157*e5436536SAndroid Build Coastguard Worker 
158*e5436536SAndroid Build Coastguard Worker /**
159*e5436536SAndroid Build Coastguard Worker  * \brief MPEG Surround init flags.
160*e5436536SAndroid Build Coastguard Worker  **/
161*e5436536SAndroid Build Coastguard Worker typedef enum {
162*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_OK = 0x00000000, /*!< indicate correct initialization */
163*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_ENFORCE_REINIT =
164*e5436536SAndroid Build Coastguard Worker       0x00000001, /*!< indicate complete initialization */
165*e5436536SAndroid Build Coastguard Worker 
166*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_CHANGE_OUTPUT_MODE =
167*e5436536SAndroid Build Coastguard Worker       0x00000010, /*!< indicate change of the output mode */
168*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX =
169*e5436536SAndroid Build Coastguard Worker       0x00000020, /*!< indicate change of low power/high quality */
170*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE =
171*e5436536SAndroid Build Coastguard Worker       0x00000040, /*!< indicate change of qmf/time interface */
172*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_CHANGE_HEADER = 0x00000080, /*!< indicate change of header */
173*e5436536SAndroid Build Coastguard Worker 
174*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_ERROR_PAYLOAD =
175*e5436536SAndroid Build Coastguard Worker       0x00000100, /*!< indicate payload/ancType/ancStartStop error */
176*e5436536SAndroid Build Coastguard Worker 
177*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_BS_INTERRUPTION =
178*e5436536SAndroid Build Coastguard Worker       0x00001000, /*!< indicate bitstream interruption  */
179*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_CLEAR_HISTORY =
180*e5436536SAndroid Build Coastguard Worker       0x00002000, /*!< indicate that all states shall be cleared */
181*e5436536SAndroid Build Coastguard Worker 
182*e5436536SAndroid Build Coastguard Worker   /* Re-initialization of submodules */
183*e5436536SAndroid Build Coastguard Worker 
184*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_CHANGE_CONCEAL_PARAMS = 0x00100000, /*!< indicate a change of at
185*e5436536SAndroid Build Coastguard Worker                                                     least one error concealment
186*e5436536SAndroid Build Coastguard Worker                                                     param */
187*e5436536SAndroid Build Coastguard Worker 
188*e5436536SAndroid Build Coastguard Worker   /* No re-initialization needed, currently not used */
189*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_CHANGE_BYPASS_MODE =
190*e5436536SAndroid Build Coastguard Worker       0x01000000, /*!< indicate change of bypass mode */
191*e5436536SAndroid Build Coastguard Worker 
192*e5436536SAndroid Build Coastguard Worker   /* Re-initialization needed, currently not used */
193*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_ERROR_ANC_TYPE = 0x10000000, /*!< indicate ancType error*/
194*e5436536SAndroid Build Coastguard Worker   MPEGS_INIT_ERROR_ANC_STARTSTOP =
195*e5436536SAndroid Build Coastguard Worker       0x20000000 /*!< indicate ancStartStop error */
196*e5436536SAndroid Build Coastguard Worker } MPEGS_INIT_FLAGS;
197*e5436536SAndroid Build Coastguard Worker 
198*e5436536SAndroid Build Coastguard Worker struct MpegSurroundDecoder {
199*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_QMF_DOMAIN pQmfDomain;
200*e5436536SAndroid Build Coastguard Worker   UCHAR mpsData[MPS_DATA_BUFFER_SIZE]; /* Buffer for MPS payload accross more
201*e5436536SAndroid Build Coastguard Worker                                           than one segment */
202*e5436536SAndroid Build Coastguard Worker   INT mpsDataBits;                     /* Amount of bits in mpsData */
203*e5436536SAndroid Build Coastguard Worker   /* MPEG Surround decoder */
204*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig[1]; /* SSC delay line which is
205*e5436536SAndroid Build Coastguard Worker                                                        used during decoding */
206*e5436536SAndroid Build Coastguard Worker   spatialDec *pSpatialDec;
207*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG
208*e5436536SAndroid Build Coastguard Worker   spatialSpecificConfigBackup; /* SSC used while parsing */
209*e5436536SAndroid Build Coastguard Worker 
210*e5436536SAndroid Build Coastguard Worker   /* Creation parameter */
211*e5436536SAndroid Build Coastguard Worker   UCHAR mpegSurroundDecoderLevel;
212*e5436536SAndroid Build Coastguard Worker   /* Run-time parameter */
213*e5436536SAndroid Build Coastguard Worker   UCHAR mpegSurroundSscIsGlobalCfg; /* Flag telling that the SSC
214*e5436536SAndroid Build Coastguard Worker                                        (::spatialSpecificConfig) is a
215*e5436536SAndroid Build Coastguard Worker                                        out-of-band configuration. */
216*e5436536SAndroid Build Coastguard Worker   UCHAR mpegSurroundUseTimeInterface;
217*e5436536SAndroid Build Coastguard Worker 
218*e5436536SAndroid Build Coastguard Worker   SPATIAL_BS_FRAME
219*e5436536SAndroid Build Coastguard Worker   bsFrames[1];         /* Bitstream Structs that contain data read from the
220*e5436536SAndroid Build Coastguard Worker                           SpatialFrame() bitstream element */
221*e5436536SAndroid Build Coastguard Worker   BS_LL_STATE llState; /* Bit stream parser state memory */
222*e5436536SAndroid Build Coastguard Worker   UCHAR bsFrameParse;  /* Current parse frame context index */
223*e5436536SAndroid Build Coastguard Worker   UCHAR bsFrameDecode; /* Current decode/apply frame context index */
224*e5436536SAndroid Build Coastguard Worker   UCHAR bsFrameDelay;  /* Amount of frames delay between parsing and processing.
225*e5436536SAndroid Build Coastguard Worker                           Required i.e. for interpolation error concealment. */
226*e5436536SAndroid Build Coastguard Worker 
227*e5436536SAndroid Build Coastguard Worker   /* User prameters */
228*e5436536SAndroid Build Coastguard Worker   SPATIALDEC_PARAM mpegSurroundUserParams;
229*e5436536SAndroid Build Coastguard Worker 
230*e5436536SAndroid Build Coastguard Worker   /* Internal flags */
231*e5436536SAndroid Build Coastguard Worker   SPATIAL_DEC_UPMIX_TYPE upmixType;
232*e5436536SAndroid Build Coastguard Worker   int initFlags[1];
233*e5436536SAndroid Build Coastguard Worker   MPEGS_ANCSTARTSTOP ancStartStopPrev;
234*e5436536SAndroid Build Coastguard Worker   MPEGS_SYNCSTATE fOnSync[1];
235*e5436536SAndroid Build Coastguard Worker 
236*e5436536SAndroid Build Coastguard Worker   /* Inital decoder configuration */
237*e5436536SAndroid Build Coastguard Worker   SPATIAL_DEC_CONFIG decConfig;
238*e5436536SAndroid Build Coastguard Worker };
239*e5436536SAndroid Build Coastguard Worker 
240*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR
241*e5436536SAndroid Build Coastguard Worker static sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc,
242*e5436536SAndroid Build Coastguard Worker                          const INT coreCodec, const INT sampleRate,
243*e5436536SAndroid Build Coastguard Worker                          const INT frameSize);
244*e5436536SAndroid Build Coastguard Worker 
245*e5436536SAndroid Build Coastguard Worker static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc);
246*e5436536SAndroid Build Coastguard Worker 
247*e5436536SAndroid Build Coastguard Worker /**
248*e5436536SAndroid Build Coastguard Worker  * \brief Get the number of QMF bands from the sampling frequency (in Hz)
249*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_GetNrOfQmfBands(const SPATIAL_SPECIFIC_CONFIG * pSsc,UINT sampleRate)250*e5436536SAndroid Build Coastguard Worker static int mpegSurroundDecoder_GetNrOfQmfBands(
251*e5436536SAndroid Build Coastguard Worker     const SPATIAL_SPECIFIC_CONFIG *pSsc, UINT sampleRate) {
252*e5436536SAndroid Build Coastguard Worker   UINT samplingFrequency = sampleRate;
253*e5436536SAndroid Build Coastguard Worker   int qmfBands = 64;
254*e5436536SAndroid Build Coastguard Worker 
255*e5436536SAndroid Build Coastguard Worker   if (pSsc != NULL) {
256*e5436536SAndroid Build Coastguard Worker     switch (pSsc->coreCodec) {
257*e5436536SAndroid Build Coastguard Worker       case AOT_USAC:
258*e5436536SAndroid Build Coastguard Worker         if ((pSsc->stereoConfigIndex == 3)) {
259*e5436536SAndroid Build Coastguard Worker           static const UCHAR mapIdx2QmfBands[3] = {24, 32, 16};
260*e5436536SAndroid Build Coastguard Worker           FDK_ASSERT((pSsc->coreSbrFrameLengthIndex >= 2) &&
261*e5436536SAndroid Build Coastguard Worker                      (pSsc->coreSbrFrameLengthIndex <= 4));
262*e5436536SAndroid Build Coastguard Worker           qmfBands = mapIdx2QmfBands[pSsc->coreSbrFrameLengthIndex - 2];
263*e5436536SAndroid Build Coastguard Worker         }
264*e5436536SAndroid Build Coastguard Worker         return qmfBands;
265*e5436536SAndroid Build Coastguard Worker       default:
266*e5436536SAndroid Build Coastguard Worker         samplingFrequency = pSsc->samplingFreq;
267*e5436536SAndroid Build Coastguard Worker         break;
268*e5436536SAndroid Build Coastguard Worker     }
269*e5436536SAndroid Build Coastguard Worker   }
270*e5436536SAndroid Build Coastguard Worker 
271*e5436536SAndroid Build Coastguard Worker   /* number of QMF bands depend on sampling frequency, see FDIS 23003-1:2006
272*e5436536SAndroid Build Coastguard Worker    * Chapter 6.3.3 */
273*e5436536SAndroid Build Coastguard Worker   if (samplingFrequency < 27713) {
274*e5436536SAndroid Build Coastguard Worker     qmfBands = 32;
275*e5436536SAndroid Build Coastguard Worker   }
276*e5436536SAndroid Build Coastguard Worker   if (samplingFrequency > 55426) {
277*e5436536SAndroid Build Coastguard Worker     qmfBands = 128;
278*e5436536SAndroid Build Coastguard Worker   }
279*e5436536SAndroid Build Coastguard Worker 
280*e5436536SAndroid Build Coastguard Worker   return qmfBands;
281*e5436536SAndroid Build Coastguard Worker }
282*e5436536SAndroid Build Coastguard Worker 
283*e5436536SAndroid Build Coastguard Worker /**
284*e5436536SAndroid Build Coastguard Worker  * \brief Analyse init flags
285*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_CalcInitFlags(SPATIAL_SPECIFIC_CONFIG * pSsc1,SPATIAL_SPECIFIC_CONFIG * pSsc2,int upmixTypeFlag,int binauralQualityFlag,int partiallyComplexFlag,int * ctrlFlags)286*e5436536SAndroid Build Coastguard Worker static int mpegSurroundDecoder_CalcInitFlags(SPATIAL_SPECIFIC_CONFIG *pSsc1,
287*e5436536SAndroid Build Coastguard Worker                                              SPATIAL_SPECIFIC_CONFIG *pSsc2,
288*e5436536SAndroid Build Coastguard Worker                                              int upmixTypeFlag,
289*e5436536SAndroid Build Coastguard Worker                                              int binauralQualityFlag,
290*e5436536SAndroid Build Coastguard Worker                                              int partiallyComplexFlag,
291*e5436536SAndroid Build Coastguard Worker                                              int *ctrlFlags) {
292*e5436536SAndroid Build Coastguard Worker   /* Analyse core coder */
293*e5436536SAndroid Build Coastguard Worker   if (pSsc1->coreCodec != pSsc2->coreCodec) {
294*e5436536SAndroid Build Coastguard Worker     *ctrlFlags |= MASK_MPEGS_INIT_ALL_STATES;
295*e5436536SAndroid Build Coastguard Worker     *ctrlFlags |= MASK_MPEGS_INIT_ALL_PARAMS;
296*e5436536SAndroid Build Coastguard Worker   } else {
297*e5436536SAndroid Build Coastguard Worker     /* Analyse elements for initialization of space analysis qmf filterbank */
298*e5436536SAndroid Build Coastguard Worker     if ((partiallyComplexFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) ||
299*e5436536SAndroid Build Coastguard Worker         (pSsc1->samplingFreq != pSsc2->samplingFreq)) {
300*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_ANA_QMF_FILTER;
301*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_ANA_HYB_FILTER;
302*e5436536SAndroid Build Coastguard Worker     }
303*e5436536SAndroid Build Coastguard Worker 
304*e5436536SAndroid Build Coastguard Worker     /* Analyse elements for initialization of space synthesis qmf filterbank */
305*e5436536SAndroid Build Coastguard Worker     if ((upmixTypeFlag) || (partiallyComplexFlag) ||
306*e5436536SAndroid Build Coastguard Worker         (pSsc1->treeConfig != pSsc2->treeConfig) ||
307*e5436536SAndroid Build Coastguard Worker         (pSsc1->samplingFreq != pSsc2->samplingFreq) ||
308*e5436536SAndroid Build Coastguard Worker         (pSsc1->bsFixedGainDMX != pSsc2->bsFixedGainDMX)) {
309*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_SYN_QMF_FILTER;
310*e5436536SAndroid Build Coastguard Worker     }
311*e5436536SAndroid Build Coastguard Worker 
312*e5436536SAndroid Build Coastguard Worker     /* Analyse elements for initialization of decorrelator */
313*e5436536SAndroid Build Coastguard Worker     if ((upmixTypeFlag) || (partiallyComplexFlag) ||
314*e5436536SAndroid Build Coastguard Worker         (pSsc1->treeConfig != pSsc2->treeConfig) ||
315*e5436536SAndroid Build Coastguard Worker         (pSsc1->samplingFreq != pSsc2->samplingFreq) ||
316*e5436536SAndroid Build Coastguard Worker         (pSsc1->decorrConfig != pSsc2->decorrConfig)) {
317*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_DECORRELATOR;
318*e5436536SAndroid Build Coastguard Worker     }
319*e5436536SAndroid Build Coastguard Worker 
320*e5436536SAndroid Build Coastguard Worker     /* Analyse elements for initialization of m1 and m2 calculation */
321*e5436536SAndroid Build Coastguard Worker     if ((upmixTypeFlag) || (binauralQualityFlag) ||
322*e5436536SAndroid Build Coastguard Worker         (pSsc1->treeConfig != pSsc2->treeConfig) ||
323*e5436536SAndroid Build Coastguard Worker         (pSsc1->samplingFreq != pSsc2->samplingFreq))
324*e5436536SAndroid Build Coastguard Worker 
325*e5436536SAndroid Build Coastguard Worker     {
326*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_M1M2;
327*e5436536SAndroid Build Coastguard Worker     }
328*e5436536SAndroid Build Coastguard Worker 
329*e5436536SAndroid Build Coastguard Worker     /* Analyse elements for initialization of GES */
330*e5436536SAndroid Build Coastguard Worker     if ((upmixTypeFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) ||
331*e5436536SAndroid Build Coastguard Worker         (pSsc1->tempShapeConfig != pSsc2->tempShapeConfig)) {
332*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_GES;
333*e5436536SAndroid Build Coastguard Worker     }
334*e5436536SAndroid Build Coastguard Worker 
335*e5436536SAndroid Build Coastguard Worker     /* Analyse elements for initialization of FDreverb */
336*e5436536SAndroid Build Coastguard Worker     if ((upmixTypeFlag) || (binauralQualityFlag) || (partiallyComplexFlag) ||
337*e5436536SAndroid Build Coastguard Worker         (pSsc1->samplingFreq != pSsc2->samplingFreq) ||
338*e5436536SAndroid Build Coastguard Worker         (pSsc1->nTimeSlots != pSsc2->nTimeSlots)) {
339*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_REVERB;
340*e5436536SAndroid Build Coastguard Worker     }
341*e5436536SAndroid Build Coastguard Worker 
342*e5436536SAndroid Build Coastguard Worker     /* Reset previous frame data whenever the config changes */
343*e5436536SAndroid Build Coastguard Worker     if (*ctrlFlags & MPEGS_INIT_CONFIG) {
344*e5436536SAndroid Build Coastguard Worker       *ctrlFlags |= MPEGS_INIT_STATES_PARAM;
345*e5436536SAndroid Build Coastguard Worker     }
346*e5436536SAndroid Build Coastguard Worker   }
347*e5436536SAndroid Build Coastguard Worker 
348*e5436536SAndroid Build Coastguard Worker   return MPS_OK;
349*e5436536SAndroid Build Coastguard Worker }
350*e5436536SAndroid Build Coastguard Worker 
351*e5436536SAndroid Build Coastguard Worker /**
352*e5436536SAndroid Build Coastguard Worker  * \brief Reset MPEG Surround status info
353*e5436536SAndroid Build Coastguard Worker  **/
updateMpegSurroundDecoderStatus(CMpegSurroundDecoder * pMpegSurroundDecoder,int initFlags,MPEGS_SYNCSTATE fOnSync,MPEGS_ANCSTARTSTOP ancStartStopPrev)354*e5436536SAndroid Build Coastguard Worker static void updateMpegSurroundDecoderStatus(
355*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder, int initFlags,
356*e5436536SAndroid Build Coastguard Worker     MPEGS_SYNCSTATE fOnSync, MPEGS_ANCSTARTSTOP ancStartStopPrev) {
357*e5436536SAndroid Build Coastguard Worker   pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
358*e5436536SAndroid Build Coastguard Worker       initFlags;
359*e5436536SAndroid Build Coastguard Worker   if ((pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg != 0) &&
360*e5436536SAndroid Build Coastguard Worker       (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] >=
361*e5436536SAndroid Build Coastguard Worker        MPEGS_SYNC_FOUND) &&
362*e5436536SAndroid Build Coastguard Worker       (fOnSync < MPEGS_SYNC_FOUND)) {
363*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
364*e5436536SAndroid Build Coastguard Worker         MPEGS_SYNC_FOUND;
365*e5436536SAndroid Build Coastguard Worker   } else {
366*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
367*e5436536SAndroid Build Coastguard Worker         fOnSync;
368*e5436536SAndroid Build Coastguard Worker   }
369*e5436536SAndroid Build Coastguard Worker   pMpegSurroundDecoder->ancStartStopPrev = ancStartStopPrev;
370*e5436536SAndroid Build Coastguard Worker }
371*e5436536SAndroid Build Coastguard Worker 
372*e5436536SAndroid Build Coastguard Worker static SACDEC_ERROR mpegSurroundDecoder_Create(
373*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex,
374*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_QMF_DOMAIN pQmfDomain);
375*e5436536SAndroid Build Coastguard Worker 
376*e5436536SAndroid Build Coastguard Worker SAC_INSTANCE_AVAIL
mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable(CMpegSurroundDecoder * pMpegSurroundDecoder)377*e5436536SAndroid Build Coastguard Worker mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable(
378*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder) {
379*e5436536SAndroid Build Coastguard Worker   SAC_INSTANCE_AVAIL instanceAvailable = SAC_INSTANCE_NOT_FULL_AVAILABLE;
380*e5436536SAndroid Build Coastguard Worker 
381*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder->pSpatialDec != NULL) {
382*e5436536SAndroid Build Coastguard Worker     instanceAvailable = SAC_INSTANCE_FULL_AVAILABLE;
383*e5436536SAndroid Build Coastguard Worker   }
384*e5436536SAndroid Build Coastguard Worker 
385*e5436536SAndroid Build Coastguard Worker   return instanceAvailable;
386*e5436536SAndroid Build Coastguard Worker }
387*e5436536SAndroid Build Coastguard Worker 
mpegSurroundDecoder_Open(CMpegSurroundDecoder ** pMpegSurroundDecoder,int stereoConfigIndex,HANDLE_FDK_QMF_DOMAIN pQmfDomain)388*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR mpegSurroundDecoder_Open(
389*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex,
390*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_QMF_DOMAIN pQmfDomain) {
391*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR error;
392*e5436536SAndroid Build Coastguard Worker 
393*e5436536SAndroid Build Coastguard Worker   error = mpegSurroundDecoder_Create(pMpegSurroundDecoder, stereoConfigIndex,
394*e5436536SAndroid Build Coastguard Worker                                      pQmfDomain);
395*e5436536SAndroid Build Coastguard Worker 
396*e5436536SAndroid Build Coastguard Worker   return error;
397*e5436536SAndroid Build Coastguard Worker }
398*e5436536SAndroid Build Coastguard Worker 
399*e5436536SAndroid Build Coastguard Worker /**
400*e5436536SAndroid Build Coastguard Worker  * \brief  Renamed function from getUpmixType to check_UParam_Build_DecConfig.
401*e5436536SAndroid Build Coastguard Worker  *         This function checks if user params, decoder config and SSC are valid
402*e5436536SAndroid Build Coastguard Worker  *         and if the decoder build can handle all this settings.
403*e5436536SAndroid Build Coastguard Worker  *         The upmix type may be modified by this function.
404*e5436536SAndroid Build Coastguard Worker  *         It is called in initMpegSurroundDecoder() after the ssc parse check,
405*e5436536SAndroid Build Coastguard Worker  *         to have all checks in one place and to ensure these checks are always
406*e5436536SAndroid Build Coastguard Worker  *         performed if config changes (inband and out-of-band).
407*e5436536SAndroid Build Coastguard Worker  *
408*e5436536SAndroid Build Coastguard Worker  * \param pUserParams  User data handle.
409*e5436536SAndroid Build Coastguard Worker  * \param pDecConfig   decoder config handle.
410*e5436536SAndroid Build Coastguard Worker  * \param pSsc         spatial specific config handle.
411*e5436536SAndroid Build Coastguard Worker  * \param pUpmixType   upmix type which is set by this function
412*e5436536SAndroid Build Coastguard Worker  *
413*e5436536SAndroid Build Coastguard Worker  * \return  MPS_OK on sucess, and else on failure.
414*e5436536SAndroid Build Coastguard Worker  */
check_UParam_Build_DecConfig(SPATIALDEC_PARAM const * pUserParams,SPATIAL_DEC_CONFIG const * pDecConfig,const SPATIAL_SPECIFIC_CONFIG * pSsc,SPATIAL_DEC_UPMIX_TYPE * pUpmixType)415*e5436536SAndroid Build Coastguard Worker static SACDEC_ERROR check_UParam_Build_DecConfig(
416*e5436536SAndroid Build Coastguard Worker     SPATIALDEC_PARAM const *pUserParams, SPATIAL_DEC_CONFIG const *pDecConfig,
417*e5436536SAndroid Build Coastguard Worker     const SPATIAL_SPECIFIC_CONFIG *pSsc, SPATIAL_DEC_UPMIX_TYPE *pUpmixType) {
418*e5436536SAndroid Build Coastguard Worker   int dmxChannels, outChannels, maxNumOutChannels;
419*e5436536SAndroid Build Coastguard Worker 
420*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pUserParams != NULL);
421*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pUpmixType != NULL);
422*e5436536SAndroid Build Coastguard Worker 
423*e5436536SAndroid Build Coastguard Worker   /* checks if implementation can handle the Ssc */
424*e5436536SAndroid Build Coastguard Worker 
425*e5436536SAndroid Build Coastguard Worker   switch (pSsc->treeConfig) {
426*e5436536SAndroid Build Coastguard Worker     case SPATIALDEC_MODE_RSVD7: /* 212 */
427*e5436536SAndroid Build Coastguard Worker       dmxChannels = 1;
428*e5436536SAndroid Build Coastguard Worker       outChannels = 2;
429*e5436536SAndroid Build Coastguard Worker       break;
430*e5436536SAndroid Build Coastguard Worker     default:
431*e5436536SAndroid Build Coastguard Worker       return MPS_UNSUPPORTED_CONFIG;
432*e5436536SAndroid Build Coastguard Worker   }
433*e5436536SAndroid Build Coastguard Worker 
434*e5436536SAndroid Build Coastguard Worker   /* ------------------------------------------- */
435*e5436536SAndroid Build Coastguard Worker 
436*e5436536SAndroid Build Coastguard Worker   /* Analyse pDecConfig params */
437*e5436536SAndroid Build Coastguard Worker   switch (pDecConfig->binauralMode) {
438*e5436536SAndroid Build Coastguard Worker     case BINAURAL_NONE:
439*e5436536SAndroid Build Coastguard Worker       break;
440*e5436536SAndroid Build Coastguard Worker     default:
441*e5436536SAndroid Build Coastguard Worker       return MPS_UNSUPPORTED_CONFIG;
442*e5436536SAndroid Build Coastguard Worker   }
443*e5436536SAndroid Build Coastguard Worker 
444*e5436536SAndroid Build Coastguard Worker   switch (pDecConfig->decoderMode) {
445*e5436536SAndroid Build Coastguard Worker     case EXT_HQ_ONLY:
446*e5436536SAndroid Build Coastguard Worker       break;
447*e5436536SAndroid Build Coastguard Worker     default:
448*e5436536SAndroid Build Coastguard Worker       return MPS_UNSUPPORTED_CONFIG;
449*e5436536SAndroid Build Coastguard Worker   }
450*e5436536SAndroid Build Coastguard Worker 
451*e5436536SAndroid Build Coastguard Worker   switch (pDecConfig->maxNumOutputChannels) {
452*e5436536SAndroid Build Coastguard Worker     case OUTPUT_CHANNELS_DEFAULT:
453*e5436536SAndroid Build Coastguard Worker       /* No special restrictions -> Get the level restriction: */
454*e5436536SAndroid Build Coastguard Worker       switch (pDecConfig->decoderLevel) {
455*e5436536SAndroid Build Coastguard Worker         case DECODER_LEVEL_0:
456*e5436536SAndroid Build Coastguard Worker           maxNumOutChannels = 2;
457*e5436536SAndroid Build Coastguard Worker           break;
458*e5436536SAndroid Build Coastguard Worker         default:
459*e5436536SAndroid Build Coastguard Worker           return MPS_UNSUPPORTED_CONFIG;
460*e5436536SAndroid Build Coastguard Worker       }
461*e5436536SAndroid Build Coastguard Worker       break;
462*e5436536SAndroid Build Coastguard Worker     case OUTPUT_CHANNELS_2_0:
463*e5436536SAndroid Build Coastguard Worker       maxNumOutChannels = 2;
464*e5436536SAndroid Build Coastguard Worker       break;
465*e5436536SAndroid Build Coastguard Worker     default:
466*e5436536SAndroid Build Coastguard Worker       return MPS_UNSUPPORTED_CONFIG;
467*e5436536SAndroid Build Coastguard Worker   }
468*e5436536SAndroid Build Coastguard Worker   /* ------------------------- */
469*e5436536SAndroid Build Coastguard Worker 
470*e5436536SAndroid Build Coastguard Worker   /* check if we can handle user params */
471*e5436536SAndroid Build Coastguard Worker   if (pUserParams->blindEnable == 1) {
472*e5436536SAndroid Build Coastguard Worker     return MPS_UNSUPPORTED_CONFIG;
473*e5436536SAndroid Build Coastguard Worker   }
474*e5436536SAndroid Build Coastguard Worker   {
475*e5436536SAndroid Build Coastguard Worker     switch ((SAC_DEC_OUTPUT_MODE)pUserParams->outputMode) {
476*e5436536SAndroid Build Coastguard Worker       case SACDEC_OUT_MODE_NORMAL:
477*e5436536SAndroid Build Coastguard Worker         if (maxNumOutChannels >= outChannels) {
478*e5436536SAndroid Build Coastguard Worker           *pUpmixType = UPMIX_TYPE_NORMAL;
479*e5436536SAndroid Build Coastguard Worker         } else {
480*e5436536SAndroid Build Coastguard Worker           { *pUpmixType = UPMIX_TYPE_BYPASS; }
481*e5436536SAndroid Build Coastguard Worker         }
482*e5436536SAndroid Build Coastguard Worker         break;
483*e5436536SAndroid Build Coastguard Worker       case SACDEC_OUT_MODE_STEREO:
484*e5436536SAndroid Build Coastguard Worker         if (dmxChannels == 1) {
485*e5436536SAndroid Build Coastguard Worker           if (outChannels == 2) {
486*e5436536SAndroid Build Coastguard Worker             *pUpmixType = UPMIX_TYPE_NORMAL;
487*e5436536SAndroid Build Coastguard Worker           }
488*e5436536SAndroid Build Coastguard Worker         } else {
489*e5436536SAndroid Build Coastguard Worker           *pUpmixType = UPMIX_TYPE_BYPASS;
490*e5436536SAndroid Build Coastguard Worker         }
491*e5436536SAndroid Build Coastguard Worker         break;
492*e5436536SAndroid Build Coastguard Worker       case SACDEC_OUT_MODE_6CHANNEL:
493*e5436536SAndroid Build Coastguard Worker         if (outChannels > 6) {
494*e5436536SAndroid Build Coastguard Worker           { *pUpmixType = UPMIX_TYPE_BYPASS; }
495*e5436536SAndroid Build Coastguard Worker         } else {
496*e5436536SAndroid Build Coastguard Worker           *pUpmixType = UPMIX_TYPE_NORMAL;
497*e5436536SAndroid Build Coastguard Worker         }
498*e5436536SAndroid Build Coastguard Worker         break;
499*e5436536SAndroid Build Coastguard Worker       default:
500*e5436536SAndroid Build Coastguard Worker         return MPS_UNSUPPORTED_CONFIG;
501*e5436536SAndroid Build Coastguard Worker     }
502*e5436536SAndroid Build Coastguard Worker   }
503*e5436536SAndroid Build Coastguard Worker 
504*e5436536SAndroid Build Coastguard Worker   return MPS_OK;
505*e5436536SAndroid Build Coastguard Worker }
506*e5436536SAndroid Build Coastguard Worker 
507*e5436536SAndroid Build Coastguard Worker /**
508*e5436536SAndroid Build Coastguard Worker  * \brief Init MPEG Surround decoder.
509*e5436536SAndroid Build Coastguard Worker  **/
initMpegSurroundDecoder(CMpegSurroundDecoder * pMpegSurroundDecoder)510*e5436536SAndroid Build Coastguard Worker static SACDEC_ERROR initMpegSurroundDecoder(
511*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder) {
512*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err;
513*e5436536SAndroid Build Coastguard Worker   int initFlags = MPEGS_INIT_NONE, initFlagsDec;
514*e5436536SAndroid Build Coastguard Worker   int upmixTypeCurr = pMpegSurroundDecoder->upmixType;
515*e5436536SAndroid Build Coastguard Worker 
516*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pMpegSurroundDecoder != NULL);
517*e5436536SAndroid Build Coastguard Worker 
518*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG *const pSSCinput =
519*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder->spatialSpecificConfigBackup;
520*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG *const pSSCtarget =
521*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder
522*e5436536SAndroid Build Coastguard Worker            ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
523*e5436536SAndroid Build Coastguard Worker   initFlagsDec =
524*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode];
525*e5436536SAndroid Build Coastguard Worker 
526*e5436536SAndroid Build Coastguard Worker   if (pSSCinput->coreCodec != AOT_USAC) {
527*e5436536SAndroid Build Coastguard Worker     /* here we check if we have a valid Ssc */
528*e5436536SAndroid Build Coastguard Worker     err = sscParseCheck(pSSCinput);
529*e5436536SAndroid Build Coastguard Worker     if (err != MPS_OK) goto bail;
530*e5436536SAndroid Build Coastguard Worker   }
531*e5436536SAndroid Build Coastguard Worker 
532*e5436536SAndroid Build Coastguard Worker   /* here we check if Ssc matches build; also check UParams and DecConfig */
533*e5436536SAndroid Build Coastguard Worker   /* if desired upmixType is changes                                      */
534*e5436536SAndroid Build Coastguard Worker   err = check_UParam_Build_DecConfig(
535*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder->mpegSurroundUserParams,
536*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder->decConfig, pSSCinput,
537*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder->upmixType);
538*e5436536SAndroid Build Coastguard Worker   if (err != MPS_OK) goto bail;
539*e5436536SAndroid Build Coastguard Worker 
540*e5436536SAndroid Build Coastguard Worker   /* init config */
541*e5436536SAndroid Build Coastguard Worker   if (initFlagsDec & MPEGS_INIT_CHANGE_HEADER) {
542*e5436536SAndroid Build Coastguard Worker     initFlags |= MPEGS_INIT_CONFIG;
543*e5436536SAndroid Build Coastguard Worker   }
544*e5436536SAndroid Build Coastguard Worker   /* init all states */
545*e5436536SAndroid Build Coastguard Worker   if (initFlagsDec & MPEGS_INIT_CLEAR_HISTORY) {
546*e5436536SAndroid Build Coastguard Worker     initFlags |= MASK_MPEGS_INIT_ALL_STATES;
547*e5436536SAndroid Build Coastguard Worker   }
548*e5436536SAndroid Build Coastguard Worker   if (initFlagsDec & MPEGS_INIT_CHANGE_CONCEAL_PARAMS) {
549*e5436536SAndroid Build Coastguard Worker     initFlags |= MPEGS_INIT_PARAMS_ERROR_CONCEALMENT;
550*e5436536SAndroid Build Coastguard Worker   }
551*e5436536SAndroid Build Coastguard Worker 
552*e5436536SAndroid Build Coastguard Worker   if (initFlagsDec & MPEGS_INIT_ENFORCE_REINIT) {
553*e5436536SAndroid Build Coastguard Worker     /* init all states */
554*e5436536SAndroid Build Coastguard Worker     initFlags |= MASK_MPEGS_INIT_ALL_STATES;
555*e5436536SAndroid Build Coastguard Worker     initFlags |= MASK_MPEGS_INIT_ALL_PARAMS;
556*e5436536SAndroid Build Coastguard Worker   } else {
557*e5436536SAndroid Build Coastguard Worker     /* analyse states which have to be initialized */
558*e5436536SAndroid Build Coastguard Worker     mpegSurroundDecoder_CalcInitFlags(
559*e5436536SAndroid Build Coastguard Worker         pSSCtarget, pSSCinput,
560*e5436536SAndroid Build Coastguard Worker         (upmixTypeCurr !=
561*e5436536SAndroid Build Coastguard Worker          pMpegSurroundDecoder->upmixType), /* upmixType changed */
562*e5436536SAndroid Build Coastguard Worker         0, (initFlagsDec & MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX) ? 1 : 0,
563*e5436536SAndroid Build Coastguard Worker         &initFlags);
564*e5436536SAndroid Build Coastguard Worker   }
565*e5436536SAndroid Build Coastguard Worker 
566*e5436536SAndroid Build Coastguard Worker   {
567*e5436536SAndroid Build Coastguard Worker     int nrOfQmfBands;
568*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(pSSCtarget, pSSCinput, sizeof(SPATIAL_SPECIFIC_CONFIG));
569*e5436536SAndroid Build Coastguard Worker 
570*e5436536SAndroid Build Coastguard Worker     nrOfQmfBands = mpegSurroundDecoder_GetNrOfQmfBands(
571*e5436536SAndroid Build Coastguard Worker         pSSCtarget, pSSCtarget->samplingFreq);
572*e5436536SAndroid Build Coastguard Worker     err = FDK_SpatialDecInit(
573*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->pSpatialDec,
574*e5436536SAndroid Build Coastguard Worker         &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode],
575*e5436536SAndroid Build Coastguard Worker         pSSCtarget, nrOfQmfBands, pMpegSurroundDecoder->upmixType,
576*e5436536SAndroid Build Coastguard Worker         &pMpegSurroundDecoder->mpegSurroundUserParams, initFlags);
577*e5436536SAndroid Build Coastguard Worker 
578*e5436536SAndroid Build Coastguard Worker     if (err != MPS_OK) goto bail;
579*e5436536SAndroid Build Coastguard Worker 
580*e5436536SAndroid Build Coastguard Worker     /* Signal that we got a header and can go on decoding */
581*e5436536SAndroid Build Coastguard Worker     if (err == MPS_OK) {
582*e5436536SAndroid Build Coastguard Worker       initFlagsDec = MPEGS_INIT_OK;
583*e5436536SAndroid Build Coastguard Worker       {
584*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
585*e5436536SAndroid Build Coastguard Worker             MPEGS_SYNC_FOUND;
586*e5436536SAndroid Build Coastguard Worker       }
587*e5436536SAndroid Build Coastguard Worker     }
588*e5436536SAndroid Build Coastguard Worker   }
589*e5436536SAndroid Build Coastguard Worker 
590*e5436536SAndroid Build Coastguard Worker bail:
591*e5436536SAndroid Build Coastguard Worker   pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] =
592*e5436536SAndroid Build Coastguard Worker       initFlagsDec;
593*e5436536SAndroid Build Coastguard Worker   return err;
594*e5436536SAndroid Build Coastguard Worker }
595*e5436536SAndroid Build Coastguard Worker 
596*e5436536SAndroid Build Coastguard Worker /**
597*e5436536SAndroid Build Coastguard Worker  * \brief Init MPEG Surround decoder.
598*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_Init(CMpegSurroundDecoder * pMpegSurroundDecoder)599*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR mpegSurroundDecoder_Init(
600*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder) {
601*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
602*e5436536SAndroid Build Coastguard Worker 
603*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) {
604*e5436536SAndroid Build Coastguard Worker     err = initMpegSurroundDecoder(pMpegSurroundDecoder);
605*e5436536SAndroid Build Coastguard Worker   }
606*e5436536SAndroid Build Coastguard Worker   return err;
607*e5436536SAndroid Build Coastguard Worker }
608*e5436536SAndroid Build Coastguard Worker 
609*e5436536SAndroid Build Coastguard Worker /**
610*e5436536SAndroid Build Coastguard Worker  * \brief Open MPEG Surround decoder.
611*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_Create(CMpegSurroundDecoder ** pMpegSurroundDecoder,int stereoConfigIndex,HANDLE_FDK_QMF_DOMAIN pQmfDomain)612*e5436536SAndroid Build Coastguard Worker static SACDEC_ERROR mpegSurroundDecoder_Create(
613*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex,
614*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_QMF_DOMAIN pQmfDomain) {
615*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
616*e5436536SAndroid Build Coastguard Worker   CMpegSurroundDecoder *sacDec = NULL;
617*e5436536SAndroid Build Coastguard Worker   spatialDec *self = NULL;
618*e5436536SAndroid Build Coastguard Worker 
619*e5436536SAndroid Build Coastguard Worker   /* decoderLevel  decoderMode  maxNumOutputChannels  binauralMode */
620*e5436536SAndroid Build Coastguard Worker   static const SPATIAL_DEC_CONFIG decConfig = {
621*e5436536SAndroid Build Coastguard Worker       (CFG_LEVEL)(0), EXT_HQ_ONLY, OUTPUT_CHANNELS_DEFAULT, BINAURAL_NONE};
622*e5436536SAndroid Build Coastguard Worker 
623*e5436536SAndroid Build Coastguard Worker   if (*pMpegSurroundDecoder == NULL) {
624*e5436536SAndroid Build Coastguard Worker     FDK_ALLOCATE_MEMORY_1D(*pMpegSurroundDecoder, 1, CMpegSurroundDecoder)
625*e5436536SAndroid Build Coastguard Worker 
626*e5436536SAndroid Build Coastguard Worker     for (int i = 0; i < 1; i++) {
627*e5436536SAndroid Build Coastguard Worker       err = SpatialDecCreateBsFrame(&(*pMpegSurroundDecoder)->bsFrames[i],
628*e5436536SAndroid Build Coastguard Worker                                     &(*pMpegSurroundDecoder)->llState);
629*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) {
630*e5436536SAndroid Build Coastguard Worker         sacDec = *pMpegSurroundDecoder;
631*e5436536SAndroid Build Coastguard Worker         goto bail;
632*e5436536SAndroid Build Coastguard Worker       }
633*e5436536SAndroid Build Coastguard Worker     }
634*e5436536SAndroid Build Coastguard Worker     (*pMpegSurroundDecoder)->pQmfDomain = pQmfDomain;
635*e5436536SAndroid Build Coastguard Worker 
636*e5436536SAndroid Build Coastguard Worker     (*pMpegSurroundDecoder)->bsFrameDelay = 1;
637*e5436536SAndroid Build Coastguard Worker     (*pMpegSurroundDecoder)->bsFrameParse = 0;
638*e5436536SAndroid Build Coastguard Worker     (*pMpegSurroundDecoder)->bsFrameDecode = 0;
639*e5436536SAndroid Build Coastguard Worker 
640*e5436536SAndroid Build Coastguard Worker     return err;
641*e5436536SAndroid Build Coastguard Worker   } else {
642*e5436536SAndroid Build Coastguard Worker     sacDec = *pMpegSurroundDecoder;
643*e5436536SAndroid Build Coastguard Worker   }
644*e5436536SAndroid Build Coastguard Worker 
645*e5436536SAndroid Build Coastguard Worker   if (sacDec->pSpatialDec == NULL) {
646*e5436536SAndroid Build Coastguard Worker     if ((self = FDK_SpatialDecOpen(&decConfig, stereoConfigIndex)) == NULL) {
647*e5436536SAndroid Build Coastguard Worker       err = MPS_OUTOFMEMORY;
648*e5436536SAndroid Build Coastguard Worker       goto bail;
649*e5436536SAndroid Build Coastguard Worker     }
650*e5436536SAndroid Build Coastguard Worker   } else {
651*e5436536SAndroid Build Coastguard Worker     self = sacDec->pSpatialDec;
652*e5436536SAndroid Build Coastguard Worker   }
653*e5436536SAndroid Build Coastguard Worker 
654*e5436536SAndroid Build Coastguard Worker   self->pQmfDomain = sacDec->pQmfDomain;
655*e5436536SAndroid Build Coastguard Worker 
656*e5436536SAndroid Build Coastguard Worker   sacDec->pSpatialDec = self;
657*e5436536SAndroid Build Coastguard Worker 
658*e5436536SAndroid Build Coastguard Worker   /* default parameter set */
659*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.outputMode = SACDEC_OUT_MODE_NORMAL;
660*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.blindEnable = 0;
661*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.bypassMode = 0;
662*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.concealMethod = 1;
663*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.concealNumKeepFrames = 10;
664*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.concealFadeOutSlopeLength = 5;
665*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.concealFadeInSlopeLength = 5;
666*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUserParams.concealNumReleaseFrames = 3;
667*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundSscIsGlobalCfg = 0;
668*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundUseTimeInterface = 1;
669*e5436536SAndroid Build Coastguard Worker   sacDec->mpegSurroundDecoderLevel = decConfig.decoderLevel;
670*e5436536SAndroid Build Coastguard Worker 
671*e5436536SAndroid Build Coastguard Worker   sacDec->upmixType = UPMIX_TYPE_NORMAL;
672*e5436536SAndroid Build Coastguard Worker 
673*e5436536SAndroid Build Coastguard Worker   /* signalize spatial decoder re-initalization */
674*e5436536SAndroid Build Coastguard Worker   updateMpegSurroundDecoderStatus(sacDec, MPEGS_INIT_ENFORCE_REINIT,
675*e5436536SAndroid Build Coastguard Worker                                   MPEGS_SYNC_LOST, MPEGS_STOP);
676*e5436536SAndroid Build Coastguard Worker 
677*e5436536SAndroid Build Coastguard Worker   /* return decoder instance */
678*e5436536SAndroid Build Coastguard Worker   *pMpegSurroundDecoder = sacDec;
679*e5436536SAndroid Build Coastguard Worker   sacDec->decConfig = decConfig;
680*e5436536SAndroid Build Coastguard Worker 
681*e5436536SAndroid Build Coastguard Worker   SpatialDecInitParserContext(sacDec->pSpatialDec);
682*e5436536SAndroid Build Coastguard Worker 
683*e5436536SAndroid Build Coastguard Worker   return err;
684*e5436536SAndroid Build Coastguard Worker 
685*e5436536SAndroid Build Coastguard Worker bail:
686*e5436536SAndroid Build Coastguard Worker   if (sacDec != NULL) {
687*e5436536SAndroid Build Coastguard Worker     mpegSurroundDecoder_Close(sacDec);
688*e5436536SAndroid Build Coastguard Worker   }
689*e5436536SAndroid Build Coastguard Worker   *pMpegSurroundDecoder = NULL;
690*e5436536SAndroid Build Coastguard Worker   if (err == MPS_OK) {
691*e5436536SAndroid Build Coastguard Worker     return MPS_OUTOFMEMORY;
692*e5436536SAndroid Build Coastguard Worker   } else {
693*e5436536SAndroid Build Coastguard Worker     return err;
694*e5436536SAndroid Build Coastguard Worker   }
695*e5436536SAndroid Build Coastguard Worker }
696*e5436536SAndroid Build Coastguard Worker 
697*e5436536SAndroid Build Coastguard Worker /**
698*e5436536SAndroid Build Coastguard Worker  * \brief Config MPEG Surround decoder.
699*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_Config(CMpegSurroundDecoder * pMpegSurroundDecoder,HANDLE_FDK_BITSTREAM hBs,AUDIO_OBJECT_TYPE coreCodec,INT samplingRate,INT frameSize,INT numChannels,INT stereoConfigIndex,INT coreSbrFrameLengthIndex,INT configBytes,const UCHAR configMode,UCHAR * configChanged)700*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR mpegSurroundDecoder_Config(
701*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
702*e5436536SAndroid Build Coastguard Worker     AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize,
703*e5436536SAndroid Build Coastguard Worker     INT numChannels, INT stereoConfigIndex, INT coreSbrFrameLengthIndex,
704*e5436536SAndroid Build Coastguard Worker     INT configBytes, const UCHAR configMode, UCHAR *configChanged) {
705*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
706*e5436536SAndroid Build Coastguard Worker   INT nInputChannels;
707*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig;
708*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG *pSsc =
709*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder->spatialSpecificConfigBackup;
710*e5436536SAndroid Build Coastguard Worker 
711*e5436536SAndroid Build Coastguard Worker   switch (coreCodec) {
712*e5436536SAndroid Build Coastguard Worker     case AOT_DRM_USAC:
713*e5436536SAndroid Build Coastguard Worker     case AOT_USAC:
714*e5436536SAndroid Build Coastguard Worker       if (configMode == AC_CM_DET_CFG_CHANGE) {
715*e5436536SAndroid Build Coastguard Worker         /* In config detection mode write spatial specific config parameters
716*e5436536SAndroid Build Coastguard Worker          * into temporarily allocated structure */
717*e5436536SAndroid Build Coastguard Worker         err = SpatialDecParseMps212Config(
718*e5436536SAndroid Build Coastguard Worker             hBs, &spatialSpecificConfig, samplingRate, coreCodec,
719*e5436536SAndroid Build Coastguard Worker             stereoConfigIndex, coreSbrFrameLengthIndex);
720*e5436536SAndroid Build Coastguard Worker         nInputChannels = spatialSpecificConfig.nInputChannels;
721*e5436536SAndroid Build Coastguard Worker         pSsc = &spatialSpecificConfig;
722*e5436536SAndroid Build Coastguard Worker       } else {
723*e5436536SAndroid Build Coastguard Worker         err = SpatialDecParseMps212Config(
724*e5436536SAndroid Build Coastguard Worker             hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
725*e5436536SAndroid Build Coastguard Worker             samplingRate, coreCodec, stereoConfigIndex,
726*e5436536SAndroid Build Coastguard Worker             coreSbrFrameLengthIndex);
727*e5436536SAndroid Build Coastguard Worker         nInputChannels =
728*e5436536SAndroid Build Coastguard Worker             pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels;
729*e5436536SAndroid Build Coastguard Worker       }
730*e5436536SAndroid Build Coastguard Worker       if ((err == MPS_OK) && (numChannels != nInputChannels)) {
731*e5436536SAndroid Build Coastguard Worker         err = MPS_PARSE_ERROR;
732*e5436536SAndroid Build Coastguard Worker       }
733*e5436536SAndroid Build Coastguard Worker       break;
734*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_ELD:
735*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_LD:
736*e5436536SAndroid Build Coastguard Worker       if (configMode == AC_CM_DET_CFG_CHANGE) {
737*e5436536SAndroid Build Coastguard Worker         /* In config detection mode write spatial specific config parameters
738*e5436536SAndroid Build Coastguard Worker          * into temporarily allocated structure */
739*e5436536SAndroid Build Coastguard Worker         err = SpatialDecParseSpecificConfig(hBs, &spatialSpecificConfig,
740*e5436536SAndroid Build Coastguard Worker                                             configBytes, coreCodec);
741*e5436536SAndroid Build Coastguard Worker         nInputChannels = spatialSpecificConfig.nInputChannels;
742*e5436536SAndroid Build Coastguard Worker         pSsc = &spatialSpecificConfig;
743*e5436536SAndroid Build Coastguard Worker       } else {
744*e5436536SAndroid Build Coastguard Worker         err = SpatialDecParseSpecificConfig(
745*e5436536SAndroid Build Coastguard Worker             hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
746*e5436536SAndroid Build Coastguard Worker             configBytes, coreCodec);
747*e5436536SAndroid Build Coastguard Worker         nInputChannels =
748*e5436536SAndroid Build Coastguard Worker             pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels;
749*e5436536SAndroid Build Coastguard Worker       }
750*e5436536SAndroid Build Coastguard Worker       /* check number of channels for channel_configuration > 0  */
751*e5436536SAndroid Build Coastguard Worker       if ((err == MPS_OK) && (numChannels > 0) &&
752*e5436536SAndroid Build Coastguard Worker           (numChannels != nInputChannels)) {
753*e5436536SAndroid Build Coastguard Worker         err = MPS_PARSE_ERROR;
754*e5436536SAndroid Build Coastguard Worker       }
755*e5436536SAndroid Build Coastguard Worker       break;
756*e5436536SAndroid Build Coastguard Worker     default:
757*e5436536SAndroid Build Coastguard Worker       err = MPS_UNSUPPORTED_FORMAT;
758*e5436536SAndroid Build Coastguard Worker       break;
759*e5436536SAndroid Build Coastguard Worker   }
760*e5436536SAndroid Build Coastguard Worker 
761*e5436536SAndroid Build Coastguard Worker   if (err != MPS_OK) {
762*e5436536SAndroid Build Coastguard Worker     goto bail;
763*e5436536SAndroid Build Coastguard Worker   }
764*e5436536SAndroid Build Coastguard Worker 
765*e5436536SAndroid Build Coastguard Worker   err = sscCheckOutOfBand(pSsc, coreCodec, samplingRate, frameSize);
766*e5436536SAndroid Build Coastguard Worker 
767*e5436536SAndroid Build Coastguard Worker   if (err != MPS_OK) {
768*e5436536SAndroid Build Coastguard Worker     goto bail;
769*e5436536SAndroid Build Coastguard Worker   }
770*e5436536SAndroid Build Coastguard Worker 
771*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_DET_CFG_CHANGE) {
772*e5436536SAndroid Build Coastguard Worker     return err;
773*e5436536SAndroid Build Coastguard Worker   }
774*e5436536SAndroid Build Coastguard Worker 
775*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_ALLOC_MEM) {
776*e5436536SAndroid Build Coastguard Worker     if (*configChanged) {
777*e5436536SAndroid Build Coastguard Worker       err = mpegSurroundDecoder_Open(&pMpegSurroundDecoder, stereoConfigIndex,
778*e5436536SAndroid Build Coastguard Worker                                      NULL);
779*e5436536SAndroid Build Coastguard Worker       if (err) {
780*e5436536SAndroid Build Coastguard Worker         return err;
781*e5436536SAndroid Build Coastguard Worker       }
782*e5436536SAndroid Build Coastguard Worker     }
783*e5436536SAndroid Build Coastguard Worker   }
784*e5436536SAndroid Build Coastguard Worker 
785*e5436536SAndroid Build Coastguard Worker   {
786*e5436536SAndroid Build Coastguard Worker     SPATIAL_SPECIFIC_CONFIG *sscParse =
787*e5436536SAndroid Build Coastguard Worker         &pMpegSurroundDecoder
788*e5436536SAndroid Build Coastguard Worker              ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse];
789*e5436536SAndroid Build Coastguard Worker 
790*e5436536SAndroid Build Coastguard Worker     if (FDK_SpatialDecCompareSpatialSpecificConfigHeader(
791*e5436536SAndroid Build Coastguard Worker             &pMpegSurroundDecoder->spatialSpecificConfigBackup, sscParse)) {
792*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse] |=
793*e5436536SAndroid Build Coastguard Worker           MPEGS_INIT_CHANGE_HEADER;
794*e5436536SAndroid Build Coastguard Worker       /* Error resilience code */
795*e5436536SAndroid Build Coastguard Worker       if (pMpegSurroundDecoder->pSpatialDec == NULL) {
796*e5436536SAndroid Build Coastguard Worker         err = MPS_NOTOK;
797*e5436536SAndroid Build Coastguard Worker         goto bail;
798*e5436536SAndroid Build Coastguard Worker       }
799*e5436536SAndroid Build Coastguard Worker       SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec);
800*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->pSpatialDec->pConfigCurrent =
801*e5436536SAndroid Build Coastguard Worker           &pMpegSurroundDecoder
802*e5436536SAndroid Build Coastguard Worker                ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
803*e5436536SAndroid Build Coastguard Worker     }
804*e5436536SAndroid Build Coastguard Worker   }
805*e5436536SAndroid Build Coastguard Worker 
806*e5436536SAndroid Build Coastguard Worker   if (err == MPS_OK) {
807*e5436536SAndroid Build Coastguard Worker     /* We got a valid out-of-band configuration so label it accordingly. */
808*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 1;
809*e5436536SAndroid Build Coastguard Worker   }
810*e5436536SAndroid Build Coastguard Worker 
811*e5436536SAndroid Build Coastguard Worker bail:
812*e5436536SAndroid Build Coastguard Worker   return err;
813*e5436536SAndroid Build Coastguard Worker }
814*e5436536SAndroid Build Coastguard Worker 
815*e5436536SAndroid Build Coastguard Worker /**
816*e5436536SAndroid Build Coastguard Worker  * \brief Determine MPEG Surround operation mode.
817*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundOperationMode(CMpegSurroundDecoder * pMpegSurroundDecoder,int mpsDataBits)818*e5436536SAndroid Build Coastguard Worker static MPEGS_OPMODE mpegSurroundOperationMode(
819*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder, int mpsDataBits) {
820*e5436536SAndroid Build Coastguard Worker   MPEGS_OPMODE mode;
821*e5436536SAndroid Build Coastguard Worker 
822*e5436536SAndroid Build Coastguard Worker   {
823*e5436536SAndroid Build Coastguard Worker     if ((mpsDataBits > 0) &&
824*e5436536SAndroid Build Coastguard Worker         (pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable == 0)) {
825*e5436536SAndroid Build Coastguard Worker       mode = MPEGS_OPMODE_MPS_PAYLOAD; /* Mode: Normal, Stereo or Binaural */
826*e5436536SAndroid Build Coastguard Worker     } else {
827*e5436536SAndroid Build Coastguard Worker       mode = MPEGS_OPMODE_NO_MPS_PAYLOAD; /* Mode: No MPEG Surround Payload */
828*e5436536SAndroid Build Coastguard Worker       updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
829*e5436536SAndroid Build Coastguard Worker                                       MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
830*e5436536SAndroid Build Coastguard Worker                                       MPEGS_STOP);
831*e5436536SAndroid Build Coastguard Worker     }
832*e5436536SAndroid Build Coastguard Worker   }
833*e5436536SAndroid Build Coastguard Worker 
834*e5436536SAndroid Build Coastguard Worker   return (mode);
835*e5436536SAndroid Build Coastguard Worker }
836*e5436536SAndroid Build Coastguard Worker 
837*e5436536SAndroid Build Coastguard Worker /**
838*e5436536SAndroid Build Coastguard Worker  * \brief  Check ssc for parse errors.
839*e5436536SAndroid Build Coastguard Worker  *         This one is called in initMpegSurroundDecoder()
840*e5436536SAndroid Build Coastguard Worker  *         to ensure checking of inband and out-of-band mps configs.
841*e5436536SAndroid Build Coastguard Worker  *         Only parse errors checked here! Check for valid config is done
842*e5436536SAndroid Build Coastguard Worker  *         in check_UParam_Build_DecConfig()!
843*e5436536SAndroid Build Coastguard Worker  *
844*e5436536SAndroid Build Coastguard Worker  * \param pSsc         spatial specific config handle.
845*e5436536SAndroid Build Coastguard Worker  *
846*e5436536SAndroid Build Coastguard Worker  * \return  MPS_OK on sucess, and else on parse error.
847*e5436536SAndroid Build Coastguard Worker  */
sscParseCheck(const SPATIAL_SPECIFIC_CONFIG * pSsc)848*e5436536SAndroid Build Coastguard Worker static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc) {
849*e5436536SAndroid Build Coastguard Worker   if (pSsc->samplingFreq > 96000) return MPS_PARSE_ERROR;
850*e5436536SAndroid Build Coastguard Worker   if (pSsc->samplingFreq < 8000) return MPS_PARSE_ERROR;
851*e5436536SAndroid Build Coastguard Worker 
852*e5436536SAndroid Build Coastguard Worker   if ((pSsc->treeConfig < 0) || (pSsc->treeConfig > 7)) {
853*e5436536SAndroid Build Coastguard Worker     return MPS_PARSE_ERROR;
854*e5436536SAndroid Build Coastguard Worker   }
855*e5436536SAndroid Build Coastguard Worker 
856*e5436536SAndroid Build Coastguard Worker   if ((pSsc->quantMode < 0) || (pSsc->quantMode > 2)) {
857*e5436536SAndroid Build Coastguard Worker     return MPS_PARSE_ERROR;
858*e5436536SAndroid Build Coastguard Worker   }
859*e5436536SAndroid Build Coastguard Worker 
860*e5436536SAndroid Build Coastguard Worker   /* now we are sure there were no parsing errors */
861*e5436536SAndroid Build Coastguard Worker 
862*e5436536SAndroid Build Coastguard Worker   return MPS_OK;
863*e5436536SAndroid Build Coastguard Worker }
864*e5436536SAndroid Build Coastguard Worker 
865*e5436536SAndroid Build Coastguard Worker /**
866*e5436536SAndroid Build Coastguard Worker  * \brief  Check number of time slots
867*e5436536SAndroid Build Coastguard Worker  *
868*e5436536SAndroid Build Coastguard Worker  * Basically the mps frame length must be a multiple of the core coder frame
869*e5436536SAndroid Build Coastguard Worker  * length. The below table shows all valid configurations in detail. See ISO/IEC
870*e5436536SAndroid Build Coastguard Worker  * 23003-1: "Table 4A - Allowed values for bsFrameLength in the Baseline MPEG
871*e5436536SAndroid Build Coastguard Worker  * Surround Profile"
872*e5436536SAndroid Build Coastguard Worker  *
873*e5436536SAndroid Build Coastguard Worker  * Downmix Coder        Downmix Code      Allowed values for bsFrameLength
874*e5436536SAndroid Build Coastguard Worker  * Allowed frame sizes for normal, downsampled and upsampled MPS Framelength
875*e5436536SAndroid Build Coastguard Worker  *                      (QMF Samples)
876*e5436536SAndroid Build Coastguard Worker  *
877*e5436536SAndroid Build Coastguard Worker  * AAC 1024                  16           15, 31, 47, 63 1024  2048  3072  4096
878*e5436536SAndroid Build Coastguard Worker  * downsampled MPS           32           31, 63 1024  2048 upsampled MPS
879*e5436536SAndroid Build Coastguard Worker  * 8            7, 15, 23, 31, 39, 47, 55, 63, 71    1024  2048  3072  4096
880*e5436536SAndroid Build Coastguard Worker  * 5120  6144  7168  8192  9216
881*e5436536SAndroid Build Coastguard Worker  *
882*e5436536SAndroid Build Coastguard Worker  * AAC 960                   15           14, 29, 44, 59 960  1920  2880  3840
883*e5436536SAndroid Build Coastguard Worker  * downsampled MPS           30           29, 59 960  1920 upsampled MPS
884*e5436536SAndroid Build Coastguard Worker  * 7,5           14, 29, 44, 59                        1920  3840  5760  7680
885*e5436536SAndroid Build Coastguard Worker  *
886*e5436536SAndroid Build Coastguard Worker  * HE-AAC 1024/2048          32           31, 63 2048  4096 downsampled MPS
887*e5436536SAndroid Build Coastguard Worker  * 64           63                                    2048 upsampled MPS
888*e5436536SAndroid Build Coastguard Worker  * 16           15, 31, 47, 63                        2048  4096  6144  8192
889*e5436536SAndroid Build Coastguard Worker  *
890*e5436536SAndroid Build Coastguard Worker  * HE-AAC 960/1920           30           29, 59 1920  3840 downsampled MPS
891*e5436536SAndroid Build Coastguard Worker  * 60           59                                    1920 upsampled MPS
892*e5436536SAndroid Build Coastguard Worker  * 15           14, 29, 44, 59                        1920  3840  5760  7680
893*e5436536SAndroid Build Coastguard Worker  *
894*e5436536SAndroid Build Coastguard Worker  * BSAC                      16           15, 31, 47, 63 1024  2048  3072  4096
895*e5436536SAndroid Build Coastguard Worker  * downsampled MPS           32           31, 63 1024  2048 upsampled MPS
896*e5436536SAndroid Build Coastguard Worker  * 8            7, 15, 23, 31, 39, 47, 55, 63, 71    1024  2048  3072  4096
897*e5436536SAndroid Build Coastguard Worker  * 5120  6144  7168  8192  9216
898*e5436536SAndroid Build Coastguard Worker  *
899*e5436536SAndroid Build Coastguard Worker  * BSAC with SBR             32           31, 63 2048  4096 downsampled MPS
900*e5436536SAndroid Build Coastguard Worker  * 64           63                                    2048 upsampled MPS
901*e5436536SAndroid Build Coastguard Worker  * 16           15, 31, 47, 63                        2048  4096  6144  8192
902*e5436536SAndroid Build Coastguard Worker  *
903*e5436536SAndroid Build Coastguard Worker  * AAC LD 512                 8            7, 15, 23, 31, 39, 47, 55, 63, 71
904*e5436536SAndroid Build Coastguard Worker  * 512  1024  1536  2048  2560  3072  3584  4096  4608 downsampled MPS
905*e5436536SAndroid Build Coastguard Worker  * 16           15, 31, 47, 63                         512  1024  1536  2048
906*e5436536SAndroid Build Coastguard Worker  *
907*e5436536SAndroid Build Coastguard Worker  * AAC ELD 512                8            7, 15, 23, 31, 39, 47, 55, 63, 71
908*e5436536SAndroid Build Coastguard Worker  * 512  1024  1536  2048  2560  3072  3584  4096  4608 downsampled MPS
909*e5436536SAndroid Build Coastguard Worker  * 16           15, 31, 47, 63                         512  1024  1536  2048
910*e5436536SAndroid Build Coastguard Worker  *
911*e5436536SAndroid Build Coastguard Worker  * AAC ELD with SBR 512/1024 16           15, 31, 47, 63 1024  2048  3072  4096
912*e5436536SAndroid Build Coastguard Worker  * downsampled MPS           32           31, 63 1024  2048 upsampled MPS
913*e5436536SAndroid Build Coastguard Worker  * 8            7, 15, 23, 31, 39, 47, 55, 63, 71    1024  2048  3072  4096
914*e5436536SAndroid Build Coastguard Worker  * 5120  6144  7168  8192  9216
915*e5436536SAndroid Build Coastguard Worker  *
916*e5436536SAndroid Build Coastguard Worker  * MPEG1/2 Layer II          18           17, 35, 53, 71 1152  2304  3456  4608
917*e5436536SAndroid Build Coastguard Worker  * downsampled MPS           36           35, 71 1152  2304
918*e5436536SAndroid Build Coastguard Worker  *
919*e5436536SAndroid Build Coastguard Worker  * MPEG1/2 Layer III         18           17, 35, 53, 71 1152  2304  3456  4608
920*e5436536SAndroid Build Coastguard Worker  * downsampled MPS           36           35, 71 1152  2304
921*e5436536SAndroid Build Coastguard Worker  *
922*e5436536SAndroid Build Coastguard Worker  * \param frameLength
923*e5436536SAndroid Build Coastguard Worker  * \param qmfBands
924*e5436536SAndroid Build Coastguard Worker  * \param timeSlots
925*e5436536SAndroid Build Coastguard Worker  *
926*e5436536SAndroid Build Coastguard Worker  * \return  error code
927*e5436536SAndroid Build Coastguard Worker  */
checkTimeSlots(int frameLength,int qmfBands,int timeSlots)928*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR checkTimeSlots(int frameLength, int qmfBands, int timeSlots) {
929*e5436536SAndroid Build Coastguard Worker   int len;
930*e5436536SAndroid Build Coastguard Worker   int maxFrameLength;
931*e5436536SAndroid Build Coastguard Worker 
932*e5436536SAndroid Build Coastguard Worker   if (qmfBands == 64) {
933*e5436536SAndroid Build Coastguard Worker     /* normal MPEG Surround */
934*e5436536SAndroid Build Coastguard Worker     switch (frameLength) {
935*e5436536SAndroid Build Coastguard Worker       case 960:
936*e5436536SAndroid Build Coastguard Worker       case 1920:
937*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 3840;
938*e5436536SAndroid Build Coastguard Worker         break;
939*e5436536SAndroid Build Coastguard Worker       case 1024:
940*e5436536SAndroid Build Coastguard Worker       case 2048:
941*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 4096;
942*e5436536SAndroid Build Coastguard Worker         break;
943*e5436536SAndroid Build Coastguard Worker       case 512:
944*e5436536SAndroid Build Coastguard Worker       case 1152:
945*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 4608;
946*e5436536SAndroid Build Coastguard Worker         break;
947*e5436536SAndroid Build Coastguard Worker       default:
948*e5436536SAndroid Build Coastguard Worker         return MPS_PARSE_ERROR;
949*e5436536SAndroid Build Coastguard Worker     }
950*e5436536SAndroid Build Coastguard Worker   } else if (qmfBands == 32) {
951*e5436536SAndroid Build Coastguard Worker     /* downsampled MPEG Surround */
952*e5436536SAndroid Build Coastguard Worker     switch (frameLength) {
953*e5436536SAndroid Build Coastguard Worker       case 960:
954*e5436536SAndroid Build Coastguard Worker       case 1920:
955*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 1920;
956*e5436536SAndroid Build Coastguard Worker         break;
957*e5436536SAndroid Build Coastguard Worker       case 512:
958*e5436536SAndroid Build Coastguard Worker       case 1024:
959*e5436536SAndroid Build Coastguard Worker       case 2048:
960*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 2048;
961*e5436536SAndroid Build Coastguard Worker         break;
962*e5436536SAndroid Build Coastguard Worker       case 1152:
963*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 2304;
964*e5436536SAndroid Build Coastguard Worker         break;
965*e5436536SAndroid Build Coastguard Worker       default:
966*e5436536SAndroid Build Coastguard Worker         return MPS_PARSE_ERROR;
967*e5436536SAndroid Build Coastguard Worker     }
968*e5436536SAndroid Build Coastguard Worker   } else if (qmfBands == 128) {
969*e5436536SAndroid Build Coastguard Worker     /* upsampled MPEG Surround */
970*e5436536SAndroid Build Coastguard Worker     switch (frameLength) {
971*e5436536SAndroid Build Coastguard Worker       case 1920:
972*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 7680;
973*e5436536SAndroid Build Coastguard Worker         break;
974*e5436536SAndroid Build Coastguard Worker       case 1024:
975*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 9216;
976*e5436536SAndroid Build Coastguard Worker         break;
977*e5436536SAndroid Build Coastguard Worker       case 2048:
978*e5436536SAndroid Build Coastguard Worker         maxFrameLength = 8192;
979*e5436536SAndroid Build Coastguard Worker         break;
980*e5436536SAndroid Build Coastguard Worker       case 512:
981*e5436536SAndroid Build Coastguard Worker       case 960:
982*e5436536SAndroid Build Coastguard Worker       case 1152:
983*e5436536SAndroid Build Coastguard Worker       /* no break, no support for upsampled MPEG Surround */
984*e5436536SAndroid Build Coastguard Worker       default:
985*e5436536SAndroid Build Coastguard Worker         return MPS_PARSE_ERROR;
986*e5436536SAndroid Build Coastguard Worker     }
987*e5436536SAndroid Build Coastguard Worker   } else {
988*e5436536SAndroid Build Coastguard Worker     return MPS_PARSE_ERROR;
989*e5436536SAndroid Build Coastguard Worker   }
990*e5436536SAndroid Build Coastguard Worker 
991*e5436536SAndroid Build Coastguard Worker   len = frameLength;
992*e5436536SAndroid Build Coastguard Worker 
993*e5436536SAndroid Build Coastguard Worker   while (len <= maxFrameLength) {
994*e5436536SAndroid Build Coastguard Worker     if (len == timeSlots * qmfBands) {
995*e5436536SAndroid Build Coastguard Worker       return MPS_OK;
996*e5436536SAndroid Build Coastguard Worker     }
997*e5436536SAndroid Build Coastguard Worker     len += frameLength;
998*e5436536SAndroid Build Coastguard Worker   }
999*e5436536SAndroid Build Coastguard Worker   return MPS_PARSE_ERROR;
1000*e5436536SAndroid Build Coastguard Worker }
1001*e5436536SAndroid Build Coastguard Worker 
1002*e5436536SAndroid Build Coastguard Worker /**
1003*e5436536SAndroid Build Coastguard Worker  * \brief  Check ssc for consistency (e.g. bit errors could cause trouble)
1004*e5436536SAndroid Build Coastguard Worker  *         First of currently two ssc-checks.
1005*e5436536SAndroid Build Coastguard Worker  *         This (old) one is called in mpegSurroundDecoder_Apply()
1006*e5436536SAndroid Build Coastguard Worker  *         only if inband mps config is contained in stream.
1007*e5436536SAndroid Build Coastguard Worker  *
1008*e5436536SAndroid Build Coastguard Worker  *         New ssc check is split in two functions sscParseCheck() and
1009*e5436536SAndroid Build Coastguard Worker  * check_UParam_Build_DecConfig(). sscParseCheck() checks only for correct
1010*e5436536SAndroid Build Coastguard Worker  * parsing. check_UParam_Build_DecConfig() is used to check if we have a
1011*e5436536SAndroid Build Coastguard Worker  * valid config. Both are called in initMpegSurroundDecoder() to ensure
1012*e5436536SAndroid Build Coastguard Worker  * checking of inband and out-of-band mps configs.
1013*e5436536SAndroid Build Coastguard Worker  *
1014*e5436536SAndroid Build Coastguard Worker  *         If this function can be integrated into the new functions.
1015*e5436536SAndroid Build Coastguard Worker  *         We can remove this one.
1016*e5436536SAndroid Build Coastguard Worker  *
1017*e5436536SAndroid Build Coastguard Worker  * \param pSsc         spatial specific config handle.
1018*e5436536SAndroid Build Coastguard Worker  * \param frameLength
1019*e5436536SAndroid Build Coastguard Worker  * \param sampleRate
1020*e5436536SAndroid Build Coastguard Worker  *
1021*e5436536SAndroid Build Coastguard Worker  * \return  MPS_OK on sucess, and else on failure.
1022*e5436536SAndroid Build Coastguard Worker  */
sscCheckInBand(SPATIAL_SPECIFIC_CONFIG * pSsc,int frameLength,int sampleRate)1023*e5436536SAndroid Build Coastguard Worker static SACDEC_ERROR sscCheckInBand(SPATIAL_SPECIFIC_CONFIG *pSsc,
1024*e5436536SAndroid Build Coastguard Worker                                    int frameLength, int sampleRate) {
1025*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
1026*e5436536SAndroid Build Coastguard Worker   int qmfBands;
1027*e5436536SAndroid Build Coastguard Worker 
1028*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pSsc != NULL);
1029*e5436536SAndroid Build Coastguard Worker 
1030*e5436536SAndroid Build Coastguard Worker   /* check ssc for parse errors */
1031*e5436536SAndroid Build Coastguard Worker   if (sscParseCheck(pSsc) != MPS_OK) {
1032*e5436536SAndroid Build Coastguard Worker     err = MPS_PARSE_ERROR;
1033*e5436536SAndroid Build Coastguard Worker   }
1034*e5436536SAndroid Build Coastguard Worker 
1035*e5436536SAndroid Build Coastguard Worker   /* core fs and mps fs must match */
1036*e5436536SAndroid Build Coastguard Worker   if (pSsc->samplingFreq != sampleRate) {
1037*e5436536SAndroid Build Coastguard Worker     err = MPS_PARSE_ERROR /* MPEGSDEC_SSC_PARSE_ERROR */;
1038*e5436536SAndroid Build Coastguard Worker   }
1039*e5436536SAndroid Build Coastguard Worker 
1040*e5436536SAndroid Build Coastguard Worker   qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq);
1041*e5436536SAndroid Build Coastguard Worker 
1042*e5436536SAndroid Build Coastguard Worker   if (checkTimeSlots(frameLength, qmfBands, pSsc->nTimeSlots) != MPS_OK) {
1043*e5436536SAndroid Build Coastguard Worker     err = MPS_PARSE_ERROR;
1044*e5436536SAndroid Build Coastguard Worker   }
1045*e5436536SAndroid Build Coastguard Worker 
1046*e5436536SAndroid Build Coastguard Worker   return err;
1047*e5436536SAndroid Build Coastguard Worker }
1048*e5436536SAndroid Build Coastguard Worker 
1049*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR
mpegSurroundDecoder_ConfigureQmfDomain(CMpegSurroundDecoder * pMpegSurroundDecoder,SAC_INPUT_CONFIG sac_dec_interface,UINT coreSamplingRate,AUDIO_OBJECT_TYPE coreCodec)1050*e5436536SAndroid Build Coastguard Worker mpegSurroundDecoder_ConfigureQmfDomain(
1051*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder,
1052*e5436536SAndroid Build Coastguard Worker     SAC_INPUT_CONFIG sac_dec_interface, UINT coreSamplingRate,
1053*e5436536SAndroid Build Coastguard Worker     AUDIO_OBJECT_TYPE coreCodec) {
1054*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
1055*e5436536SAndroid Build Coastguard Worker   FDK_QMF_DOMAIN_GC *pGC = NULL;
1056*e5436536SAndroid Build Coastguard Worker 
1057*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder == NULL) {
1058*e5436536SAndroid Build Coastguard Worker     return MPS_INVALID_HANDLE;
1059*e5436536SAndroid Build Coastguard Worker   }
1060*e5436536SAndroid Build Coastguard Worker 
1061*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec);
1062*e5436536SAndroid Build Coastguard Worker 
1063*e5436536SAndroid Build Coastguard Worker   pGC = &pMpegSurroundDecoder->pQmfDomain->globalConf;
1064*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg) {
1065*e5436536SAndroid Build Coastguard Worker     SPATIAL_SPECIFIC_CONFIG *pSSC =
1066*e5436536SAndroid Build Coastguard Worker         &pMpegSurroundDecoder->spatialSpecificConfigBackup;
1067*e5436536SAndroid Build Coastguard Worker     if (sac_dec_interface == SAC_INTERFACE_TIME) {
1068*e5436536SAndroid Build Coastguard Worker       /* For SAC_INTERFACE_QMF these parameters are set by SBR. */
1069*e5436536SAndroid Build Coastguard Worker       pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands(
1070*e5436536SAndroid Build Coastguard Worker           pSSC, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for
1071*e5436536SAndroid Build Coastguard Worker                                       SAC_INTERFACE_TIME */
1072*e5436536SAndroid Build Coastguard Worker       pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested;
1073*e5436536SAndroid Build Coastguard Worker       pGC->nInputChannels_requested =
1074*e5436536SAndroid Build Coastguard Worker           fMax((UINT)pSSC->nInputChannels, (UINT)pGC->nInputChannels_requested);
1075*e5436536SAndroid Build Coastguard Worker     }
1076*e5436536SAndroid Build Coastguard Worker     pGC->nOutputChannels_requested =
1077*e5436536SAndroid Build Coastguard Worker         fMax((UINT)pSSC->nOutputChannels, (UINT)pGC->nOutputChannels_requested);
1078*e5436536SAndroid Build Coastguard Worker   } else {
1079*e5436536SAndroid Build Coastguard Worker     if (sac_dec_interface == SAC_INTERFACE_TIME) {
1080*e5436536SAndroid Build Coastguard Worker       /* For SAC_INTERFACE_QMF these parameters are set by SBR. */
1081*e5436536SAndroid Build Coastguard Worker       pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands(
1082*e5436536SAndroid Build Coastguard Worker           NULL, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for
1083*e5436536SAndroid Build Coastguard Worker                                       SAC_INTERFACE_TIME */
1084*e5436536SAndroid Build Coastguard Worker       pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested;
1085*e5436536SAndroid Build Coastguard Worker       pGC->nInputChannels_requested =
1086*e5436536SAndroid Build Coastguard Worker           pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels;
1087*e5436536SAndroid Build Coastguard Worker     }
1088*e5436536SAndroid Build Coastguard Worker     pGC->nOutputChannels_requested =
1089*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->pSpatialDec->createParams.maxNumOutputChannels;
1090*e5436536SAndroid Build Coastguard Worker   }
1091*e5436536SAndroid Build Coastguard Worker   pGC->nQmfProcBands_requested = 64;
1092*e5436536SAndroid Build Coastguard Worker   pGC->nQmfProcChannels_requested =
1093*e5436536SAndroid Build Coastguard Worker       fMin((INT)pGC->nInputChannels_requested,
1094*e5436536SAndroid Build Coastguard Worker            pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels);
1095*e5436536SAndroid Build Coastguard Worker 
1096*e5436536SAndroid Build Coastguard Worker   if (coreCodec == AOT_ER_AAC_ELD) {
1097*e5436536SAndroid Build Coastguard Worker     pGC->flags_requested |= QMF_FLAG_MPSLDFB;
1098*e5436536SAndroid Build Coastguard Worker     pGC->flags_requested &= ~QMF_FLAG_CLDFB;
1099*e5436536SAndroid Build Coastguard Worker   }
1100*e5436536SAndroid Build Coastguard Worker 
1101*e5436536SAndroid Build Coastguard Worker   return err;
1102*e5436536SAndroid Build Coastguard Worker }
1103*e5436536SAndroid Build Coastguard Worker 
1104*e5436536SAndroid Build Coastguard Worker /**
1105*e5436536SAndroid Build Coastguard Worker  * \brief  Check out-of-band config
1106*e5436536SAndroid Build Coastguard Worker  *
1107*e5436536SAndroid Build Coastguard Worker  * \param pSsc         spatial specific config handle.
1108*e5436536SAndroid Build Coastguard Worker  * \param coreCodec    core codec.
1109*e5436536SAndroid Build Coastguard Worker  * \param sampleRate   sampling frequency.
1110*e5436536SAndroid Build Coastguard Worker  *
1111*e5436536SAndroid Build Coastguard Worker  * \return  errorStatus
1112*e5436536SAndroid Build Coastguard Worker  */
1113*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR
sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG * pSsc,const INT coreCodec,const INT sampleRate,const INT frameSize)1114*e5436536SAndroid Build Coastguard Worker sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc, const INT coreCodec,
1115*e5436536SAndroid Build Coastguard Worker                   const INT sampleRate, const INT frameSize) {
1116*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pSsc != NULL);
1117*e5436536SAndroid Build Coastguard Worker   int qmfBands = 0;
1118*e5436536SAndroid Build Coastguard Worker 
1119*e5436536SAndroid Build Coastguard Worker   /* check ssc for parse errors */
1120*e5436536SAndroid Build Coastguard Worker   if (sscParseCheck(pSsc) != MPS_OK) {
1121*e5436536SAndroid Build Coastguard Worker     return MPS_PARSE_ERROR;
1122*e5436536SAndroid Build Coastguard Worker   }
1123*e5436536SAndroid Build Coastguard Worker 
1124*e5436536SAndroid Build Coastguard Worker   switch (coreCodec) {
1125*e5436536SAndroid Build Coastguard Worker     case AOT_USAC:
1126*e5436536SAndroid Build Coastguard Worker     case AOT_DRM_USAC:
1127*e5436536SAndroid Build Coastguard Worker       /* ISO/IEC 23003-1:2007(E), Chapter 6.3.3, Support for lower and higher
1128*e5436536SAndroid Build Coastguard Worker        * sampling frequencies */
1129*e5436536SAndroid Build Coastguard Worker       if (pSsc->samplingFreq >= 55426) {
1130*e5436536SAndroid Build Coastguard Worker         return MPS_PARSE_ERROR;
1131*e5436536SAndroid Build Coastguard Worker       }
1132*e5436536SAndroid Build Coastguard Worker       break;
1133*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_LD:
1134*e5436536SAndroid Build Coastguard Worker     case AOT_ER_AAC_ELD:
1135*e5436536SAndroid Build Coastguard Worker       /* core fs and mps fs must match */
1136*e5436536SAndroid Build Coastguard Worker       if (pSsc->samplingFreq != sampleRate) {
1137*e5436536SAndroid Build Coastguard Worker         return MPS_PARSE_ERROR;
1138*e5436536SAndroid Build Coastguard Worker       }
1139*e5436536SAndroid Build Coastguard Worker 
1140*e5436536SAndroid Build Coastguard Worker       /* ISO/IEC 14496-3:2009 FDAM 3: Chapter 1.5.2.3, Levels for the Low Delay
1141*e5436536SAndroid Build Coastguard Worker        * AAC v2 profile */
1142*e5436536SAndroid Build Coastguard Worker       if (pSsc->samplingFreq > 48000) {
1143*e5436536SAndroid Build Coastguard Worker         return MPS_PARSE_ERROR;
1144*e5436536SAndroid Build Coastguard Worker       }
1145*e5436536SAndroid Build Coastguard Worker 
1146*e5436536SAndroid Build Coastguard Worker       qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq);
1147*e5436536SAndroid Build Coastguard Worker       switch (frameSize) {
1148*e5436536SAndroid Build Coastguard Worker         case 480:
1149*e5436536SAndroid Build Coastguard Worker           if (!((qmfBands == 32) && (pSsc->nTimeSlots == 15))) {
1150*e5436536SAndroid Build Coastguard Worker             return MPS_PARSE_ERROR;
1151*e5436536SAndroid Build Coastguard Worker           }
1152*e5436536SAndroid Build Coastguard Worker           break;
1153*e5436536SAndroid Build Coastguard Worker         case 960:
1154*e5436536SAndroid Build Coastguard Worker           if (!((qmfBands == 64) && (pSsc->nTimeSlots == 15))) {
1155*e5436536SAndroid Build Coastguard Worker             return MPS_PARSE_ERROR;
1156*e5436536SAndroid Build Coastguard Worker           }
1157*e5436536SAndroid Build Coastguard Worker           break;
1158*e5436536SAndroid Build Coastguard Worker         case 512:
1159*e5436536SAndroid Build Coastguard Worker           if (!(((qmfBands == 32) && (pSsc->nTimeSlots == 16)) ||
1160*e5436536SAndroid Build Coastguard Worker                 ((qmfBands == 64) && (pSsc->nTimeSlots == 8)))) {
1161*e5436536SAndroid Build Coastguard Worker             return MPS_PARSE_ERROR;
1162*e5436536SAndroid Build Coastguard Worker           }
1163*e5436536SAndroid Build Coastguard Worker           break;
1164*e5436536SAndroid Build Coastguard Worker         case 1024:
1165*e5436536SAndroid Build Coastguard Worker           if (!((qmfBands == 64) && (pSsc->nTimeSlots == 16))) {
1166*e5436536SAndroid Build Coastguard Worker             return MPS_PARSE_ERROR;
1167*e5436536SAndroid Build Coastguard Worker           }
1168*e5436536SAndroid Build Coastguard Worker           break;
1169*e5436536SAndroid Build Coastguard Worker         default:
1170*e5436536SAndroid Build Coastguard Worker           return MPS_PARSE_ERROR;
1171*e5436536SAndroid Build Coastguard Worker       }
1172*e5436536SAndroid Build Coastguard Worker       break;
1173*e5436536SAndroid Build Coastguard Worker     default:
1174*e5436536SAndroid Build Coastguard Worker       return MPS_PARSE_ERROR;
1175*e5436536SAndroid Build Coastguard Worker       break;
1176*e5436536SAndroid Build Coastguard Worker   }
1177*e5436536SAndroid Build Coastguard Worker 
1178*e5436536SAndroid Build Coastguard Worker   return MPS_OK;
1179*e5436536SAndroid Build Coastguard Worker }
1180*e5436536SAndroid Build Coastguard Worker 
1181*e5436536SAndroid Build Coastguard Worker /**
1182*e5436536SAndroid Build Coastguard Worker  * \brief Decode MPEG Surround frame.
1183*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_ParseNoHeader(CMpegSurroundDecoder * pMpegSurroundDecoder,HANDLE_FDK_BITSTREAM hBs,int * pMpsDataBits,int fGlobalIndependencyFlag)1184*e5436536SAndroid Build Coastguard Worker int mpegSurroundDecoder_ParseNoHeader(
1185*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
1186*e5436536SAndroid Build Coastguard Worker     int *pMpsDataBits, int fGlobalIndependencyFlag) {
1187*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
1188*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG *sscParse;
1189*e5436536SAndroid Build Coastguard Worker   int bitsAvail, numSacBits;
1190*e5436536SAndroid Build Coastguard Worker 
1191*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder == NULL || hBs == NULL) {
1192*e5436536SAndroid Build Coastguard Worker     return MPS_INVALID_HANDLE;
1193*e5436536SAndroid Build Coastguard Worker   }
1194*e5436536SAndroid Build Coastguard Worker 
1195*e5436536SAndroid Build Coastguard Worker   sscParse = &pMpegSurroundDecoder
1196*e5436536SAndroid Build Coastguard Worker                   ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse];
1197*e5436536SAndroid Build Coastguard Worker 
1198*e5436536SAndroid Build Coastguard Worker   bitsAvail = FDKgetValidBits(hBs);
1199*e5436536SAndroid Build Coastguard Worker 
1200*e5436536SAndroid Build Coastguard Worker   /* First spatial specific config is parsed into spatialSpecificConfigBackup,
1201*e5436536SAndroid Build Coastguard Worker    * second spatialSpecificConfigBackup is copied into
1202*e5436536SAndroid Build Coastguard Worker    * spatialSpecificConfig[bsFrameDecode] */
1203*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse]) {
1204*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(sscParse, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
1205*e5436536SAndroid Build Coastguard Worker               sizeof(SPATIAL_SPECIFIC_CONFIG));
1206*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameParse] =
1207*e5436536SAndroid Build Coastguard Worker         MPEGS_SYNC_FOUND;
1208*e5436536SAndroid Build Coastguard Worker   }
1209*e5436536SAndroid Build Coastguard Worker 
1210*e5436536SAndroid Build Coastguard Worker   if (bitsAvail <= 0) {
1211*e5436536SAndroid Build Coastguard Worker     err = MPS_PARSE_ERROR;
1212*e5436536SAndroid Build Coastguard Worker   } else {
1213*e5436536SAndroid Build Coastguard Worker     err = SpatialDecParseFrameData(
1214*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->pSpatialDec,
1215*e5436536SAndroid Build Coastguard Worker         &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse],
1216*e5436536SAndroid Build Coastguard Worker         hBs, sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType,
1217*e5436536SAndroid Build Coastguard Worker         fGlobalIndependencyFlag);
1218*e5436536SAndroid Build Coastguard Worker     if (err == MPS_OK) {
1219*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]
1220*e5436536SAndroid Build Coastguard Worker           .newBsData = 1;
1221*e5436536SAndroid Build Coastguard Worker     }
1222*e5436536SAndroid Build Coastguard Worker   }
1223*e5436536SAndroid Build Coastguard Worker 
1224*e5436536SAndroid Build Coastguard Worker   numSacBits = bitsAvail - (INT)FDKgetValidBits(hBs);
1225*e5436536SAndroid Build Coastguard Worker 
1226*e5436536SAndroid Build Coastguard Worker   if (numSacBits > bitsAvail) {
1227*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]
1228*e5436536SAndroid Build Coastguard Worker         .newBsData = 0;
1229*e5436536SAndroid Build Coastguard Worker     err = MPS_PARSE_ERROR;
1230*e5436536SAndroid Build Coastguard Worker   }
1231*e5436536SAndroid Build Coastguard Worker 
1232*e5436536SAndroid Build Coastguard Worker   *pMpsDataBits -= numSacBits;
1233*e5436536SAndroid Build Coastguard Worker 
1234*e5436536SAndroid Build Coastguard Worker   return err;
1235*e5436536SAndroid Build Coastguard Worker }
1236*e5436536SAndroid Build Coastguard Worker 
1237*e5436536SAndroid Build Coastguard Worker /**
1238*e5436536SAndroid Build Coastguard Worker  * \brief Check, if ancType is valid.
1239*e5436536SAndroid Build Coastguard Worker  **/
isValidAncType(CMpegSurroundDecoder * pMpegSurroundDecoder,int ancType)1240*e5436536SAndroid Build Coastguard Worker static int isValidAncType(CMpegSurroundDecoder *pMpegSurroundDecoder,
1241*e5436536SAndroid Build Coastguard Worker                           int ancType) {
1242*e5436536SAndroid Build Coastguard Worker   int ret = 1;
1243*e5436536SAndroid Build Coastguard Worker 
1244*e5436536SAndroid Build Coastguard Worker   if ((ancType != MPEGS_ANCTYPE_HEADER_AND_FRAME) &&
1245*e5436536SAndroid Build Coastguard Worker       (ancType != MPEGS_ANCTYPE_FRAME)) {
1246*e5436536SAndroid Build Coastguard Worker     ret = 0;
1247*e5436536SAndroid Build Coastguard Worker   }
1248*e5436536SAndroid Build Coastguard Worker 
1249*e5436536SAndroid Build Coastguard Worker   if (ret == 0) {
1250*e5436536SAndroid Build Coastguard Worker     updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
1251*e5436536SAndroid Build Coastguard Worker                                     MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
1252*e5436536SAndroid Build Coastguard Worker                                     MPEGS_STOP);
1253*e5436536SAndroid Build Coastguard Worker   }
1254*e5436536SAndroid Build Coastguard Worker 
1255*e5436536SAndroid Build Coastguard Worker   return (ret);
1256*e5436536SAndroid Build Coastguard Worker }
1257*e5436536SAndroid Build Coastguard Worker 
1258*e5436536SAndroid Build Coastguard Worker /**
1259*e5436536SAndroid Build Coastguard Worker  * \brief Check, if ancStartStop is valid.
1260*e5436536SAndroid Build Coastguard Worker  **/
isValidAncStartStop(CMpegSurroundDecoder * pMpegSurroundDecoder,int ancStartStop)1261*e5436536SAndroid Build Coastguard Worker static int isValidAncStartStop(CMpegSurroundDecoder *pMpegSurroundDecoder,
1262*e5436536SAndroid Build Coastguard Worker                                int ancStartStop) {
1263*e5436536SAndroid Build Coastguard Worker   int ret = 1;
1264*e5436536SAndroid Build Coastguard Worker 
1265*e5436536SAndroid Build Coastguard Worker   switch (ancStartStop) {
1266*e5436536SAndroid Build Coastguard Worker     case MPEGS_START:
1267*e5436536SAndroid Build Coastguard Worker       /* Sequence start - start and continue - start not allowed */
1268*e5436536SAndroid Build Coastguard Worker       if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START) ||
1269*e5436536SAndroid Build Coastguard Worker           (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_CONTINUE)) {
1270*e5436536SAndroid Build Coastguard Worker         ret = 0;
1271*e5436536SAndroid Build Coastguard Worker       }
1272*e5436536SAndroid Build Coastguard Worker       break;
1273*e5436536SAndroid Build Coastguard Worker 
1274*e5436536SAndroid Build Coastguard Worker     case MPEGS_STOP:
1275*e5436536SAndroid Build Coastguard Worker       /* MPS payload of the previous frame must be valid if current type is stop
1276*e5436536SAndroid Build Coastguard Worker          Sequence startstop - stop and stop - stop not allowed
1277*e5436536SAndroid Build Coastguard Worker          Sequence startstop - continue and stop - continue are allowed */
1278*e5436536SAndroid Build Coastguard Worker       if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_STOP) ||
1279*e5436536SAndroid Build Coastguard Worker           (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START_STOP)) {
1280*e5436536SAndroid Build Coastguard Worker         ret = 0;
1281*e5436536SAndroid Build Coastguard Worker       }
1282*e5436536SAndroid Build Coastguard Worker       break;
1283*e5436536SAndroid Build Coastguard Worker 
1284*e5436536SAndroid Build Coastguard Worker     case MPEGS_CONTINUE:
1285*e5436536SAndroid Build Coastguard Worker     case MPEGS_START_STOP:
1286*e5436536SAndroid Build Coastguard Worker       /* No error detection possible for this states */
1287*e5436536SAndroid Build Coastguard Worker       break;
1288*e5436536SAndroid Build Coastguard Worker   }
1289*e5436536SAndroid Build Coastguard Worker 
1290*e5436536SAndroid Build Coastguard Worker   if (ret == 0) {
1291*e5436536SAndroid Build Coastguard Worker     updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
1292*e5436536SAndroid Build Coastguard Worker                                     MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
1293*e5436536SAndroid Build Coastguard Worker                                     MPEGS_STOP);
1294*e5436536SAndroid Build Coastguard Worker   } else {
1295*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->ancStartStopPrev = (MPEGS_ANCSTARTSTOP)ancStartStop;
1296*e5436536SAndroid Build Coastguard Worker   }
1297*e5436536SAndroid Build Coastguard Worker 
1298*e5436536SAndroid Build Coastguard Worker   return (ret);
1299*e5436536SAndroid Build Coastguard Worker }
1300*e5436536SAndroid Build Coastguard Worker 
mpegSurroundDecoder_Parse(CMpegSurroundDecoder * pMpegSurroundDecoder,HANDLE_FDK_BITSTREAM hBs,int * pMpsDataBits,AUDIO_OBJECT_TYPE coreCodec,int sampleRate,int frameSize,int fGlobalIndependencyFlag)1301*e5436536SAndroid Build Coastguard Worker int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder,
1302*e5436536SAndroid Build Coastguard Worker                               HANDLE_FDK_BITSTREAM hBs, int *pMpsDataBits,
1303*e5436536SAndroid Build Coastguard Worker                               AUDIO_OBJECT_TYPE coreCodec, int sampleRate,
1304*e5436536SAndroid Build Coastguard Worker                               int frameSize, int fGlobalIndependencyFlag) {
1305*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
1306*e5436536SAndroid Build Coastguard Worker   SPATIAL_SPECIFIC_CONFIG *sscParse;
1307*e5436536SAndroid Build Coastguard Worker   SPATIAL_BS_FRAME *bsFrame;
1308*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hMpsBsData = NULL;
1309*e5436536SAndroid Build Coastguard Worker   FDK_BITSTREAM mpsBsData;
1310*e5436536SAndroid Build Coastguard Worker   int mpsDataBits = *pMpsDataBits;
1311*e5436536SAndroid Build Coastguard Worker   int mpsBsBits;
1312*e5436536SAndroid Build Coastguard Worker   MPEGS_ANCTYPE ancType;
1313*e5436536SAndroid Build Coastguard Worker   MPEGS_ANCSTARTSTOP ancStartStop;
1314*e5436536SAndroid Build Coastguard Worker 
1315*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder == NULL) {
1316*e5436536SAndroid Build Coastguard Worker     return MPS_INVALID_HANDLE;
1317*e5436536SAndroid Build Coastguard Worker   }
1318*e5436536SAndroid Build Coastguard Worker 
1319*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec);
1320*e5436536SAndroid Build Coastguard Worker 
1321*e5436536SAndroid Build Coastguard Worker   mpsBsBits = (INT)FDKgetValidBits(hBs);
1322*e5436536SAndroid Build Coastguard Worker 
1323*e5436536SAndroid Build Coastguard Worker   sscParse = &pMpegSurroundDecoder
1324*e5436536SAndroid Build Coastguard Worker                   ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse];
1325*e5436536SAndroid Build Coastguard Worker   bsFrame = &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse];
1326*e5436536SAndroid Build Coastguard Worker 
1327*e5436536SAndroid Build Coastguard Worker   /*
1328*e5436536SAndroid Build Coastguard Worker      Find operation mode of mpeg surround decoder:
1329*e5436536SAndroid Build Coastguard Worker      - MPEGS_OPMODE_EMM:            Mode: Enhanced Matrix Mode (Blind)
1330*e5436536SAndroid Build Coastguard Worker      - MPEGS_OPMODE_MPS_PAYLOAD:    Mode: Normal, Stereo or Binaural
1331*e5436536SAndroid Build Coastguard Worker      - MPEGS_OPMODE_NO_MPS_PAYLOAD: Mode: No MpegSurround Payload
1332*e5436536SAndroid Build Coastguard Worker   */
1333*e5436536SAndroid Build Coastguard Worker   {
1334*e5436536SAndroid Build Coastguard Worker     /* Parse ancType and ancStartStop */
1335*e5436536SAndroid Build Coastguard Worker     ancType = (MPEGS_ANCTYPE)FDKreadBits(hBs, 2);
1336*e5436536SAndroid Build Coastguard Worker     ancStartStop = (MPEGS_ANCSTARTSTOP)FDKreadBits(hBs, 2);
1337*e5436536SAndroid Build Coastguard Worker     mpsDataBits -= 4;
1338*e5436536SAndroid Build Coastguard Worker 
1339*e5436536SAndroid Build Coastguard Worker     /* Set valid anc type flag, if ancType signals a payload with either header
1340*e5436536SAndroid Build Coastguard Worker      * and frame or frame */
1341*e5436536SAndroid Build Coastguard Worker     if (isValidAncType(pMpegSurroundDecoder, ancType)) {
1342*e5436536SAndroid Build Coastguard Worker       /* Set valid anc startstop flag, if transmitted sequence is not illegal */
1343*e5436536SAndroid Build Coastguard Worker       if (isValidAncStartStop(pMpegSurroundDecoder, ancStartStop)) {
1344*e5436536SAndroid Build Coastguard Worker         switch (ancStartStop) {
1345*e5436536SAndroid Build Coastguard Worker           case MPEGS_START:
1346*e5436536SAndroid Build Coastguard Worker             /* Assuming that core coder frame size (AAC) is smaller than MPS
1347*e5436536SAndroid Build Coastguard Worker                coder frame size. Save audio data for next frame. */
1348*e5436536SAndroid Build Coastguard Worker             if (mpsDataBits > MPS_DATA_BUFFER_SIZE * 8) {
1349*e5436536SAndroid Build Coastguard Worker               err = MPS_NOTOK;
1350*e5436536SAndroid Build Coastguard Worker               goto bail;
1351*e5436536SAndroid Build Coastguard Worker             }
1352*e5436536SAndroid Build Coastguard Worker             for (int i = 0; i < mpsDataBits / 8; i++) {
1353*e5436536SAndroid Build Coastguard Worker               pMpegSurroundDecoder->mpsData[i] = FDKreadBits(hBs, 8);
1354*e5436536SAndroid Build Coastguard Worker             }
1355*e5436536SAndroid Build Coastguard Worker             pMpegSurroundDecoder->mpsDataBits = mpsDataBits;
1356*e5436536SAndroid Build Coastguard Worker             break;
1357*e5436536SAndroid Build Coastguard Worker 
1358*e5436536SAndroid Build Coastguard Worker           case MPEGS_CONTINUE:
1359*e5436536SAndroid Build Coastguard Worker           case MPEGS_STOP:
1360*e5436536SAndroid Build Coastguard Worker             /* Assuming that core coder frame size (AAC) is smaller than MPS
1361*e5436536SAndroid Build Coastguard Worker                coder frame size. Save audio data for next frame. */
1362*e5436536SAndroid Build Coastguard Worker             if ((pMpegSurroundDecoder->mpsDataBits + mpsDataBits) >
1363*e5436536SAndroid Build Coastguard Worker                 MPS_DATA_BUFFER_SIZE * 8) {
1364*e5436536SAndroid Build Coastguard Worker               err = MPS_NOTOK;
1365*e5436536SAndroid Build Coastguard Worker               goto bail;
1366*e5436536SAndroid Build Coastguard Worker             }
1367*e5436536SAndroid Build Coastguard Worker             for (int i = 0; i < mpsDataBits / 8; i++) {
1368*e5436536SAndroid Build Coastguard Worker               pMpegSurroundDecoder
1369*e5436536SAndroid Build Coastguard Worker                   ->mpsData[(pMpegSurroundDecoder->mpsDataBits / 8) + i] =
1370*e5436536SAndroid Build Coastguard Worker                   FDKreadBits(hBs, 8);
1371*e5436536SAndroid Build Coastguard Worker             }
1372*e5436536SAndroid Build Coastguard Worker             pMpegSurroundDecoder->mpsDataBits += mpsDataBits;
1373*e5436536SAndroid Build Coastguard Worker             FDKinitBitStream(&mpsBsData, pMpegSurroundDecoder->mpsData,
1374*e5436536SAndroid Build Coastguard Worker                              MAX_BUFSIZE_BYTES,
1375*e5436536SAndroid Build Coastguard Worker                              pMpegSurroundDecoder->mpsDataBits, BS_READER);
1376*e5436536SAndroid Build Coastguard Worker             hMpsBsData = &mpsBsData;
1377*e5436536SAndroid Build Coastguard Worker             break;
1378*e5436536SAndroid Build Coastguard Worker 
1379*e5436536SAndroid Build Coastguard Worker           case MPEGS_START_STOP:
1380*e5436536SAndroid Build Coastguard Worker             pMpegSurroundDecoder->mpsDataBits = mpsDataBits;
1381*e5436536SAndroid Build Coastguard Worker             hMpsBsData = hBs;
1382*e5436536SAndroid Build Coastguard Worker             break;
1383*e5436536SAndroid Build Coastguard Worker 
1384*e5436536SAndroid Build Coastguard Worker           default:
1385*e5436536SAndroid Build Coastguard Worker             FDK_ASSERT(0);
1386*e5436536SAndroid Build Coastguard Worker         }
1387*e5436536SAndroid Build Coastguard Worker 
1388*e5436536SAndroid Build Coastguard Worker         if ((ancStartStop == MPEGS_STOP) ||
1389*e5436536SAndroid Build Coastguard Worker             (ancStartStop == MPEGS_START_STOP)) {
1390*e5436536SAndroid Build Coastguard Worker           switch (ancType) {
1391*e5436536SAndroid Build Coastguard Worker             case MPEGS_ANCTYPE_HEADER_AND_FRAME: {
1392*e5436536SAndroid Build Coastguard Worker               int parseResult, bitsRead;
1393*e5436536SAndroid Build Coastguard Worker               SPATIAL_SPECIFIC_CONFIG spatialSpecificConfigTmp =
1394*e5436536SAndroid Build Coastguard Worker                   pMpegSurroundDecoder->spatialSpecificConfigBackup;
1395*e5436536SAndroid Build Coastguard Worker 
1396*e5436536SAndroid Build Coastguard Worker               /* Parse spatial specific config */
1397*e5436536SAndroid Build Coastguard Worker               bitsRead = (INT)FDKgetValidBits(hMpsBsData);
1398*e5436536SAndroid Build Coastguard Worker 
1399*e5436536SAndroid Build Coastguard Worker               err = SpatialDecParseSpecificConfigHeader(
1400*e5436536SAndroid Build Coastguard Worker                   hMpsBsData,
1401*e5436536SAndroid Build Coastguard Worker                   &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec,
1402*e5436536SAndroid Build Coastguard Worker                   pMpegSurroundDecoder->upmixType);
1403*e5436536SAndroid Build Coastguard Worker 
1404*e5436536SAndroid Build Coastguard Worker               bitsRead = (bitsRead - (INT)FDKgetValidBits(hMpsBsData));
1405*e5436536SAndroid Build Coastguard Worker               parseResult = ((err == MPS_OK) ? bitsRead : -bitsRead);
1406*e5436536SAndroid Build Coastguard Worker 
1407*e5436536SAndroid Build Coastguard Worker               if (parseResult < 0) {
1408*e5436536SAndroid Build Coastguard Worker                 parseResult = -parseResult;
1409*e5436536SAndroid Build Coastguard Worker                 err = MPS_PARSE_ERROR;
1410*e5436536SAndroid Build Coastguard Worker               } else if (err == MPS_OK) {
1411*e5436536SAndroid Build Coastguard Worker                 /* Check SSC for consistency (e.g. bit errors could cause
1412*e5436536SAndroid Build Coastguard Worker                  * trouble) */
1413*e5436536SAndroid Build Coastguard Worker                 err = sscCheckInBand(
1414*e5436536SAndroid Build Coastguard Worker                     &pMpegSurroundDecoder->spatialSpecificConfigBackup,
1415*e5436536SAndroid Build Coastguard Worker                     frameSize, sampleRate);
1416*e5436536SAndroid Build Coastguard Worker               }
1417*e5436536SAndroid Build Coastguard Worker               if (err != MPS_OK) {
1418*e5436536SAndroid Build Coastguard Worker                 pMpegSurroundDecoder->spatialSpecificConfigBackup =
1419*e5436536SAndroid Build Coastguard Worker                     spatialSpecificConfigTmp;
1420*e5436536SAndroid Build Coastguard Worker                 break;
1421*e5436536SAndroid Build Coastguard Worker               }
1422*e5436536SAndroid Build Coastguard Worker 
1423*e5436536SAndroid Build Coastguard Worker               pMpegSurroundDecoder->mpsDataBits -= parseResult;
1424*e5436536SAndroid Build Coastguard Worker 
1425*e5436536SAndroid Build Coastguard Worker               /* Initiate re-initialization, if header has changed */
1426*e5436536SAndroid Build Coastguard Worker               if (FDK_SpatialDecCompareSpatialSpecificConfigHeader(
1427*e5436536SAndroid Build Coastguard Worker                       &pMpegSurroundDecoder->spatialSpecificConfigBackup,
1428*e5436536SAndroid Build Coastguard Worker                       sscParse) == MPS_UNEQUAL_SSC) {
1429*e5436536SAndroid Build Coastguard Worker                 pMpegSurroundDecoder
1430*e5436536SAndroid Build Coastguard Worker                     ->initFlags[pMpegSurroundDecoder->bsFrameParse] |=
1431*e5436536SAndroid Build Coastguard Worker                     MPEGS_INIT_CHANGE_HEADER;
1432*e5436536SAndroid Build Coastguard Worker                 SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec);
1433*e5436536SAndroid Build Coastguard Worker                 /* We found a valid in-band configuration. Therefore any
1434*e5436536SAndroid Build Coastguard Worker                  * previous config is invalid now. */
1435*e5436536SAndroid Build Coastguard Worker                 pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 0;
1436*e5436536SAndroid Build Coastguard Worker               }
1437*e5436536SAndroid Build Coastguard Worker             }
1438*e5436536SAndroid Build Coastguard Worker               FDK_FALLTHROUGH;
1439*e5436536SAndroid Build Coastguard Worker             case MPEGS_ANCTYPE_FRAME:
1440*e5436536SAndroid Build Coastguard Worker 
1441*e5436536SAndroid Build Coastguard Worker               if (pMpegSurroundDecoder
1442*e5436536SAndroid Build Coastguard Worker                       ->initFlags[pMpegSurroundDecoder->bsFrameParse] &
1443*e5436536SAndroid Build Coastguard Worker                   MPEGS_INIT_ERROR_PAYLOAD) {
1444*e5436536SAndroid Build Coastguard Worker                 err = MPS_PARSE_ERROR;
1445*e5436536SAndroid Build Coastguard Worker                 break;
1446*e5436536SAndroid Build Coastguard Worker               }
1447*e5436536SAndroid Build Coastguard Worker 
1448*e5436536SAndroid Build Coastguard Worker               /* First spatial specific config is parsed into
1449*e5436536SAndroid Build Coastguard Worker                * spatialSpecificConfigBackup, second spatialSpecificConfigBackup
1450*e5436536SAndroid Build Coastguard Worker                * is copied into spatialSpecificConfig[bsFrameDecode] */
1451*e5436536SAndroid Build Coastguard Worker               if (pMpegSurroundDecoder
1452*e5436536SAndroid Build Coastguard Worker                       ->initFlags[pMpegSurroundDecoder->bsFrameParse]) {
1453*e5436536SAndroid Build Coastguard Worker                 FDKmemcpy(sscParse,
1454*e5436536SAndroid Build Coastguard Worker                           &pMpegSurroundDecoder->spatialSpecificConfigBackup,
1455*e5436536SAndroid Build Coastguard Worker                           sizeof(SPATIAL_SPECIFIC_CONFIG));
1456*e5436536SAndroid Build Coastguard Worker                 pMpegSurroundDecoder
1457*e5436536SAndroid Build Coastguard Worker                     ->fOnSync[pMpegSurroundDecoder->bsFrameParse] =
1458*e5436536SAndroid Build Coastguard Worker                     MPEGS_SYNC_FOUND;
1459*e5436536SAndroid Build Coastguard Worker               }
1460*e5436536SAndroid Build Coastguard Worker 
1461*e5436536SAndroid Build Coastguard Worker               if (pMpegSurroundDecoder
1462*e5436536SAndroid Build Coastguard Worker                       ->fOnSync[pMpegSurroundDecoder->bsFrameParse] >=
1463*e5436536SAndroid Build Coastguard Worker                   MPEGS_SYNC_FOUND) {
1464*e5436536SAndroid Build Coastguard Worker                 int nbits = 0, bitsAvail;
1465*e5436536SAndroid Build Coastguard Worker 
1466*e5436536SAndroid Build Coastguard Worker                 if (err != MPS_OK) {
1467*e5436536SAndroid Build Coastguard Worker                   break;
1468*e5436536SAndroid Build Coastguard Worker                 }
1469*e5436536SAndroid Build Coastguard Worker 
1470*e5436536SAndroid Build Coastguard Worker                 bitsAvail = FDKgetValidBits(hMpsBsData);
1471*e5436536SAndroid Build Coastguard Worker 
1472*e5436536SAndroid Build Coastguard Worker                 if (bitsAvail <= 0) {
1473*e5436536SAndroid Build Coastguard Worker                   err = MPS_PARSE_ERROR;
1474*e5436536SAndroid Build Coastguard Worker                 } else {
1475*e5436536SAndroid Build Coastguard Worker                   err = SpatialDecParseFrameData(
1476*e5436536SAndroid Build Coastguard Worker                       pMpegSurroundDecoder->pSpatialDec, bsFrame, hMpsBsData,
1477*e5436536SAndroid Build Coastguard Worker                       sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType,
1478*e5436536SAndroid Build Coastguard Worker                       fGlobalIndependencyFlag);
1479*e5436536SAndroid Build Coastguard Worker                   if (err == MPS_OK) {
1480*e5436536SAndroid Build Coastguard Worker                     bsFrame->newBsData = 1;
1481*e5436536SAndroid Build Coastguard Worker                   }
1482*e5436536SAndroid Build Coastguard Worker                 }
1483*e5436536SAndroid Build Coastguard Worker 
1484*e5436536SAndroid Build Coastguard Worker                 nbits = bitsAvail - (INT)FDKgetValidBits(hMpsBsData);
1485*e5436536SAndroid Build Coastguard Worker 
1486*e5436536SAndroid Build Coastguard Worker                 if ((nbits > bitsAvail) ||
1487*e5436536SAndroid Build Coastguard Worker                     (nbits > pMpegSurroundDecoder->mpsDataBits) ||
1488*e5436536SAndroid Build Coastguard Worker                     (pMpegSurroundDecoder->mpsDataBits > nbits + 7 &&
1489*e5436536SAndroid Build Coastguard Worker                      !IS_LOWDELAY(coreCodec))) {
1490*e5436536SAndroid Build Coastguard Worker                   bsFrame->newBsData = 0;
1491*e5436536SAndroid Build Coastguard Worker                   err = MPS_PARSE_ERROR;
1492*e5436536SAndroid Build Coastguard Worker                   break;
1493*e5436536SAndroid Build Coastguard Worker                 }
1494*e5436536SAndroid Build Coastguard Worker                 pMpegSurroundDecoder->mpsDataBits -= nbits;
1495*e5436536SAndroid Build Coastguard Worker               }
1496*e5436536SAndroid Build Coastguard Worker               break;
1497*e5436536SAndroid Build Coastguard Worker 
1498*e5436536SAndroid Build Coastguard Worker             default: /* added to avoid compiler warning */
1499*e5436536SAndroid Build Coastguard Worker               err = MPS_NOTOK;
1500*e5436536SAndroid Build Coastguard Worker               break; /* added to avoid compiler warning */
1501*e5436536SAndroid Build Coastguard Worker           }          /* switch (ancType) */
1502*e5436536SAndroid Build Coastguard Worker 
1503*e5436536SAndroid Build Coastguard Worker           if (err == MPS_OK) {
1504*e5436536SAndroid Build Coastguard Worker             pMpegSurroundDecoder->ancStartStopPrev = ancStartStop;
1505*e5436536SAndroid Build Coastguard Worker           } else {
1506*e5436536SAndroid Build Coastguard Worker             updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
1507*e5436536SAndroid Build Coastguard Worker                                             MPEGS_INIT_ERROR_PAYLOAD,
1508*e5436536SAndroid Build Coastguard Worker                                             MPEGS_SYNC_LOST, MPEGS_STOP);
1509*e5436536SAndroid Build Coastguard Worker             pMpegSurroundDecoder->mpsDataBits = 0;
1510*e5436536SAndroid Build Coastguard Worker           }
1511*e5436536SAndroid Build Coastguard Worker         } /* (ancStartStop == MPEGS_STOP) || (ancStartStop == MPEGS_START_STOP)
1512*e5436536SAndroid Build Coastguard Worker            */
1513*e5436536SAndroid Build Coastguard Worker       }   /* validAncStartStop */
1514*e5436536SAndroid Build Coastguard Worker     }     /* validAncType */
1515*e5436536SAndroid Build Coastguard Worker   }
1516*e5436536SAndroid Build Coastguard Worker 
1517*e5436536SAndroid Build Coastguard Worker bail:
1518*e5436536SAndroid Build Coastguard Worker 
1519*e5436536SAndroid Build Coastguard Worker   *pMpsDataBits -= (mpsBsBits - (INT)FDKgetValidBits(hBs));
1520*e5436536SAndroid Build Coastguard Worker 
1521*e5436536SAndroid Build Coastguard Worker   return err;
1522*e5436536SAndroid Build Coastguard Worker }
1523*e5436536SAndroid Build Coastguard Worker 
mpegSurroundDecoder_Apply(CMpegSurroundDecoder * pMpegSurroundDecoder,PCM_MPS * input,PCM_MPS * pTimeData,const int timeDataSize,int timeDataFrameSize,int * nChannels,int * frameSize,int sampleRate,AUDIO_OBJECT_TYPE coreCodec,AUDIO_CHANNEL_TYPE channelType[],UCHAR channelIndices[],const FDK_channelMapDescr * const mapDescr,const INT inDataHeadroom,INT * outDataHeadroom)1524*e5436536SAndroid Build Coastguard Worker int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder,
1525*e5436536SAndroid Build Coastguard Worker                               PCM_MPS *input, PCM_MPS *pTimeData,
1526*e5436536SAndroid Build Coastguard Worker                               const int timeDataSize, int timeDataFrameSize,
1527*e5436536SAndroid Build Coastguard Worker                               int *nChannels, int *frameSize, int sampleRate,
1528*e5436536SAndroid Build Coastguard Worker                               AUDIO_OBJECT_TYPE coreCodec,
1529*e5436536SAndroid Build Coastguard Worker                               AUDIO_CHANNEL_TYPE channelType[],
1530*e5436536SAndroid Build Coastguard Worker                               UCHAR channelIndices[],
1531*e5436536SAndroid Build Coastguard Worker                               const FDK_channelMapDescr *const mapDescr,
1532*e5436536SAndroid Build Coastguard Worker                               const INT inDataHeadroom, INT *outDataHeadroom) {
1533*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
1534*e5436536SAndroid Build Coastguard Worker   PCM_MPS *pTimeOut = pTimeData;
1535*e5436536SAndroid Build Coastguard Worker   PCM_MPS *TDinput = NULL;
1536*e5436536SAndroid Build Coastguard Worker   UINT initControlFlags = 0, controlFlags = 0;
1537*e5436536SAndroid Build Coastguard Worker   int timeDataRequiredSize = 0;
1538*e5436536SAndroid Build Coastguard Worker   int newData;
1539*e5436536SAndroid Build Coastguard Worker 
1540*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder == NULL) {
1541*e5436536SAndroid Build Coastguard Worker     return MPS_INVALID_HANDLE;
1542*e5436536SAndroid Build Coastguard Worker   }
1543*e5436536SAndroid Build Coastguard Worker 
1544*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec);
1545*e5436536SAndroid Build Coastguard Worker 
1546*e5436536SAndroid Build Coastguard Worker   if (!FDK_chMapDescr_isValid(mapDescr)) {
1547*e5436536SAndroid Build Coastguard Worker     return MPS_INVALID_HANDLE;
1548*e5436536SAndroid Build Coastguard Worker   }
1549*e5436536SAndroid Build Coastguard Worker 
1550*e5436536SAndroid Build Coastguard Worker   if ((*nChannels <= 0) || (*nChannels > 2)) {
1551*e5436536SAndroid Build Coastguard Worker     return MPS_NOTOK;
1552*e5436536SAndroid Build Coastguard Worker   }
1553*e5436536SAndroid Build Coastguard Worker 
1554*e5436536SAndroid Build Coastguard Worker   pMpegSurroundDecoder->pSpatialDec->sacInDataHeadroom = inDataHeadroom;
1555*e5436536SAndroid Build Coastguard Worker   *outDataHeadroom = (INT)(8);
1556*e5436536SAndroid Build Coastguard Worker 
1557*e5436536SAndroid Build Coastguard Worker   pMpegSurroundDecoder->pSpatialDec->pConfigCurrent =
1558*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder
1559*e5436536SAndroid Build Coastguard Worker            ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
1560*e5436536SAndroid Build Coastguard Worker   newData = pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]
1561*e5436536SAndroid Build Coastguard Worker                 .newBsData;
1562*e5436536SAndroid Build Coastguard Worker 
1563*e5436536SAndroid Build Coastguard Worker   switch (mpegSurroundOperationMode(pMpegSurroundDecoder, 1000)) {
1564*e5436536SAndroid Build Coastguard Worker     case MPEGS_OPMODE_MPS_PAYLOAD:
1565*e5436536SAndroid Build Coastguard Worker       if (pMpegSurroundDecoder
1566*e5436536SAndroid Build Coastguard Worker               ->initFlags[pMpegSurroundDecoder->bsFrameDecode]) {
1567*e5436536SAndroid Build Coastguard Worker         err = initMpegSurroundDecoder(pMpegSurroundDecoder);
1568*e5436536SAndroid Build Coastguard Worker       }
1569*e5436536SAndroid Build Coastguard Worker 
1570*e5436536SAndroid Build Coastguard Worker       if (err == MPS_OK) {
1571*e5436536SAndroid Build Coastguard Worker         if ((pMpegSurroundDecoder
1572*e5436536SAndroid Build Coastguard Worker                  ->fOnSync[pMpegSurroundDecoder->bsFrameDecode] !=
1573*e5436536SAndroid Build Coastguard Worker              MPEGS_SYNC_COMPLETE) &&
1574*e5436536SAndroid Build Coastguard Worker             (pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode]
1575*e5436536SAndroid Build Coastguard Worker                  .bsIndependencyFlag == 1)) {
1576*e5436536SAndroid Build Coastguard Worker           /* We got a valid header and independently decodeable frame data.
1577*e5436536SAndroid Build Coastguard Worker               -> Go to the next sync level and start processing. */
1578*e5436536SAndroid Build Coastguard Worker           pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
1579*e5436536SAndroid Build Coastguard Worker               MPEGS_SYNC_COMPLETE;
1580*e5436536SAndroid Build Coastguard Worker         }
1581*e5436536SAndroid Build Coastguard Worker       } else {
1582*e5436536SAndroid Build Coastguard Worker         /* We got a valid config header but found an error while parsing the
1583*e5436536SAndroid Build Coastguard Worker            bitstream. Wait for the next independent frame and apply error
1584*e5436536SAndroid Build Coastguard Worker            conealment in the meantime. */
1585*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
1586*e5436536SAndroid Build Coastguard Worker             MPEGS_SYNC_FOUND;
1587*e5436536SAndroid Build Coastguard Worker         controlFlags |= MPEGS_CONCEAL;
1588*e5436536SAndroid Build Coastguard Worker         err = MPS_OK;
1589*e5436536SAndroid Build Coastguard Worker       }
1590*e5436536SAndroid Build Coastguard Worker       /*
1591*e5436536SAndroid Build Coastguard Worker          Concealment:
1592*e5436536SAndroid Build Coastguard Worker          - Bitstream is available, no sync found during bitstream processing
1593*e5436536SAndroid Build Coastguard Worker          - Bitstream is available, sync lost due to corrupted bitstream
1594*e5436536SAndroid Build Coastguard Worker          - Bitstream is available, sync found but no independent frame
1595*e5436536SAndroid Build Coastguard Worker       */
1596*e5436536SAndroid Build Coastguard Worker       if (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] !=
1597*e5436536SAndroid Build Coastguard Worker           MPEGS_SYNC_COMPLETE) {
1598*e5436536SAndroid Build Coastguard Worker         controlFlags |= MPEGS_CONCEAL;
1599*e5436536SAndroid Build Coastguard Worker       }
1600*e5436536SAndroid Build Coastguard Worker       break;
1601*e5436536SAndroid Build Coastguard Worker 
1602*e5436536SAndroid Build Coastguard Worker     case MPEGS_OPMODE_NO_MPS_PAYLOAD:
1603*e5436536SAndroid Build Coastguard Worker       /* Concealment: No bitstream is available */
1604*e5436536SAndroid Build Coastguard Worker       controlFlags |= MPEGS_CONCEAL;
1605*e5436536SAndroid Build Coastguard Worker       break;
1606*e5436536SAndroid Build Coastguard Worker 
1607*e5436536SAndroid Build Coastguard Worker     default:
1608*e5436536SAndroid Build Coastguard Worker       err = MPS_NOTOK;
1609*e5436536SAndroid Build Coastguard Worker   }
1610*e5436536SAndroid Build Coastguard Worker 
1611*e5436536SAndroid Build Coastguard Worker   if (err != MPS_OK) {
1612*e5436536SAndroid Build Coastguard Worker     goto bail;
1613*e5436536SAndroid Build Coastguard Worker   }
1614*e5436536SAndroid Build Coastguard Worker 
1615*e5436536SAndroid Build Coastguard Worker   /*
1616*e5436536SAndroid Build Coastguard Worker    * Force BypassMode if choosen by user
1617*e5436536SAndroid Build Coastguard Worker    */
1618*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder->mpegSurroundUserParams.bypassMode) {
1619*e5436536SAndroid Build Coastguard Worker     controlFlags |= MPEGS_BYPASSMODE;
1620*e5436536SAndroid Build Coastguard Worker   }
1621*e5436536SAndroid Build Coastguard Worker 
1622*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) {
1623*e5436536SAndroid Build Coastguard Worker     int startWithDfltCfg = 0;
1624*e5436536SAndroid Build Coastguard Worker     /*
1625*e5436536SAndroid Build Coastguard Worker      * Init with a default configuration if we came here and are still not
1626*e5436536SAndroid Build Coastguard Worker      * initialized.
1627*e5436536SAndroid Build Coastguard Worker      */
1628*e5436536SAndroid Build Coastguard Worker     if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] &
1629*e5436536SAndroid Build Coastguard Worker         MPEGS_INIT_ENFORCE_REINIT) {
1630*e5436536SAndroid Build Coastguard Worker       /* Get default spatial specific config */
1631*e5436536SAndroid Build Coastguard Worker       if (FDK_SpatialDecInitDefaultSpatialSpecificConfig(
1632*e5436536SAndroid Build Coastguard Worker               &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec,
1633*e5436536SAndroid Build Coastguard Worker               *nChannels, sampleRate,
1634*e5436536SAndroid Build Coastguard Worker               *frameSize /
1635*e5436536SAndroid Build Coastguard Worker                   mpegSurroundDecoder_GetNrOfQmfBands(NULL, sampleRate),
1636*e5436536SAndroid Build Coastguard Worker               pMpegSurroundDecoder->mpegSurroundDecoderLevel,
1637*e5436536SAndroid Build Coastguard Worker               pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable)) {
1638*e5436536SAndroid Build Coastguard Worker         err = MPS_NOTOK;
1639*e5436536SAndroid Build Coastguard Worker         goto bail;
1640*e5436536SAndroid Build Coastguard Worker       }
1641*e5436536SAndroid Build Coastguard Worker 
1642*e5436536SAndroid Build Coastguard Worker       /* Initiate re-initialization, if header has changed */
1643*e5436536SAndroid Build Coastguard Worker       if (FDK_SpatialDecCompareSpatialSpecificConfigHeader(
1644*e5436536SAndroid Build Coastguard Worker               &pMpegSurroundDecoder->spatialSpecificConfigBackup,
1645*e5436536SAndroid Build Coastguard Worker               &pMpegSurroundDecoder->spatialSpecificConfig
1646*e5436536SAndroid Build Coastguard Worker                    [pMpegSurroundDecoder->bsFrameDecode]) == MPS_UNEQUAL_SSC) {
1647*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
1648*e5436536SAndroid Build Coastguard Worker             MPEGS_INIT_CHANGE_HEADER;
1649*e5436536SAndroid Build Coastguard Worker         SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec);
1650*e5436536SAndroid Build Coastguard Worker       }
1651*e5436536SAndroid Build Coastguard Worker 
1652*e5436536SAndroid Build Coastguard Worker       startWithDfltCfg = 1;
1653*e5436536SAndroid Build Coastguard Worker     }
1654*e5436536SAndroid Build Coastguard Worker 
1655*e5436536SAndroid Build Coastguard Worker     /* First spatial specific config is parsed into spatialSpecificConfigBackup,
1656*e5436536SAndroid Build Coastguard Worker      * second spatialSpecificConfigBackup is copied into spatialSpecificConfig
1657*e5436536SAndroid Build Coastguard Worker      */
1658*e5436536SAndroid Build Coastguard Worker     err = initMpegSurroundDecoder(pMpegSurroundDecoder);
1659*e5436536SAndroid Build Coastguard Worker 
1660*e5436536SAndroid Build Coastguard Worker     if (startWithDfltCfg) {
1661*e5436536SAndroid Build Coastguard Worker       /* initialized with default config, but no sync found */
1662*e5436536SAndroid Build Coastguard Worker       /* maybe use updateMpegSurroundDecoderStatus later on */
1663*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] =
1664*e5436536SAndroid Build Coastguard Worker           MPEGS_SYNC_LOST;
1665*e5436536SAndroid Build Coastguard Worker     }
1666*e5436536SAndroid Build Coastguard Worker 
1667*e5436536SAndroid Build Coastguard Worker     /* Since we do not have state MPEGS_SYNC_COMPLETE apply concealment */
1668*e5436536SAndroid Build Coastguard Worker     controlFlags |= MPEGS_CONCEAL;
1669*e5436536SAndroid Build Coastguard Worker 
1670*e5436536SAndroid Build Coastguard Worker     if (err != MPS_OK) {
1671*e5436536SAndroid Build Coastguard Worker       goto bail;
1672*e5436536SAndroid Build Coastguard Worker     }
1673*e5436536SAndroid Build Coastguard Worker   }
1674*e5436536SAndroid Build Coastguard Worker 
1675*e5436536SAndroid Build Coastguard Worker   /*
1676*e5436536SAndroid Build Coastguard Worker    * Process MPEG Surround Audio
1677*e5436536SAndroid Build Coastguard Worker    */
1678*e5436536SAndroid Build Coastguard Worker   initControlFlags = controlFlags;
1679*e5436536SAndroid Build Coastguard Worker 
1680*e5436536SAndroid Build Coastguard Worker   /* Check that provided output buffer is large enough. */
1681*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis == 0) {
1682*e5436536SAndroid Build Coastguard Worker     err = MPS_UNSUPPORTED_FORMAT;
1683*e5436536SAndroid Build Coastguard Worker     goto bail;
1684*e5436536SAndroid Build Coastguard Worker   }
1685*e5436536SAndroid Build Coastguard Worker   timeDataRequiredSize =
1686*e5436536SAndroid Build Coastguard Worker       (timeDataFrameSize *
1687*e5436536SAndroid Build Coastguard Worker        pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT *
1688*e5436536SAndroid Build Coastguard Worker        pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) /
1689*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis;
1690*e5436536SAndroid Build Coastguard Worker   if (timeDataSize < timeDataRequiredSize) {
1691*e5436536SAndroid Build Coastguard Worker     err = MPS_OUTPUT_BUFFER_TOO_SMALL;
1692*e5436536SAndroid Build Coastguard Worker     goto bail;
1693*e5436536SAndroid Build Coastguard Worker   }
1694*e5436536SAndroid Build Coastguard Worker 
1695*e5436536SAndroid Build Coastguard Worker   if ((pMpegSurroundDecoder->pSpatialDec->pConfigCurrent->syntaxFlags &
1696*e5436536SAndroid Build Coastguard Worker        SACDEC_SYNTAX_USAC) &&
1697*e5436536SAndroid Build Coastguard Worker       (pMpegSurroundDecoder->pSpatialDec->stereoConfigIndex > 1)) {
1698*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(timeDataRequiredSize >= timeDataFrameSize * *nChannels);
1699*e5436536SAndroid Build Coastguard Worker     /* Place samples comprising QMF time slots spaced at QMF output Band raster
1700*e5436536SAndroid Build Coastguard Worker      * to allow slot wise processing */
1701*e5436536SAndroid Build Coastguard Worker     int timeDataFrameSizeOut =
1702*e5436536SAndroid Build Coastguard Worker         (timeDataFrameSize *
1703*e5436536SAndroid Build Coastguard Worker          pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) /
1704*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis;
1705*e5436536SAndroid Build Coastguard Worker     TDinput = pTimeData + timeDataFrameSizeOut - timeDataFrameSize;
1706*e5436536SAndroid Build Coastguard Worker     for (int i = *nChannels - 1; i >= 0; i--) {
1707*e5436536SAndroid Build Coastguard Worker       FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize,
1708*e5436536SAndroid Build Coastguard Worker                  pTimeData + timeDataFrameSize * i,
1709*e5436536SAndroid Build Coastguard Worker                  sizeof(PCM_MPS) * timeDataFrameSize);
1710*e5436536SAndroid Build Coastguard Worker       FDKmemclear(pTimeData + i * timeDataFrameSizeOut,
1711*e5436536SAndroid Build Coastguard Worker                   sizeof(PCM_MPS) * (timeDataFrameSizeOut - timeDataFrameSize));
1712*e5436536SAndroid Build Coastguard Worker     }
1713*e5436536SAndroid Build Coastguard Worker   } else {
1714*e5436536SAndroid Build Coastguard Worker     if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) {
1715*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(input, pTimeData,
1716*e5436536SAndroid Build Coastguard Worker                 sizeof(PCM_MPS) * (*nChannels) * (*frameSize));
1717*e5436536SAndroid Build Coastguard Worker       TDinput = input;
1718*e5436536SAndroid Build Coastguard Worker     }
1719*e5436536SAndroid Build Coastguard Worker   }
1720*e5436536SAndroid Build Coastguard Worker 
1721*e5436536SAndroid Build Coastguard Worker   /*
1722*e5436536SAndroid Build Coastguard Worker    * Process MPEG Surround Audio
1723*e5436536SAndroid Build Coastguard Worker    */
1724*e5436536SAndroid Build Coastguard Worker   err = SpatialDecApplyFrame(
1725*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->pSpatialDec,
1726*e5436536SAndroid Build Coastguard Worker       &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode],
1727*e5436536SAndroid Build Coastguard Worker       pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME
1728*e5436536SAndroid Build Coastguard Worker                                                          : INPUTMODE_QMF_SBR,
1729*e5436536SAndroid Build Coastguard Worker       TDinput, NULL, NULL, pTimeOut, *frameSize, &controlFlags, *nChannels,
1730*e5436536SAndroid Build Coastguard Worker       mapDescr);
1731*e5436536SAndroid Build Coastguard Worker   *nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT;
1732*e5436536SAndroid Build Coastguard Worker 
1733*e5436536SAndroid Build Coastguard Worker   if (err !=
1734*e5436536SAndroid Build Coastguard Worker       MPS_OK) { /* A fatal error occured. Go back to start and try again: */
1735*e5436536SAndroid Build Coastguard Worker     updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
1736*e5436536SAndroid Build Coastguard Worker                                     MPEGS_INIT_ENFORCE_REINIT, MPEGS_SYNC_LOST,
1737*e5436536SAndroid Build Coastguard Worker                                     MPEGS_STOP);
1738*e5436536SAndroid Build Coastguard Worker     *frameSize =
1739*e5436536SAndroid Build Coastguard Worker         0; /* Declare that framework can not use the data in pTimeOut. */
1740*e5436536SAndroid Build Coastguard Worker   } else {
1741*e5436536SAndroid Build Coastguard Worker     if (((controlFlags & MPEGS_CONCEAL) &&
1742*e5436536SAndroid Build Coastguard Worker          !(initControlFlags & MPEGS_CONCEAL)) ||
1743*e5436536SAndroid Build Coastguard Worker         (pMpegSurroundDecoder->pSpatialDec->errInt !=
1744*e5436536SAndroid Build Coastguard Worker          MPS_OK)) { /* Account for errors that occured in
1745*e5436536SAndroid Build Coastguard Worker                        SpatialDecApplyFrame(): */
1746*e5436536SAndroid Build Coastguard Worker       updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
1747*e5436536SAndroid Build Coastguard Worker                                       MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST,
1748*e5436536SAndroid Build Coastguard Worker                                       MPEGS_STOP);
1749*e5436536SAndroid Build Coastguard Worker     }
1750*e5436536SAndroid Build Coastguard Worker   }
1751*e5436536SAndroid Build Coastguard Worker 
1752*e5436536SAndroid Build Coastguard Worker   if ((err == MPS_OK) && !(controlFlags & MPEGS_BYPASSMODE) &&
1753*e5436536SAndroid Build Coastguard Worker       !(pMpegSurroundDecoder->upmixType == UPMIX_TYPE_BYPASS)) {
1754*e5436536SAndroid Build Coastguard Worker     SpatialDecChannelProperties(pMpegSurroundDecoder->pSpatialDec, channelType,
1755*e5436536SAndroid Build Coastguard Worker                                 channelIndices, mapDescr);
1756*e5436536SAndroid Build Coastguard Worker   }
1757*e5436536SAndroid Build Coastguard Worker 
1758*e5436536SAndroid Build Coastguard Worker bail:
1759*e5436536SAndroid Build Coastguard Worker 
1760*e5436536SAndroid Build Coastguard Worker   if (newData) {
1761*e5436536SAndroid Build Coastguard Worker     /* numParameterSetsPrev shall only be read in the decode process, because of
1762*e5436536SAndroid Build Coastguard Worker        that we can update this state variable here */
1763*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->pSpatialDec->numParameterSetsPrev =
1764*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode]
1765*e5436536SAndroid Build Coastguard Worker             .numParameterSets;
1766*e5436536SAndroid Build Coastguard Worker   }
1767*e5436536SAndroid Build Coastguard Worker 
1768*e5436536SAndroid Build Coastguard Worker   return (err);
1769*e5436536SAndroid Build Coastguard Worker }
1770*e5436536SAndroid Build Coastguard Worker 
1771*e5436536SAndroid Build Coastguard Worker /**
1772*e5436536SAndroid Build Coastguard Worker  * \brief Free config dependent MPEG Surround memory.
1773*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_FreeMem(CMpegSurroundDecoder * pMpegSurroundDecoder)1774*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR mpegSurroundDecoder_FreeMem(
1775*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder) {
1776*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
1777*e5436536SAndroid Build Coastguard Worker 
1778*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder != NULL) {
1779*e5436536SAndroid Build Coastguard Worker     FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec);
1780*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->pSpatialDec = NULL;
1781*e5436536SAndroid Build Coastguard Worker   }
1782*e5436536SAndroid Build Coastguard Worker 
1783*e5436536SAndroid Build Coastguard Worker   return err;
1784*e5436536SAndroid Build Coastguard Worker }
1785*e5436536SAndroid Build Coastguard Worker 
1786*e5436536SAndroid Build Coastguard Worker /**
1787*e5436536SAndroid Build Coastguard Worker  * \brief Close MPEG Surround decoder.
1788*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_Close(CMpegSurroundDecoder * pMpegSurroundDecoder)1789*e5436536SAndroid Build Coastguard Worker void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder) {
1790*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder != NULL) {
1791*e5436536SAndroid Build Coastguard Worker     FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec);
1792*e5436536SAndroid Build Coastguard Worker     pMpegSurroundDecoder->pSpatialDec = NULL;
1793*e5436536SAndroid Build Coastguard Worker 
1794*e5436536SAndroid Build Coastguard Worker     for (int i = 0; i < 1; i++) {
1795*e5436536SAndroid Build Coastguard Worker       SpatialDecCloseBsFrame(&pMpegSurroundDecoder->bsFrames[i]);
1796*e5436536SAndroid Build Coastguard Worker     }
1797*e5436536SAndroid Build Coastguard Worker 
1798*e5436536SAndroid Build Coastguard Worker     FDK_FREE_MEMORY_1D(pMpegSurroundDecoder);
1799*e5436536SAndroid Build Coastguard Worker   }
1800*e5436536SAndroid Build Coastguard Worker }
1801*e5436536SAndroid Build Coastguard Worker 
1802*e5436536SAndroid Build Coastguard Worker #define SACDEC_VL0 2
1803*e5436536SAndroid Build Coastguard Worker #define SACDEC_VL1 1
1804*e5436536SAndroid Build Coastguard Worker #define SACDEC_VL2 0
1805*e5436536SAndroid Build Coastguard Worker 
mpegSurroundDecoder_GetLibInfo(LIB_INFO * info)1806*e5436536SAndroid Build Coastguard Worker int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) {
1807*e5436536SAndroid Build Coastguard Worker   int i;
1808*e5436536SAndroid Build Coastguard Worker 
1809*e5436536SAndroid Build Coastguard Worker   if (info == NULL) {
1810*e5436536SAndroid Build Coastguard Worker     return -1;
1811*e5436536SAndroid Build Coastguard Worker   }
1812*e5436536SAndroid Build Coastguard Worker 
1813*e5436536SAndroid Build Coastguard Worker   /* search for next free tab */
1814*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < FDK_MODULE_LAST; i++) {
1815*e5436536SAndroid Build Coastguard Worker     if (info[i].module_id == FDK_NONE) break;
1816*e5436536SAndroid Build Coastguard Worker   }
1817*e5436536SAndroid Build Coastguard Worker   if (i == FDK_MODULE_LAST) return -1;
1818*e5436536SAndroid Build Coastguard Worker 
1819*e5436536SAndroid Build Coastguard Worker   info += i;
1820*e5436536SAndroid Build Coastguard Worker 
1821*e5436536SAndroid Build Coastguard Worker   info->module_id = FDK_MPSDEC;
1822*e5436536SAndroid Build Coastguard Worker #ifdef SUPPRESS_BUILD_DATE_INFO
1823*e5436536SAndroid Build Coastguard Worker   info->build_date = "";
1824*e5436536SAndroid Build Coastguard Worker   info->build_time = "";
1825*e5436536SAndroid Build Coastguard Worker #else
1826*e5436536SAndroid Build Coastguard Worker   info->build_date = __DATE__;
1827*e5436536SAndroid Build Coastguard Worker   info->build_time = __TIME__;
1828*e5436536SAndroid Build Coastguard Worker #endif
1829*e5436536SAndroid Build Coastguard Worker   info->title = "MPEG Surround Decoder";
1830*e5436536SAndroid Build Coastguard Worker   info->version = LIB_VERSION(SACDEC_VL0, SACDEC_VL1, SACDEC_VL2);
1831*e5436536SAndroid Build Coastguard Worker   LIB_VERSION_STRING(info);
1832*e5436536SAndroid Build Coastguard Worker   info->flags = 0 | CAPF_MPS_LD | CAPF_MPS_USAC | CAPF_MPS_HQ |
1833*e5436536SAndroid Build Coastguard Worker                 CAPF_MPS_1CH_IN | CAPF_MPS_2CH_OUT; /* end flags */
1834*e5436536SAndroid Build Coastguard Worker 
1835*e5436536SAndroid Build Coastguard Worker   return 0;
1836*e5436536SAndroid Build Coastguard Worker }
1837*e5436536SAndroid Build Coastguard Worker 
mpegSurroundDecoder_SetParam(CMpegSurroundDecoder * pMpegSurroundDecoder,const SACDEC_PARAM param,const INT value)1838*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR mpegSurroundDecoder_SetParam(
1839*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder, const SACDEC_PARAM param,
1840*e5436536SAndroid Build Coastguard Worker     const INT value) {
1841*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
1842*e5436536SAndroid Build Coastguard Worker   SPATIALDEC_PARAM *pUserParams = NULL;
1843*e5436536SAndroid Build Coastguard Worker 
1844*e5436536SAndroid Build Coastguard Worker   /* check decoder handle */
1845*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder != NULL) {
1846*e5436536SAndroid Build Coastguard Worker     /* init local shortcuts */
1847*e5436536SAndroid Build Coastguard Worker     pUserParams = &pMpegSurroundDecoder->mpegSurroundUserParams;
1848*e5436536SAndroid Build Coastguard Worker   } else {
1849*e5436536SAndroid Build Coastguard Worker     err = MPS_INVALID_HANDLE;
1850*e5436536SAndroid Build Coastguard Worker     /* check the parameter values before exiting. */
1851*e5436536SAndroid Build Coastguard Worker   }
1852*e5436536SAndroid Build Coastguard Worker 
1853*e5436536SAndroid Build Coastguard Worker   /* apply param value */
1854*e5436536SAndroid Build Coastguard Worker   switch (param) {
1855*e5436536SAndroid Build Coastguard Worker     case SACDEC_OUTPUT_MODE:
1856*e5436536SAndroid Build Coastguard Worker       switch ((SAC_DEC_OUTPUT_MODE)value) {
1857*e5436536SAndroid Build Coastguard Worker         case SACDEC_OUT_MODE_NORMAL:
1858*e5436536SAndroid Build Coastguard Worker         case SACDEC_OUT_MODE_STEREO:
1859*e5436536SAndroid Build Coastguard Worker           break;
1860*e5436536SAndroid Build Coastguard Worker         default:
1861*e5436536SAndroid Build Coastguard Worker           err = MPS_INVALID_PARAMETER;
1862*e5436536SAndroid Build Coastguard Worker       }
1863*e5436536SAndroid Build Coastguard Worker       if (err == MPS_OK) {
1864*e5436536SAndroid Build Coastguard Worker         if (0) {
1865*e5436536SAndroid Build Coastguard Worker           err = MPS_INVALID_PARAMETER;
1866*e5436536SAndroid Build Coastguard Worker         } else if (pUserParams->outputMode != (UCHAR)value) {
1867*e5436536SAndroid Build Coastguard Worker           pUserParams->outputMode = (UCHAR)value;
1868*e5436536SAndroid Build Coastguard Worker           pMpegSurroundDecoder
1869*e5436536SAndroid Build Coastguard Worker               ->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
1870*e5436536SAndroid Build Coastguard Worker               MPEGS_INIT_CHANGE_OUTPUT_MODE;
1871*e5436536SAndroid Build Coastguard Worker         }
1872*e5436536SAndroid Build Coastguard Worker       }
1873*e5436536SAndroid Build Coastguard Worker       break;
1874*e5436536SAndroid Build Coastguard Worker 
1875*e5436536SAndroid Build Coastguard Worker     case SACDEC_INTERFACE:
1876*e5436536SAndroid Build Coastguard Worker       if (value < 0 || value > 1) {
1877*e5436536SAndroid Build Coastguard Worker         err = MPS_INVALID_PARAMETER;
1878*e5436536SAndroid Build Coastguard Worker       }
1879*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) {
1880*e5436536SAndroid Build Coastguard Worker         goto bail;
1881*e5436536SAndroid Build Coastguard Worker       }
1882*e5436536SAndroid Build Coastguard Worker       if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface != (UCHAR)value) {
1883*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->mpegSurroundUseTimeInterface = (UCHAR)value;
1884*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
1885*e5436536SAndroid Build Coastguard Worker             MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE;
1886*e5436536SAndroid Build Coastguard Worker       }
1887*e5436536SAndroid Build Coastguard Worker       break;
1888*e5436536SAndroid Build Coastguard Worker 
1889*e5436536SAndroid Build Coastguard Worker     case SACDEC_BS_INTERRUPTION:
1890*e5436536SAndroid Build Coastguard Worker       if ((err == MPS_OK) && (value != 0)) {
1891*e5436536SAndroid Build Coastguard Worker         updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
1892*e5436536SAndroid Build Coastguard Worker                                         MPEGS_INIT_BS_INTERRUPTION,
1893*e5436536SAndroid Build Coastguard Worker                                         MPEGS_SYNC_LOST, MPEGS_STOP);
1894*e5436536SAndroid Build Coastguard Worker       }
1895*e5436536SAndroid Build Coastguard Worker       break;
1896*e5436536SAndroid Build Coastguard Worker 
1897*e5436536SAndroid Build Coastguard Worker     case SACDEC_CLEAR_HISTORY:
1898*e5436536SAndroid Build Coastguard Worker       if ((err == MPS_OK) && (value != 0)) {
1899*e5436536SAndroid Build Coastguard Worker         /* Just reset the states and go on. */
1900*e5436536SAndroid Build Coastguard Worker         updateMpegSurroundDecoderStatus(pMpegSurroundDecoder,
1901*e5436536SAndroid Build Coastguard Worker                                         MPEGS_INIT_CLEAR_HISTORY,
1902*e5436536SAndroid Build Coastguard Worker                                         MPEGS_SYNC_LOST, MPEGS_STOP);
1903*e5436536SAndroid Build Coastguard Worker       }
1904*e5436536SAndroid Build Coastguard Worker       break;
1905*e5436536SAndroid Build Coastguard Worker 
1906*e5436536SAndroid Build Coastguard Worker     case SACDEC_CONCEAL_NUM_KEEP_FRAMES:
1907*e5436536SAndroid Build Coastguard Worker       if (value < 0) { /* Check valid value range */
1908*e5436536SAndroid Build Coastguard Worker         err = MPS_INVALID_PARAMETER;
1909*e5436536SAndroid Build Coastguard Worker       }
1910*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) {
1911*e5436536SAndroid Build Coastguard Worker         goto bail;
1912*e5436536SAndroid Build Coastguard Worker       }
1913*e5436536SAndroid Build Coastguard Worker       if (pUserParams->concealNumKeepFrames != (UINT)value) {
1914*e5436536SAndroid Build Coastguard Worker         pUserParams->concealNumKeepFrames = (UINT)value;
1915*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
1916*e5436536SAndroid Build Coastguard Worker             MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
1917*e5436536SAndroid Build Coastguard Worker       }
1918*e5436536SAndroid Build Coastguard Worker       break;
1919*e5436536SAndroid Build Coastguard Worker 
1920*e5436536SAndroid Build Coastguard Worker     case SACDEC_CONCEAL_FADE_OUT_SLOPE_LENGTH:
1921*e5436536SAndroid Build Coastguard Worker       if (value < 0) { /* Check valid value range */
1922*e5436536SAndroid Build Coastguard Worker         err = MPS_INVALID_PARAMETER;
1923*e5436536SAndroid Build Coastguard Worker       }
1924*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) {
1925*e5436536SAndroid Build Coastguard Worker         goto bail;
1926*e5436536SAndroid Build Coastguard Worker       }
1927*e5436536SAndroid Build Coastguard Worker       if (pUserParams->concealFadeOutSlopeLength != (UINT)value) {
1928*e5436536SAndroid Build Coastguard Worker         pUserParams->concealFadeOutSlopeLength = (UINT)value;
1929*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
1930*e5436536SAndroid Build Coastguard Worker             MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
1931*e5436536SAndroid Build Coastguard Worker       }
1932*e5436536SAndroid Build Coastguard Worker       break;
1933*e5436536SAndroid Build Coastguard Worker 
1934*e5436536SAndroid Build Coastguard Worker     case SACDEC_CONCEAL_FADE_IN_SLOPE_LENGTH:
1935*e5436536SAndroid Build Coastguard Worker       if (value < 0) { /* Check valid value range */
1936*e5436536SAndroid Build Coastguard Worker         err = MPS_INVALID_PARAMETER;
1937*e5436536SAndroid Build Coastguard Worker       }
1938*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) {
1939*e5436536SAndroid Build Coastguard Worker         goto bail;
1940*e5436536SAndroid Build Coastguard Worker       }
1941*e5436536SAndroid Build Coastguard Worker       if (pUserParams->concealFadeInSlopeLength != (UINT)value) {
1942*e5436536SAndroid Build Coastguard Worker         pUserParams->concealFadeInSlopeLength = (UINT)value;
1943*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
1944*e5436536SAndroid Build Coastguard Worker             MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
1945*e5436536SAndroid Build Coastguard Worker       }
1946*e5436536SAndroid Build Coastguard Worker       break;
1947*e5436536SAndroid Build Coastguard Worker 
1948*e5436536SAndroid Build Coastguard Worker     case SACDEC_CONCEAL_NUM_RELEASE_FRAMES:
1949*e5436536SAndroid Build Coastguard Worker       if (value < 0) { /* Check valid value range */
1950*e5436536SAndroid Build Coastguard Worker         err = MPS_INVALID_PARAMETER;
1951*e5436536SAndroid Build Coastguard Worker       }
1952*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) {
1953*e5436536SAndroid Build Coastguard Worker         goto bail;
1954*e5436536SAndroid Build Coastguard Worker       }
1955*e5436536SAndroid Build Coastguard Worker       if (pUserParams->concealNumReleaseFrames != (UINT)value) {
1956*e5436536SAndroid Build Coastguard Worker         pUserParams->concealNumReleaseFrames = (UINT)value;
1957*e5436536SAndroid Build Coastguard Worker         pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |=
1958*e5436536SAndroid Build Coastguard Worker             MPEGS_INIT_CHANGE_CONCEAL_PARAMS;
1959*e5436536SAndroid Build Coastguard Worker       }
1960*e5436536SAndroid Build Coastguard Worker       break;
1961*e5436536SAndroid Build Coastguard Worker 
1962*e5436536SAndroid Build Coastguard Worker     default:
1963*e5436536SAndroid Build Coastguard Worker       err = MPS_INVALID_PARAMETER;
1964*e5436536SAndroid Build Coastguard Worker       break;
1965*e5436536SAndroid Build Coastguard Worker   } /* switch(param) */
1966*e5436536SAndroid Build Coastguard Worker 
1967*e5436536SAndroid Build Coastguard Worker bail:
1968*e5436536SAndroid Build Coastguard Worker   return err;
1969*e5436536SAndroid Build Coastguard Worker }
1970*e5436536SAndroid Build Coastguard Worker 
mpegSurroundDecoder_IsPseudoLR(CMpegSurroundDecoder * pMpegSurroundDecoder,int * bsPseudoLr)1971*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR mpegSurroundDecoder_IsPseudoLR(
1972*e5436536SAndroid Build Coastguard Worker     CMpegSurroundDecoder *pMpegSurroundDecoder, int *bsPseudoLr) {
1973*e5436536SAndroid Build Coastguard Worker   if (pMpegSurroundDecoder != NULL) {
1974*e5436536SAndroid Build Coastguard Worker     const SPATIAL_SPECIFIC_CONFIG *sscDecode =
1975*e5436536SAndroid Build Coastguard Worker         &pMpegSurroundDecoder
1976*e5436536SAndroid Build Coastguard Worker              ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode];
1977*e5436536SAndroid Build Coastguard Worker     *bsPseudoLr = (int)sscDecode->bsPseudoLr;
1978*e5436536SAndroid Build Coastguard Worker     return MPS_OK;
1979*e5436536SAndroid Build Coastguard Worker   } else
1980*e5436536SAndroid Build Coastguard Worker     return MPS_INVALID_HANDLE;
1981*e5436536SAndroid Build Coastguard Worker }
1982*e5436536SAndroid Build Coastguard Worker 
1983*e5436536SAndroid Build Coastguard Worker /**
1984*e5436536SAndroid Build Coastguard Worker  * \brief Get the signal delay caused by the MPEG Surround decoder module.
1985*e5436536SAndroid Build Coastguard Worker  **/
mpegSurroundDecoder_GetDelay(const CMpegSurroundDecoder * self)1986*e5436536SAndroid Build Coastguard Worker UINT mpegSurroundDecoder_GetDelay(const CMpegSurroundDecoder *self) {
1987*e5436536SAndroid Build Coastguard Worker   INT outputDelay = 0;
1988*e5436536SAndroid Build Coastguard Worker 
1989*e5436536SAndroid Build Coastguard Worker   if (self != NULL) {
1990*e5436536SAndroid Build Coastguard Worker     const SPATIAL_SPECIFIC_CONFIG *sscDecode =
1991*e5436536SAndroid Build Coastguard Worker         &self->spatialSpecificConfig[self->bsFrameDecode];
1992*e5436536SAndroid Build Coastguard Worker     AUDIO_OBJECT_TYPE coreCodec = sscDecode->coreCodec;
1993*e5436536SAndroid Build Coastguard Worker 
1994*e5436536SAndroid Build Coastguard Worker     /* See chapter 4.5 (delay and synchronization) of ISO/IEC FDIS 23003-1 and
1995*e5436536SAndroid Build Coastguard Worker        chapter 5.4.3 of ISO/IEC FDIS 23003-2 for details on the following
1996*e5436536SAndroid Build Coastguard Worker        figures. */
1997*e5436536SAndroid Build Coastguard Worker 
1998*e5436536SAndroid Build Coastguard Worker     if (coreCodec > AOT_NULL_OBJECT) {
1999*e5436536SAndroid Build Coastguard Worker       if (IS_LOWDELAY(coreCodec)) {
2000*e5436536SAndroid Build Coastguard Worker         /* All low delay variants (ER-AAC-(E)LD): */
2001*e5436536SAndroid Build Coastguard Worker         outputDelay += 256;
2002*e5436536SAndroid Build Coastguard Worker       } else if (!IS_USAC(coreCodec)) {
2003*e5436536SAndroid Build Coastguard Worker         /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...)
2004*e5436536SAndroid Build Coastguard Worker          * branch: */
2005*e5436536SAndroid Build Coastguard Worker         outputDelay += 320 + 257; /* cos to exp delay + QMF synthesis */
2006*e5436536SAndroid Build Coastguard Worker         if (self->mpegSurroundUseTimeInterface) {
2007*e5436536SAndroid Build Coastguard Worker           outputDelay += 320 + 384; /* QMF and hybrid analysis */
2008*e5436536SAndroid Build Coastguard Worker         }
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   return (outputDelay);
2014*e5436536SAndroid Build Coastguard Worker }
2015