xref: /aosp_15_r20/external/aac/libMpegTPDec/src/tpdec_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 - 2022 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 transport format decoder library *********************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):   Manuel Jander
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description: MPEG Transport decoder
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "tpdec_lib.h"
104*e5436536SAndroid Build Coastguard Worker 
105*e5436536SAndroid Build Coastguard Worker /* library version */
106*e5436536SAndroid Build Coastguard Worker #include "tp_version.h"
107*e5436536SAndroid Build Coastguard Worker 
108*e5436536SAndroid Build Coastguard Worker #include "tp_data.h"
109*e5436536SAndroid Build Coastguard Worker 
110*e5436536SAndroid Build Coastguard Worker #include "tpdec_adts.h"
111*e5436536SAndroid Build Coastguard Worker 
112*e5436536SAndroid Build Coastguard Worker #include "tpdec_adif.h"
113*e5436536SAndroid Build Coastguard Worker 
114*e5436536SAndroid Build Coastguard Worker #include "tpdec_latm.h"
115*e5436536SAndroid Build Coastguard Worker 
116*e5436536SAndroid Build Coastguard Worker #include "tpdec_drm.h"
117*e5436536SAndroid Build Coastguard Worker 
118*e5436536SAndroid Build Coastguard Worker #include "FDK_crc.h"
119*e5436536SAndroid Build Coastguard Worker 
120*e5436536SAndroid Build Coastguard Worker #define MODULE_NAME "transportDec"
121*e5436536SAndroid Build Coastguard Worker 
122*e5436536SAndroid Build Coastguard Worker typedef union {
123*e5436536SAndroid Build Coastguard Worker   STRUCT_ADTS adts;
124*e5436536SAndroid Build Coastguard Worker 
125*e5436536SAndroid Build Coastguard Worker   CAdifHeader adif;
126*e5436536SAndroid Build Coastguard Worker 
127*e5436536SAndroid Build Coastguard Worker   CLatmDemux latm;
128*e5436536SAndroid Build Coastguard Worker 
129*e5436536SAndroid Build Coastguard Worker   STRUCT_DRM drm;
130*e5436536SAndroid Build Coastguard Worker 
131*e5436536SAndroid Build Coastguard Worker } transportdec_parser_t;
132*e5436536SAndroid Build Coastguard Worker 
133*e5436536SAndroid Build Coastguard Worker #define MHAS_CONFIG_PRESENT 0x001
134*e5436536SAndroid Build Coastguard Worker #define MHAS_UI_PRESENT 0x002
135*e5436536SAndroid Build Coastguard Worker 
136*e5436536SAndroid Build Coastguard Worker struct TRANSPORTDEC {
137*e5436536SAndroid Build Coastguard Worker   TRANSPORT_TYPE transportFmt; /*!< MPEG4 transportDec type. */
138*e5436536SAndroid Build Coastguard Worker 
139*e5436536SAndroid Build Coastguard Worker   CSTpCallBacks callbacks; /*!< Struct holding callback and its data */
140*e5436536SAndroid Build Coastguard Worker 
141*e5436536SAndroid Build Coastguard Worker   FDK_BITSTREAM bitStream[1]; /* Bitstream reader */
142*e5436536SAndroid Build Coastguard Worker   UCHAR *bsBuffer;            /* Internal bitstreamd data buffer */
143*e5436536SAndroid Build Coastguard Worker 
144*e5436536SAndroid Build Coastguard Worker   transportdec_parser_t parser; /* Format specific parser structs. */
145*e5436536SAndroid Build Coastguard Worker 
146*e5436536SAndroid Build Coastguard Worker   CSAudioSpecificConfig asc[(1 * 1) + 1]; /* Audio specific config from the last
147*e5436536SAndroid Build Coastguard Worker                                              config found. One additional
148*e5436536SAndroid Build Coastguard Worker                                              CSAudioSpecificConfig is used
149*e5436536SAndroid Build Coastguard Worker                                              temporarily for parsing. */
150*e5436536SAndroid Build Coastguard Worker   CCtrlCFGChange ctrlCFGChange[(1 * 1)];  /* Controls config change */
151*e5436536SAndroid Build Coastguard Worker 
152*e5436536SAndroid Build Coastguard Worker   UINT globalFramePos;      /* Global transport frame reference bit position. */
153*e5436536SAndroid Build Coastguard Worker   UINT accessUnitAnchor[1]; /* Current access unit start bit position. */
154*e5436536SAndroid Build Coastguard Worker   INT auLength[1];          /* Length of current access unit. */
155*e5436536SAndroid Build Coastguard Worker   INT numberOfRawDataBlocks; /* Current number of raw data blocks contained
156*e5436536SAndroid Build Coastguard Worker                                 remaining from the current transport frame. */
157*e5436536SAndroid Build Coastguard Worker   UINT avgBitRate; /* Average bit rate used for frame loss estimation. */
158*e5436536SAndroid Build Coastguard Worker   UINT lastValidBufferFullness; /* Last valid buffer fullness value for frame
159*e5436536SAndroid Build Coastguard Worker                                    loss estimation */
160*e5436536SAndroid Build Coastguard Worker   INT remainder; /* Reminder in division during lost access unit estimation. */
161*e5436536SAndroid Build Coastguard Worker   INT missingAccessUnits; /* Estimated missing access units. */
162*e5436536SAndroid Build Coastguard Worker   UINT burstPeriod;       /* Data burst period in mili seconds. */
163*e5436536SAndroid Build Coastguard Worker   UINT holdOffFrames;     /* Amount of frames that were already hold off due to
164*e5436536SAndroid Build Coastguard Worker                              buffer fullness condition not being met. */
165*e5436536SAndroid Build Coastguard Worker   UINT flags;             /* Flags. */
166*e5436536SAndroid Build Coastguard Worker   INT targetLayout;       /* CICP target layout. */
167*e5436536SAndroid Build Coastguard Worker   UINT *pLoudnessInfoSetPosition; /* Reference and start position (bits) and
168*e5436536SAndroid Build Coastguard Worker                                      length (bytes) of loudnessInfoSet within
169*e5436536SAndroid Build Coastguard Worker                                      rsv603daConfig.  */
170*e5436536SAndroid Build Coastguard Worker };
171*e5436536SAndroid Build Coastguard Worker 
172*e5436536SAndroid Build Coastguard Worker /* Flag bitmasks for "flags" member of struct TRANSPORTDEC */
173*e5436536SAndroid Build Coastguard Worker #define TPDEC_SYNCOK 1
174*e5436536SAndroid Build Coastguard Worker #define TPDEC_MINIMIZE_DELAY 2
175*e5436536SAndroid Build Coastguard Worker #define TPDEC_IGNORE_BUFFERFULLNESS 4
176*e5436536SAndroid Build Coastguard Worker #define TPDEC_EARLY_CONFIG 8
177*e5436536SAndroid Build Coastguard Worker #define TPDEC_LOST_FRAMES_PENDING 16
178*e5436536SAndroid Build Coastguard Worker #define TPDEC_CONFIG_FOUND 32
179*e5436536SAndroid Build Coastguard Worker #define TPDEC_USE_ELEM_SKIPPING 64
180*e5436536SAndroid Build Coastguard Worker 
181*e5436536SAndroid Build Coastguard Worker /* force config/content change */
182*e5436536SAndroid Build Coastguard Worker #define TPDEC_FORCE_CONFIG_CHANGE 1
183*e5436536SAndroid Build Coastguard Worker #define TPDEC_FORCE_CONTENT_CHANGE 2
184*e5436536SAndroid Build Coastguard Worker 
185*e5436536SAndroid Build Coastguard Worker /* skip packet */
186*e5436536SAndroid Build Coastguard Worker #define TPDEC_SKIP_PACKET 1
187*e5436536SAndroid Build Coastguard Worker 
188*e5436536SAndroid Build Coastguard Worker C_ALLOC_MEM(Ram_TransportDecoder, struct TRANSPORTDEC, 1)
189*e5436536SAndroid Build Coastguard Worker C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, (8192 * 4))
190*e5436536SAndroid Build Coastguard Worker 
transportDec_Open(const TRANSPORT_TYPE transportFmt,const UINT flags,const UINT nrOfLayers)191*e5436536SAndroid Build Coastguard Worker HANDLE_TRANSPORTDEC transportDec_Open(const TRANSPORT_TYPE transportFmt,
192*e5436536SAndroid Build Coastguard Worker                                       const UINT flags, const UINT nrOfLayers) {
193*e5436536SAndroid Build Coastguard Worker   HANDLE_TRANSPORTDEC hInput;
194*e5436536SAndroid Build Coastguard Worker 
195*e5436536SAndroid Build Coastguard Worker   hInput = GetRam_TransportDecoder(0);
196*e5436536SAndroid Build Coastguard Worker   if (hInput == NULL) {
197*e5436536SAndroid Build Coastguard Worker     return NULL;
198*e5436536SAndroid Build Coastguard Worker   }
199*e5436536SAndroid Build Coastguard Worker 
200*e5436536SAndroid Build Coastguard Worker   /* Init transportDec struct. */
201*e5436536SAndroid Build Coastguard Worker   hInput->transportFmt = transportFmt;
202*e5436536SAndroid Build Coastguard Worker 
203*e5436536SAndroid Build Coastguard Worker   switch (transportFmt) {
204*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADIF:
205*e5436536SAndroid Build Coastguard Worker       break;
206*e5436536SAndroid Build Coastguard Worker 
207*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
208*e5436536SAndroid Build Coastguard Worker       if (flags & TP_FLAG_MPEG4)
209*e5436536SAndroid Build Coastguard Worker         hInput->parser.adts.decoderCanDoMpeg4 = 1;
210*e5436536SAndroid Build Coastguard Worker       else
211*e5436536SAndroid Build Coastguard Worker         hInput->parser.adts.decoderCanDoMpeg4 = 0;
212*e5436536SAndroid Build Coastguard Worker       adtsRead_CrcInit(&hInput->parser.adts);
213*e5436536SAndroid Build Coastguard Worker       hInput->parser.adts.BufferFullnesStartFlag = 1;
214*e5436536SAndroid Build Coastguard Worker       hInput->numberOfRawDataBlocks = 0;
215*e5436536SAndroid Build Coastguard Worker       break;
216*e5436536SAndroid Build Coastguard Worker 
217*e5436536SAndroid Build Coastguard Worker     case TT_DRM:
218*e5436536SAndroid Build Coastguard Worker       drmRead_CrcInit(&hInput->parser.drm);
219*e5436536SAndroid Build Coastguard Worker       break;
220*e5436536SAndroid Build Coastguard Worker 
221*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP0:
222*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP1:
223*e5436536SAndroid Build Coastguard Worker       hInput->parser.latm.usacExplicitCfgChanged = 0;
224*e5436536SAndroid Build Coastguard Worker       hInput->parser.latm.applyAsc = 1;
225*e5436536SAndroid Build Coastguard Worker       break;
226*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
227*e5436536SAndroid Build Coastguard Worker       hInput->parser.latm.usacExplicitCfgChanged = 0;
228*e5436536SAndroid Build Coastguard Worker       hInput->parser.latm.applyAsc = 1;
229*e5436536SAndroid Build Coastguard Worker       break;
230*e5436536SAndroid Build Coastguard Worker     case TT_MP4_RAW:
231*e5436536SAndroid Build Coastguard Worker       break;
232*e5436536SAndroid Build Coastguard Worker 
233*e5436536SAndroid Build Coastguard Worker     default:
234*e5436536SAndroid Build Coastguard Worker       FreeRam_TransportDecoder(&hInput);
235*e5436536SAndroid Build Coastguard Worker       hInput = NULL;
236*e5436536SAndroid Build Coastguard Worker       break;
237*e5436536SAndroid Build Coastguard Worker   }
238*e5436536SAndroid Build Coastguard Worker 
239*e5436536SAndroid Build Coastguard Worker   if (hInput != NULL) {
240*e5436536SAndroid Build Coastguard Worker     /* Create bitstream */
241*e5436536SAndroid Build Coastguard Worker     {
242*e5436536SAndroid Build Coastguard Worker       hInput->bsBuffer = GetRam_TransportDecoderBuffer(0);
243*e5436536SAndroid Build Coastguard Worker       if (hInput->bsBuffer == NULL) {
244*e5436536SAndroid Build Coastguard Worker         transportDec_Close(&hInput);
245*e5436536SAndroid Build Coastguard Worker         return NULL;
246*e5436536SAndroid Build Coastguard Worker       }
247*e5436536SAndroid Build Coastguard Worker       if (nrOfLayers > 1) {
248*e5436536SAndroid Build Coastguard Worker         transportDec_Close(&hInput);
249*e5436536SAndroid Build Coastguard Worker         return NULL;
250*e5436536SAndroid Build Coastguard Worker       }
251*e5436536SAndroid Build Coastguard Worker       for (UINT i = 0; i < nrOfLayers; i++) {
252*e5436536SAndroid Build Coastguard Worker         FDKinitBitStream(&hInput->bitStream[i], hInput->bsBuffer, (8192 * 4), 0,
253*e5436536SAndroid Build Coastguard Worker                          BS_READER);
254*e5436536SAndroid Build Coastguard Worker       }
255*e5436536SAndroid Build Coastguard Worker     }
256*e5436536SAndroid Build Coastguard Worker     hInput->burstPeriod = 0;
257*e5436536SAndroid Build Coastguard Worker   }
258*e5436536SAndroid Build Coastguard Worker 
259*e5436536SAndroid Build Coastguard Worker   return hInput;
260*e5436536SAndroid Build Coastguard Worker }
261*e5436536SAndroid Build Coastguard Worker 
transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp,UCHAR * conf,const UINT length,UINT layer)262*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp,
263*e5436536SAndroid Build Coastguard Worker                                                 UCHAR *conf, const UINT length,
264*e5436536SAndroid Build Coastguard Worker                                                 UINT layer) {
265*e5436536SAndroid Build Coastguard Worker   int i;
266*e5436536SAndroid Build Coastguard Worker 
267*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
268*e5436536SAndroid Build Coastguard Worker 
269*e5436536SAndroid Build Coastguard Worker   FDK_BITSTREAM bs;
270*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs = &bs;
271*e5436536SAndroid Build Coastguard Worker 
272*e5436536SAndroid Build Coastguard Worker   int fConfigFound = 0;
273*e5436536SAndroid Build Coastguard Worker 
274*e5436536SAndroid Build Coastguard Worker   UCHAR configChanged = 0;
275*e5436536SAndroid Build Coastguard Worker   UCHAR configMode = AC_CM_DET_CFG_CHANGE;
276*e5436536SAndroid Build Coastguard Worker 
277*e5436536SAndroid Build Coastguard Worker   UCHAR tmpConf[1024] = {0};
278*e5436536SAndroid Build Coastguard Worker   if (length > 1024) {
279*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_UNSUPPORTED_FORMAT;
280*e5436536SAndroid Build Coastguard Worker   }
281*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(tmpConf, conf, length);
282*e5436536SAndroid Build Coastguard Worker   FDKinitBitStream(hBs, tmpConf, 1024, length << 3, BS_READER);
283*e5436536SAndroid Build Coastguard Worker 
284*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < 2; i++) {
285*e5436536SAndroid Build Coastguard Worker     if (i > 0) {
286*e5436536SAndroid Build Coastguard Worker       FDKpushBack(hBs, (INT)length * 8 - (INT)FDKgetValidBits(hBs));
287*e5436536SAndroid Build Coastguard Worker       configMode = AC_CM_ALLOC_MEM;
288*e5436536SAndroid Build Coastguard Worker     }
289*e5436536SAndroid Build Coastguard Worker 
290*e5436536SAndroid Build Coastguard Worker     /* config transport decoder */
291*e5436536SAndroid Build Coastguard Worker     switch (hTp->transportFmt) {
292*e5436536SAndroid Build Coastguard Worker       case TT_MP4_LATM_MCP0:
293*e5436536SAndroid Build Coastguard Worker       case TT_MP4_LATM_MCP1:
294*e5436536SAndroid Build Coastguard Worker       case TT_MP4_LOAS: {
295*e5436536SAndroid Build Coastguard Worker         if (layer != 0) {
296*e5436536SAndroid Build Coastguard Worker           return TRANSPORTDEC_INVALID_PARAMETER;
297*e5436536SAndroid Build Coastguard Worker         }
298*e5436536SAndroid Build Coastguard Worker         CLatmDemux *pLatmDemux = &hTp->parser.latm;
299*e5436536SAndroid Build Coastguard Worker         err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks,
300*e5436536SAndroid Build Coastguard Worker                                              hTp->asc, &fConfigFound,
301*e5436536SAndroid Build Coastguard Worker                                              configMode, configChanged);
302*e5436536SAndroid Build Coastguard Worker         if (err != TRANSPORTDEC_OK) {
303*e5436536SAndroid Build Coastguard Worker           return err;
304*e5436536SAndroid Build Coastguard Worker         }
305*e5436536SAndroid Build Coastguard Worker       } break;
306*e5436536SAndroid Build Coastguard Worker       default:
307*e5436536SAndroid Build Coastguard Worker         fConfigFound = 1;
308*e5436536SAndroid Build Coastguard Worker         err = AudioSpecificConfig_Parse(&hTp->asc[(1 * 1)], hBs, 1,
309*e5436536SAndroid Build Coastguard Worker                                         &hTp->callbacks, configMode,
310*e5436536SAndroid Build Coastguard Worker                                         configChanged, AOT_NULL_OBJECT);
311*e5436536SAndroid Build Coastguard Worker         if (err == TRANSPORTDEC_OK) {
312*e5436536SAndroid Build Coastguard Worker           int errC;
313*e5436536SAndroid Build Coastguard Worker 
314*e5436536SAndroid Build Coastguard Worker           hTp->asc[layer] = hTp->asc[(1 * 1)];
315*e5436536SAndroid Build Coastguard Worker           errC = hTp->callbacks.cbUpdateConfig(
316*e5436536SAndroid Build Coastguard Worker               hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer],
317*e5436536SAndroid Build Coastguard Worker               hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged);
318*e5436536SAndroid Build Coastguard Worker           if (errC != 0) {
319*e5436536SAndroid Build Coastguard Worker             err = TRANSPORTDEC_PARSE_ERROR;
320*e5436536SAndroid Build Coastguard Worker           }
321*e5436536SAndroid Build Coastguard Worker         }
322*e5436536SAndroid Build Coastguard Worker         break;
323*e5436536SAndroid Build Coastguard Worker       case TT_DRM:
324*e5436536SAndroid Build Coastguard Worker         fConfigFound = 1;
325*e5436536SAndroid Build Coastguard Worker         err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs, &hTp->callbacks,
326*e5436536SAndroid Build Coastguard Worker                                          configMode, configChanged);
327*e5436536SAndroid Build Coastguard Worker         if (err == TRANSPORTDEC_OK) {
328*e5436536SAndroid Build Coastguard Worker           int errC;
329*e5436536SAndroid Build Coastguard Worker 
330*e5436536SAndroid Build Coastguard Worker           errC = hTp->callbacks.cbUpdateConfig(
331*e5436536SAndroid Build Coastguard Worker               hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer],
332*e5436536SAndroid Build Coastguard Worker               hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged);
333*e5436536SAndroid Build Coastguard Worker           if (errC != 0) {
334*e5436536SAndroid Build Coastguard Worker             err = TRANSPORTDEC_PARSE_ERROR;
335*e5436536SAndroid Build Coastguard Worker           }
336*e5436536SAndroid Build Coastguard Worker         }
337*e5436536SAndroid Build Coastguard Worker         break;
338*e5436536SAndroid Build Coastguard Worker     }
339*e5436536SAndroid Build Coastguard Worker 
340*e5436536SAndroid Build Coastguard Worker     if (err == TRANSPORTDEC_OK) {
341*e5436536SAndroid Build Coastguard Worker       if ((i == 0) && (hTp->asc[layer].AacConfigChanged ||
342*e5436536SAndroid Build Coastguard Worker                        hTp->asc[layer].SbrConfigChanged ||
343*e5436536SAndroid Build Coastguard Worker                        hTp->asc[layer].SacConfigChanged)) {
344*e5436536SAndroid Build Coastguard Worker         int errC;
345*e5436536SAndroid Build Coastguard Worker 
346*e5436536SAndroid Build Coastguard Worker         configChanged = 1;
347*e5436536SAndroid Build Coastguard Worker         errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData,
348*e5436536SAndroid Build Coastguard Worker                                         &hTp->asc[layer]);
349*e5436536SAndroid Build Coastguard Worker         if (errC != 0) {
350*e5436536SAndroid Build Coastguard Worker           err = TRANSPORTDEC_PARSE_ERROR;
351*e5436536SAndroid Build Coastguard Worker         }
352*e5436536SAndroid Build Coastguard Worker       }
353*e5436536SAndroid Build Coastguard Worker     }
354*e5436536SAndroid Build Coastguard Worker 
355*e5436536SAndroid Build Coastguard Worker     /* if an error is detected terminate config parsing to avoid that an invalid
356*e5436536SAndroid Build Coastguard Worker      * config is accepted in the second pass */
357*e5436536SAndroid Build Coastguard Worker     if (err != TRANSPORTDEC_OK) {
358*e5436536SAndroid Build Coastguard Worker       break;
359*e5436536SAndroid Build Coastguard Worker     }
360*e5436536SAndroid Build Coastguard Worker   }
361*e5436536SAndroid Build Coastguard Worker 
362*e5436536SAndroid Build Coastguard Worker   if (err == TRANSPORTDEC_OK && fConfigFound) {
363*e5436536SAndroid Build Coastguard Worker     hTp->flags |= TPDEC_CONFIG_FOUND;
364*e5436536SAndroid Build Coastguard Worker   }
365*e5436536SAndroid Build Coastguard Worker 
366*e5436536SAndroid Build Coastguard Worker   return err;
367*e5436536SAndroid Build Coastguard Worker }
368*e5436536SAndroid Build Coastguard Worker 
transportDec_InBandConfig(HANDLE_TRANSPORTDEC hTp,UCHAR * newConfig,const UINT newConfigLength,const UCHAR buildUpStatus,UCHAR * configChanged,UINT layer,UCHAR * implicitExplicitCfgDiff)369*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_InBandConfig(HANDLE_TRANSPORTDEC hTp,
370*e5436536SAndroid Build Coastguard Worker                                              UCHAR *newConfig,
371*e5436536SAndroid Build Coastguard Worker                                              const UINT newConfigLength,
372*e5436536SAndroid Build Coastguard Worker                                              const UCHAR buildUpStatus,
373*e5436536SAndroid Build Coastguard Worker                                              UCHAR *configChanged, UINT layer,
374*e5436536SAndroid Build Coastguard Worker                                              UCHAR *implicitExplicitCfgDiff) {
375*e5436536SAndroid Build Coastguard Worker   int errC;
376*e5436536SAndroid Build Coastguard Worker   FDK_BITSTREAM bs;
377*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs = &bs;
378*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
379*e5436536SAndroid Build Coastguard Worker   int fConfigFound = 0;
380*e5436536SAndroid Build Coastguard Worker   UCHAR configMode = AC_CM_ALLOC_MEM;
381*e5436536SAndroid Build Coastguard Worker   *implicitExplicitCfgDiff = 0;
382*e5436536SAndroid Build Coastguard Worker 
383*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(hTp->asc->m_aot == AOT_USAC);
384*e5436536SAndroid Build Coastguard Worker 
385*e5436536SAndroid Build Coastguard Worker   FDKinitBitStream(hBs, newConfig, TP_USAC_MAX_CONFIG_LEN, newConfigLength << 3,
386*e5436536SAndroid Build Coastguard Worker                    BS_READER);
387*e5436536SAndroid Build Coastguard Worker 
388*e5436536SAndroid Build Coastguard Worker   if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) &&
389*e5436536SAndroid Build Coastguard Worker       (hTp->ctrlCFGChange[layer].buildUpStatus !=
390*e5436536SAndroid Build Coastguard Worker        TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) {
391*e5436536SAndroid Build Coastguard Worker     if (hTp->asc->m_aot == AOT_USAC) {
392*e5436536SAndroid Build Coastguard Worker       if ((UINT)(hTp->asc->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3 ==
393*e5436536SAndroid Build Coastguard Worker           newConfigLength) {
394*e5436536SAndroid Build Coastguard Worker         if (0 == FDKmemcmp(newConfig, hTp->asc->m_sc.m_usacConfig.UsacConfig,
395*e5436536SAndroid Build Coastguard Worker                            newConfigLength)) {
396*e5436536SAndroid Build Coastguard Worker           if (hTp->parser.latm.usacExplicitCfgChanged) { /* configChange from
397*e5436536SAndroid Build Coastguard Worker                                                             LOAS/LATM parser */
398*e5436536SAndroid Build Coastguard Worker             hTp->parser.latm.usacExplicitCfgChanged = 0;
399*e5436536SAndroid Build Coastguard Worker             hTp->ctrlCFGChange[layer].flushCnt = 0;
400*e5436536SAndroid Build Coastguard Worker             hTp->ctrlCFGChange[layer].flushStatus =
401*e5436536SAndroid Build Coastguard Worker                 TPDEC_USAC_DASH_IPF_FLUSH_ON;
402*e5436536SAndroid Build Coastguard Worker             hTp->ctrlCFGChange[layer].buildUpCnt = 0;
403*e5436536SAndroid Build Coastguard Worker             hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF;
404*e5436536SAndroid Build Coastguard Worker           } else {
405*e5436536SAndroid Build Coastguard Worker             *configChanged = 0;
406*e5436536SAndroid Build Coastguard Worker             return err;
407*e5436536SAndroid Build Coastguard Worker           }
408*e5436536SAndroid Build Coastguard Worker         } else {
409*e5436536SAndroid Build Coastguard Worker           *implicitExplicitCfgDiff = 1;
410*e5436536SAndroid Build Coastguard Worker         }
411*e5436536SAndroid Build Coastguard Worker       } else {
412*e5436536SAndroid Build Coastguard Worker         *implicitExplicitCfgDiff = 1;
413*e5436536SAndroid Build Coastguard Worker       }
414*e5436536SAndroid Build Coastguard Worker       /* ISO/IEC 23003-3:2012/FDAM 3:2016(E) Annex F.2: explicit and implicit
415*e5436536SAndroid Build Coastguard Worker        * config shall be identical. */
416*e5436536SAndroid Build Coastguard Worker       if (*implicitExplicitCfgDiff) {
417*e5436536SAndroid Build Coastguard Worker         switch (hTp->transportFmt) {
418*e5436536SAndroid Build Coastguard Worker           case TT_MP4_LATM_MCP0:
419*e5436536SAndroid Build Coastguard Worker           case TT_MP4_LATM_MCP1:
420*e5436536SAndroid Build Coastguard Worker           case TT_MP4_LOAS:
421*e5436536SAndroid Build Coastguard Worker             /* reset decoder to initial state to achieve definite behavior after
422*e5436536SAndroid Build Coastguard Worker              * error in config */
423*e5436536SAndroid Build Coastguard Worker             hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData,
424*e5436536SAndroid Build Coastguard Worker                                      &hTp->asc[layer]);
425*e5436536SAndroid Build Coastguard Worker             hTp->parser.latm.usacExplicitCfgChanged = 0;
426*e5436536SAndroid Build Coastguard Worker             hTp->parser.latm.applyAsc = 1;
427*e5436536SAndroid Build Coastguard Worker             err = TRANSPORTDEC_PARSE_ERROR;
428*e5436536SAndroid Build Coastguard Worker             goto bail;
429*e5436536SAndroid Build Coastguard Worker           default:
430*e5436536SAndroid Build Coastguard Worker             break;
431*e5436536SAndroid Build Coastguard Worker         }
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   {
437*e5436536SAndroid Build Coastguard Worker     if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) &&
438*e5436536SAndroid Build Coastguard Worker         (hTp->ctrlCFGChange[layer].buildUpStatus !=
439*e5436536SAndroid Build Coastguard Worker          TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) {
440*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].flushCnt = 0;
441*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].buildUpCnt = 0;
442*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF;
443*e5436536SAndroid Build Coastguard Worker       if (hTp->asc->m_aot == AOT_USAC) {
444*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].flushStatus = TPDEC_USAC_DASH_IPF_FLUSH_ON;
445*e5436536SAndroid Build Coastguard Worker       }
446*e5436536SAndroid Build Coastguard Worker     }
447*e5436536SAndroid Build Coastguard Worker 
448*e5436536SAndroid Build Coastguard Worker     if ((hTp->ctrlCFGChange[layer].flushStatus ==
449*e5436536SAndroid Build Coastguard Worker          TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) ||
450*e5436536SAndroid Build Coastguard Worker         (hTp->ctrlCFGChange[layer].flushStatus ==
451*e5436536SAndroid Build Coastguard Worker          TPDEC_USAC_DASH_IPF_FLUSH_ON)) {
452*e5436536SAndroid Build Coastguard Worker       SCHAR counter = 0;
453*e5436536SAndroid Build Coastguard Worker       if (hTp->asc->m_aot == AOT_USAC) {
454*e5436536SAndroid Build Coastguard Worker         counter = TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES;
455*e5436536SAndroid Build Coastguard Worker       }
456*e5436536SAndroid Build Coastguard Worker       if (hTp->ctrlCFGChange[layer].flushCnt >= counter) {
457*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].flushCnt = 0;
458*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF;
459*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].forceCfgChange = 0;
460*e5436536SAndroid Build Coastguard Worker         if (hTp->asc->m_aot == AOT_USAC) {
461*e5436536SAndroid Build Coastguard Worker           hTp->ctrlCFGChange[layer].buildUpCnt =
462*e5436536SAndroid Build Coastguard Worker               TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES - 1;
463*e5436536SAndroid Build Coastguard Worker           hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_USAC_BUILD_UP_ON;
464*e5436536SAndroid Build Coastguard Worker         }
465*e5436536SAndroid Build Coastguard Worker       }
466*e5436536SAndroid Build Coastguard Worker 
467*e5436536SAndroid Build Coastguard Worker       /* Activate flush mode. After that continue with build up mode in core */
468*e5436536SAndroid Build Coastguard Worker       if (hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData,
469*e5436536SAndroid Build Coastguard Worker                                          &hTp->ctrlCFGChange[layer]) != 0) {
470*e5436536SAndroid Build Coastguard Worker         err = TRANSPORTDEC_PARSE_ERROR;
471*e5436536SAndroid Build Coastguard Worker       }
472*e5436536SAndroid Build Coastguard Worker 
473*e5436536SAndroid Build Coastguard Worker       if ((hTp->ctrlCFGChange[layer].flushStatus ==
474*e5436536SAndroid Build Coastguard Worker            TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) ||
475*e5436536SAndroid Build Coastguard Worker           (hTp->ctrlCFGChange[layer].flushStatus ==
476*e5436536SAndroid Build Coastguard Worker            TPDEC_USAC_DASH_IPF_FLUSH_ON)) {
477*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].flushCnt++;
478*e5436536SAndroid Build Coastguard Worker         return err;
479*e5436536SAndroid Build Coastguard Worker       }
480*e5436536SAndroid Build Coastguard Worker     }
481*e5436536SAndroid Build Coastguard Worker 
482*e5436536SAndroid Build Coastguard Worker     if (hTp->asc->m_aot == AOT_USAC) {
483*e5436536SAndroid Build Coastguard Worker       fConfigFound = 1;
484*e5436536SAndroid Build Coastguard Worker 
485*e5436536SAndroid Build Coastguard Worker       if (err == TRANSPORTDEC_OK) {
486*e5436536SAndroid Build Coastguard Worker         *configChanged = 0;
487*e5436536SAndroid Build Coastguard Worker         configMode = AC_CM_DET_CFG_CHANGE;
488*e5436536SAndroid Build Coastguard Worker 
489*e5436536SAndroid Build Coastguard Worker         for (int i = 0; i < 2; i++) {
490*e5436536SAndroid Build Coastguard Worker           if (i > 0) {
491*e5436536SAndroid Build Coastguard Worker             FDKpushBack(hBs,
492*e5436536SAndroid Build Coastguard Worker                         (INT)newConfigLength * 8 - (INT)FDKgetValidBits(hBs));
493*e5436536SAndroid Build Coastguard Worker             configMode = AC_CM_ALLOC_MEM;
494*e5436536SAndroid Build Coastguard Worker           }
495*e5436536SAndroid Build Coastguard Worker           /* config transport decoder */
496*e5436536SAndroid Build Coastguard Worker           err = AudioSpecificConfig_Parse(
497*e5436536SAndroid Build Coastguard Worker               &hTp->asc[(1 * 1)], hBs, 0, &hTp->callbacks, configMode,
498*e5436536SAndroid Build Coastguard Worker               *configChanged, hTp->asc[layer].m_aot);
499*e5436536SAndroid Build Coastguard Worker           if (err == TRANSPORTDEC_OK) {
500*e5436536SAndroid Build Coastguard Worker             hTp->asc[layer] = hTp->asc[(1 * 1)];
501*e5436536SAndroid Build Coastguard Worker             errC = hTp->callbacks.cbUpdateConfig(
502*e5436536SAndroid Build Coastguard Worker                 hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer],
503*e5436536SAndroid Build Coastguard Worker                 hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged);
504*e5436536SAndroid Build Coastguard Worker             if (errC != 0) {
505*e5436536SAndroid Build Coastguard Worker               err = TRANSPORTDEC_PARSE_ERROR;
506*e5436536SAndroid Build Coastguard Worker             }
507*e5436536SAndroid Build Coastguard Worker           }
508*e5436536SAndroid Build Coastguard Worker 
509*e5436536SAndroid Build Coastguard Worker           if (err == TRANSPORTDEC_OK) {
510*e5436536SAndroid Build Coastguard Worker             if ((i == 0) && (hTp->asc[layer].AacConfigChanged ||
511*e5436536SAndroid Build Coastguard Worker                              hTp->asc[layer].SbrConfigChanged ||
512*e5436536SAndroid Build Coastguard Worker                              hTp->asc[layer].SacConfigChanged)) {
513*e5436536SAndroid Build Coastguard Worker               *configChanged = 1;
514*e5436536SAndroid Build Coastguard Worker               errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData,
515*e5436536SAndroid Build Coastguard Worker                                               &hTp->asc[layer]);
516*e5436536SAndroid Build Coastguard Worker               if (errC != 0) {
517*e5436536SAndroid Build Coastguard Worker                 err = TRANSPORTDEC_PARSE_ERROR;
518*e5436536SAndroid Build Coastguard Worker               }
519*e5436536SAndroid Build Coastguard Worker             }
520*e5436536SAndroid Build Coastguard Worker           }
521*e5436536SAndroid Build Coastguard Worker 
522*e5436536SAndroid Build Coastguard Worker           /* if an error is detected terminate config parsing to avoid that an
523*e5436536SAndroid Build Coastguard Worker            * invalid config is accepted in the second pass */
524*e5436536SAndroid Build Coastguard Worker           if (err != TRANSPORTDEC_OK) {
525*e5436536SAndroid Build Coastguard Worker             break;
526*e5436536SAndroid Build Coastguard Worker           }
527*e5436536SAndroid Build Coastguard Worker         }
528*e5436536SAndroid Build Coastguard Worker       }
529*e5436536SAndroid Build Coastguard Worker     }
530*e5436536SAndroid Build Coastguard Worker 
531*e5436536SAndroid Build Coastguard Worker   bail:
532*e5436536SAndroid Build Coastguard Worker     /* save new config */
533*e5436536SAndroid Build Coastguard Worker     if (err == TRANSPORTDEC_OK) {
534*e5436536SAndroid Build Coastguard Worker       if (hTp->asc->m_aot == AOT_USAC) {
535*e5436536SAndroid Build Coastguard Worker         hTp->asc->m_sc.m_usacConfig.UsacConfigBits = newConfigLength << 3;
536*e5436536SAndroid Build Coastguard Worker         FDKmemcpy(hTp->asc->m_sc.m_usacConfig.UsacConfig, newConfig,
537*e5436536SAndroid Build Coastguard Worker                   newConfigLength);
538*e5436536SAndroid Build Coastguard Worker         /* in case of USAC reset transportDecoder variables here because
539*e5436536SAndroid Build Coastguard Worker          * otherwise without IPF they are not reset */
540*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].flushCnt = 0;
541*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF;
542*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].buildUpCnt = 0;
543*e5436536SAndroid Build Coastguard Worker         hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF;
544*e5436536SAndroid Build Coastguard Worker       }
545*e5436536SAndroid Build Coastguard Worker     } else {
546*e5436536SAndroid Build Coastguard Worker       hTp->numberOfRawDataBlocks = 0;
547*e5436536SAndroid Build Coastguard Worker 
548*e5436536SAndroid Build Coastguard Worker       /* If parsing error while config found, clear ctrlCFGChange-struct */
549*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].flushCnt = 0;
550*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF;
551*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].buildUpCnt = 0;
552*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF;
553*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].cfgChanged = 0;
554*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].contentChanged = 0;
555*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[layer].forceCfgChange = 0;
556*e5436536SAndroid Build Coastguard Worker 
557*e5436536SAndroid Build Coastguard Worker       hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData,
558*e5436536SAndroid Build Coastguard Worker                                      &hTp->ctrlCFGChange[layer]);
559*e5436536SAndroid Build Coastguard Worker     }
560*e5436536SAndroid Build Coastguard Worker   }
561*e5436536SAndroid Build Coastguard Worker 
562*e5436536SAndroid Build Coastguard Worker   if (err == TRANSPORTDEC_OK && fConfigFound) {
563*e5436536SAndroid Build Coastguard Worker     hTp->flags |= TPDEC_CONFIG_FOUND;
564*e5436536SAndroid Build Coastguard Worker   }
565*e5436536SAndroid Build Coastguard Worker 
566*e5436536SAndroid Build Coastguard Worker   return err;
567*e5436536SAndroid Build Coastguard Worker }
568*e5436536SAndroid Build Coastguard Worker 
transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTpDec,const cbUpdateConfig_t cbUpdateConfig,void * user_data)569*e5436536SAndroid Build Coastguard Worker int transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTpDec,
570*e5436536SAndroid Build Coastguard Worker                                      const cbUpdateConfig_t cbUpdateConfig,
571*e5436536SAndroid Build Coastguard Worker                                      void *user_data) {
572*e5436536SAndroid Build Coastguard Worker   if (hTpDec == NULL) {
573*e5436536SAndroid Build Coastguard Worker     return -1;
574*e5436536SAndroid Build Coastguard Worker   }
575*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbUpdateConfig = cbUpdateConfig;
576*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbUpdateConfigData = user_data;
577*e5436536SAndroid Build Coastguard Worker   return 0;
578*e5436536SAndroid Build Coastguard Worker }
579*e5436536SAndroid Build Coastguard Worker 
transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTpDec,const cbFreeMem_t cbFreeMem,void * user_data)580*e5436536SAndroid Build Coastguard Worker int transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTpDec,
581*e5436536SAndroid Build Coastguard Worker                                          const cbFreeMem_t cbFreeMem,
582*e5436536SAndroid Build Coastguard Worker                                          void *user_data) {
583*e5436536SAndroid Build Coastguard Worker   if (hTpDec == NULL) {
584*e5436536SAndroid Build Coastguard Worker     return -1;
585*e5436536SAndroid Build Coastguard Worker   }
586*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbFreeMem = cbFreeMem;
587*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbFreeMemData = user_data;
588*e5436536SAndroid Build Coastguard Worker   return 0;
589*e5436536SAndroid Build Coastguard Worker }
590*e5436536SAndroid Build Coastguard Worker 
transportDec_RegisterCtrlCFGChangeCallback(HANDLE_TRANSPORTDEC hTpDec,const cbCtrlCFGChange_t cbCtrlCFGChange,void * user_data)591*e5436536SAndroid Build Coastguard Worker int transportDec_RegisterCtrlCFGChangeCallback(
592*e5436536SAndroid Build Coastguard Worker     HANDLE_TRANSPORTDEC hTpDec, const cbCtrlCFGChange_t cbCtrlCFGChange,
593*e5436536SAndroid Build Coastguard Worker     void *user_data) {
594*e5436536SAndroid Build Coastguard Worker   if (hTpDec == NULL) {
595*e5436536SAndroid Build Coastguard Worker     return -1;
596*e5436536SAndroid Build Coastguard Worker   }
597*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbCtrlCFGChange = cbCtrlCFGChange;
598*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbCtrlCFGChangeData = user_data;
599*e5436536SAndroid Build Coastguard Worker   return 0;
600*e5436536SAndroid Build Coastguard Worker }
601*e5436536SAndroid Build Coastguard Worker 
transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTpDec,const cbSsc_t cbSsc,void * user_data)602*e5436536SAndroid Build Coastguard Worker int transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTpDec,
603*e5436536SAndroid Build Coastguard Worker                                      const cbSsc_t cbSsc, void *user_data) {
604*e5436536SAndroid Build Coastguard Worker   if (hTpDec == NULL) {
605*e5436536SAndroid Build Coastguard Worker     return -1;
606*e5436536SAndroid Build Coastguard Worker   }
607*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbSsc = cbSsc;
608*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbSscData = user_data;
609*e5436536SAndroid Build Coastguard Worker   return 0;
610*e5436536SAndroid Build Coastguard Worker }
611*e5436536SAndroid Build Coastguard Worker 
transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec,const cbSbr_t cbSbr,void * user_data)612*e5436536SAndroid Build Coastguard Worker int transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec,
613*e5436536SAndroid Build Coastguard Worker                                      const cbSbr_t cbSbr, void *user_data) {
614*e5436536SAndroid Build Coastguard Worker   if (hTpDec == NULL) {
615*e5436536SAndroid Build Coastguard Worker     return -1;
616*e5436536SAndroid Build Coastguard Worker   }
617*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbSbr = cbSbr;
618*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbSbrData = user_data;
619*e5436536SAndroid Build Coastguard Worker   return 0;
620*e5436536SAndroid Build Coastguard Worker }
621*e5436536SAndroid Build Coastguard Worker 
transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec,const cbUsac_t cbUsac,void * user_data)622*e5436536SAndroid Build Coastguard Worker int transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec,
623*e5436536SAndroid Build Coastguard Worker                                       const cbUsac_t cbUsac, void *user_data) {
624*e5436536SAndroid Build Coastguard Worker   if (hTpDec == NULL) {
625*e5436536SAndroid Build Coastguard Worker     return -1;
626*e5436536SAndroid Build Coastguard Worker   }
627*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbUsac = cbUsac;
628*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbUsacData = user_data;
629*e5436536SAndroid Build Coastguard Worker   return 0;
630*e5436536SAndroid Build Coastguard Worker }
631*e5436536SAndroid Build Coastguard Worker 
transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec,const cbUniDrc_t cbUniDrc,void * user_data,UINT * pLoudnessInfoSetPosition)632*e5436536SAndroid Build Coastguard Worker int transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec,
633*e5436536SAndroid Build Coastguard Worker                                               const cbUniDrc_t cbUniDrc,
634*e5436536SAndroid Build Coastguard Worker                                               void *user_data,
635*e5436536SAndroid Build Coastguard Worker                                               UINT *pLoudnessInfoSetPosition) {
636*e5436536SAndroid Build Coastguard Worker   if (hTpDec == NULL) {
637*e5436536SAndroid Build Coastguard Worker     return -1;
638*e5436536SAndroid Build Coastguard Worker   }
639*e5436536SAndroid Build Coastguard Worker 
640*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbUniDrc = cbUniDrc;
641*e5436536SAndroid Build Coastguard Worker   hTpDec->callbacks.cbUniDrcData = user_data;
642*e5436536SAndroid Build Coastguard Worker 
643*e5436536SAndroid Build Coastguard Worker   hTpDec->pLoudnessInfoSetPosition = pLoudnessInfoSetPosition;
644*e5436536SAndroid Build Coastguard Worker   return 0;
645*e5436536SAndroid Build Coastguard Worker }
646*e5436536SAndroid Build Coastguard Worker 
transportDec_FillData(const HANDLE_TRANSPORTDEC hTp,UCHAR * pBuffer,const UINT bufferSize,UINT * pBytesValid,const INT layer)647*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_FillData(const HANDLE_TRANSPORTDEC hTp,
648*e5436536SAndroid Build Coastguard Worker                                          UCHAR *pBuffer, const UINT bufferSize,
649*e5436536SAndroid Build Coastguard Worker                                          UINT *pBytesValid, const INT layer) {
650*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs;
651*e5436536SAndroid Build Coastguard Worker 
652*e5436536SAndroid Build Coastguard Worker   if ((hTp == NULL) || (layer >= 1)) {
653*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_INVALID_PARAMETER;
654*e5436536SAndroid Build Coastguard Worker   }
655*e5436536SAndroid Build Coastguard Worker 
656*e5436536SAndroid Build Coastguard Worker   /* set bitbuffer shortcut */
657*e5436536SAndroid Build Coastguard Worker   hBs = &hTp->bitStream[layer];
658*e5436536SAndroid Build Coastguard Worker 
659*e5436536SAndroid Build Coastguard Worker   if (TT_IS_PACKET(hTp->transportFmt)) {
660*e5436536SAndroid Build Coastguard Worker     if (hTp->numberOfRawDataBlocks == 0) {
661*e5436536SAndroid Build Coastguard Worker       FDKresetBitbuffer(hBs);
662*e5436536SAndroid Build Coastguard Worker       FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid);
663*e5436536SAndroid Build Coastguard Worker       if (*pBytesValid != 0) {
664*e5436536SAndroid Build Coastguard Worker         return TRANSPORTDEC_TOO_MANY_BITS;
665*e5436536SAndroid Build Coastguard Worker       }
666*e5436536SAndroid Build Coastguard Worker     }
667*e5436536SAndroid Build Coastguard Worker   } else {
668*e5436536SAndroid Build Coastguard Worker     /* ... else feed bitbuffer with new stream data (append). */
669*e5436536SAndroid Build Coastguard Worker 
670*e5436536SAndroid Build Coastguard Worker     if (*pBytesValid == 0) {
671*e5436536SAndroid Build Coastguard Worker       /* nothing to do */
672*e5436536SAndroid Build Coastguard Worker       return TRANSPORTDEC_OK;
673*e5436536SAndroid Build Coastguard Worker     } else {
674*e5436536SAndroid Build Coastguard Worker       const int bytesValid = *pBytesValid;
675*e5436536SAndroid Build Coastguard Worker       FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid);
676*e5436536SAndroid Build Coastguard Worker 
677*e5436536SAndroid Build Coastguard Worker       if (hTp->numberOfRawDataBlocks > 0) {
678*e5436536SAndroid Build Coastguard Worker         hTp->globalFramePos += (bytesValid - *pBytesValid) * 8;
679*e5436536SAndroid Build Coastguard Worker         hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs);
680*e5436536SAndroid Build Coastguard Worker       }
681*e5436536SAndroid Build Coastguard Worker     }
682*e5436536SAndroid Build Coastguard Worker   }
683*e5436536SAndroid Build Coastguard Worker 
684*e5436536SAndroid Build Coastguard Worker   return TRANSPORTDEC_OK;
685*e5436536SAndroid Build Coastguard Worker }
686*e5436536SAndroid Build Coastguard Worker 
transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp,const UINT layer)687*e5436536SAndroid Build Coastguard Worker HANDLE_FDK_BITSTREAM transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp,
688*e5436536SAndroid Build Coastguard Worker                                                const UINT layer) {
689*e5436536SAndroid Build Coastguard Worker   return &hTp->bitStream[layer];
690*e5436536SAndroid Build Coastguard Worker }
691*e5436536SAndroid Build Coastguard Worker 
transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp)692*e5436536SAndroid Build Coastguard Worker TRANSPORT_TYPE transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp) {
693*e5436536SAndroid Build Coastguard Worker   return hTp->transportFmt;
694*e5436536SAndroid Build Coastguard Worker }
695*e5436536SAndroid Build Coastguard Worker 
transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp)696*e5436536SAndroid Build Coastguard Worker INT transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp) {
697*e5436536SAndroid Build Coastguard Worker   INT bufferFullness = -1;
698*e5436536SAndroid Build Coastguard Worker 
699*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
700*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
701*e5436536SAndroid Build Coastguard Worker       if (hTp->parser.adts.bs.adts_fullness != 0x7ff) {
702*e5436536SAndroid Build Coastguard Worker         bufferFullness = hTp->parser.adts.bs.frame_length * 8 +
703*e5436536SAndroid Build Coastguard Worker                          hTp->parser.adts.bs.adts_fullness * 32 *
704*e5436536SAndroid Build Coastguard Worker                              getNumberOfEffectiveChannels(
705*e5436536SAndroid Build Coastguard Worker                                  hTp->parser.adts.bs.channel_config);
706*e5436536SAndroid Build Coastguard Worker       }
707*e5436536SAndroid Build Coastguard Worker       break;
708*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
709*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP0:
710*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP1:
711*e5436536SAndroid Build Coastguard Worker       if (hTp->parser.latm.m_linfo[0][0].m_bufferFullness != 0xff) {
712*e5436536SAndroid Build Coastguard Worker         bufferFullness = hTp->parser.latm.m_linfo[0][0].m_bufferFullness;
713*e5436536SAndroid Build Coastguard Worker       }
714*e5436536SAndroid Build Coastguard Worker       break;
715*e5436536SAndroid Build Coastguard Worker     default:
716*e5436536SAndroid Build Coastguard Worker       break;
717*e5436536SAndroid Build Coastguard Worker   }
718*e5436536SAndroid Build Coastguard Worker 
719*e5436536SAndroid Build Coastguard Worker   return bufferFullness;
720*e5436536SAndroid Build Coastguard Worker }
721*e5436536SAndroid Build Coastguard Worker 
722*e5436536SAndroid Build Coastguard Worker /**
723*e5436536SAndroid Build Coastguard Worker  * \brief adjust bit stream position and the end of an access unit.
724*e5436536SAndroid Build Coastguard Worker  * \param hTp transport decoder handle.
725*e5436536SAndroid Build Coastguard Worker  * \return error code.
726*e5436536SAndroid Build Coastguard Worker  */
transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp)727*e5436536SAndroid Build Coastguard Worker static TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(
728*e5436536SAndroid Build Coastguard Worker     HANDLE_TRANSPORTDEC hTp) {
729*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
730*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
731*e5436536SAndroid Build Coastguard Worker 
732*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
733*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADIF:
734*e5436536SAndroid Build Coastguard Worker       /* Do byte align at the end of raw_data_block() because UsacFrame() is not
735*e5436536SAndroid Build Coastguard Worker        * byte aligned. */
736*e5436536SAndroid Build Coastguard Worker       FDKbyteAlign(hBs, hTp->accessUnitAnchor[0]);
737*e5436536SAndroid Build Coastguard Worker       break;
738*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
739*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP0:
740*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP1:
741*e5436536SAndroid Build Coastguard Worker       if (hTp->numberOfRawDataBlocks == 0) {
742*e5436536SAndroid Build Coastguard Worker         /* Do byte align at the end of AudioMuxElement. */
743*e5436536SAndroid Build Coastguard Worker         FDKbyteAlign(hBs, hTp->globalFramePos);
744*e5436536SAndroid Build Coastguard Worker 
745*e5436536SAndroid Build Coastguard Worker         /* Check global frame length */
746*e5436536SAndroid Build Coastguard Worker         if (hTp->transportFmt == TT_MP4_LOAS &&
747*e5436536SAndroid Build Coastguard Worker             hTp->parser.latm.m_audioMuxLengthBytes > 0) {
748*e5436536SAndroid Build Coastguard Worker           int loasOffset;
749*e5436536SAndroid Build Coastguard Worker 
750*e5436536SAndroid Build Coastguard Worker           loasOffset = ((INT)hTp->parser.latm.m_audioMuxLengthBytes * 8 +
751*e5436536SAndroid Build Coastguard Worker                         (INT)FDKgetValidBits(hBs)) -
752*e5436536SAndroid Build Coastguard Worker                        (INT)hTp->globalFramePos;
753*e5436536SAndroid Build Coastguard Worker           if (loasOffset != 0) {
754*e5436536SAndroid Build Coastguard Worker             FDKpushBiDirectional(hBs, loasOffset);
755*e5436536SAndroid Build Coastguard Worker             /* For ELD and other payloads there is an unknown amount of padding,
756*e5436536SAndroid Build Coastguard Worker                so ignore unread bits, but throw an error only if too many bits
757*e5436536SAndroid Build Coastguard Worker                where read. */
758*e5436536SAndroid Build Coastguard Worker             if (loasOffset < 0) {
759*e5436536SAndroid Build Coastguard Worker               err = TRANSPORTDEC_PARSE_ERROR;
760*e5436536SAndroid Build Coastguard Worker             }
761*e5436536SAndroid Build Coastguard Worker           }
762*e5436536SAndroid Build Coastguard Worker         }
763*e5436536SAndroid Build Coastguard Worker       }
764*e5436536SAndroid Build Coastguard Worker       break;
765*e5436536SAndroid Build Coastguard Worker 
766*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
767*e5436536SAndroid Build Coastguard Worker       if (hTp->parser.adts.bs.protection_absent == 0) {
768*e5436536SAndroid Build Coastguard Worker         int offset;
769*e5436536SAndroid Build Coastguard Worker 
770*e5436536SAndroid Build Coastguard Worker         /* Calculate offset to end of AU */
771*e5436536SAndroid Build Coastguard Worker         offset = hTp->parser.adts
772*e5436536SAndroid Build Coastguard Worker                      .rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks -
773*e5436536SAndroid Build Coastguard Worker                                        hTp->numberOfRawDataBlocks]
774*e5436536SAndroid Build Coastguard Worker                  << 3;
775*e5436536SAndroid Build Coastguard Worker         /* CAUTION: The PCE (if available) is declared to be a part of the
776*e5436536SAndroid Build Coastguard Worker          * header! */
777*e5436536SAndroid Build Coastguard Worker         offset -= (INT)hTp->accessUnitAnchor[0] - (INT)FDKgetValidBits(hBs) +
778*e5436536SAndroid Build Coastguard Worker                   16 + hTp->parser.adts.bs.num_pce_bits;
779*e5436536SAndroid Build Coastguard Worker         FDKpushBiDirectional(hBs, offset);
780*e5436536SAndroid Build Coastguard Worker       }
781*e5436536SAndroid Build Coastguard Worker       if (hTp->parser.adts.bs.num_raw_blocks > 0 &&
782*e5436536SAndroid Build Coastguard Worker           hTp->parser.adts.bs.protection_absent == 0) {
783*e5436536SAndroid Build Coastguard Worker         /* Note this CRC read currently happens twice because of
784*e5436536SAndroid Build Coastguard Worker          * transportDec_CrcCheck() */
785*e5436536SAndroid Build Coastguard Worker         hTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16);
786*e5436536SAndroid Build Coastguard Worker       }
787*e5436536SAndroid Build Coastguard Worker       if (hTp->numberOfRawDataBlocks == 0) {
788*e5436536SAndroid Build Coastguard Worker         /* Check global frame length */
789*e5436536SAndroid Build Coastguard Worker         if (hTp->parser.adts.bs.protection_absent == 0) {
790*e5436536SAndroid Build Coastguard Worker           int offset;
791*e5436536SAndroid Build Coastguard Worker 
792*e5436536SAndroid Build Coastguard Worker           offset = (hTp->parser.adts.bs.frame_length * 8 - ADTS_SYNCLENGTH +
793*e5436536SAndroid Build Coastguard Worker                     (INT)FDKgetValidBits(hBs)) -
794*e5436536SAndroid Build Coastguard Worker                    (INT)hTp->globalFramePos;
795*e5436536SAndroid Build Coastguard Worker           if (offset != 0) {
796*e5436536SAndroid Build Coastguard Worker             FDKpushBiDirectional(hBs, offset);
797*e5436536SAndroid Build Coastguard Worker           }
798*e5436536SAndroid Build Coastguard Worker         }
799*e5436536SAndroid Build Coastguard Worker       }
800*e5436536SAndroid Build Coastguard Worker       break;
801*e5436536SAndroid Build Coastguard Worker 
802*e5436536SAndroid Build Coastguard Worker     default:
803*e5436536SAndroid Build Coastguard Worker       break;
804*e5436536SAndroid Build Coastguard Worker   }
805*e5436536SAndroid Build Coastguard Worker 
806*e5436536SAndroid Build Coastguard Worker   return err;
807*e5436536SAndroid Build Coastguard Worker }
808*e5436536SAndroid Build Coastguard Worker 
809*e5436536SAndroid Build Coastguard Worker /**
810*e5436536SAndroid Build Coastguard Worker  * \brief Determine additional buffer fullness contraint due to burst data
811*e5436536SAndroid Build Coastguard Worker  * reception. The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a
812*e5436536SAndroid Build Coastguard Worker  * precondition.
813*e5436536SAndroid Build Coastguard Worker  * \param hTp transport decoder handle.
814*e5436536SAndroid Build Coastguard Worker  * \param bufferFullness the buffer fullness value of the first frame to be
815*e5436536SAndroid Build Coastguard Worker  * decoded.
816*e5436536SAndroid Build Coastguard Worker  * \param bitsAvail the amount of available bits at the end of the first frame
817*e5436536SAndroid Build Coastguard Worker  * to be decoded.
818*e5436536SAndroid Build Coastguard Worker  * \return error code
819*e5436536SAndroid Build Coastguard Worker  */
additionalHoldOffNeeded(HANDLE_TRANSPORTDEC hTp,INT bufferFullness,INT bitsAvail)820*e5436536SAndroid Build Coastguard Worker static TRANSPORTDEC_ERROR additionalHoldOffNeeded(HANDLE_TRANSPORTDEC hTp,
821*e5436536SAndroid Build Coastguard Worker                                                   INT bufferFullness,
822*e5436536SAndroid Build Coastguard Worker                                                   INT bitsAvail) {
823*e5436536SAndroid Build Coastguard Worker   INT checkLengthBits, avgBitsPerFrame;
824*e5436536SAndroid Build Coastguard Worker   INT maxAU; /* maximum number of frames per Master Frame */
825*e5436536SAndroid Build Coastguard Worker   INT samplesPerFrame = hTp->asc->m_samplesPerFrame;
826*e5436536SAndroid Build Coastguard Worker   INT samplingFrequency = (INT)hTp->asc->m_samplingFrequency;
827*e5436536SAndroid Build Coastguard Worker 
828*e5436536SAndroid Build Coastguard Worker   if ((hTp->avgBitRate == 0) || (hTp->burstPeriod == 0)) {
829*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_OK;
830*e5436536SAndroid Build Coastguard Worker   }
831*e5436536SAndroid Build Coastguard Worker   if ((samplesPerFrame == 0) || (samplingFrequency == 0)) {
832*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_NOT_ENOUGH_BITS;
833*e5436536SAndroid Build Coastguard Worker   }
834*e5436536SAndroid Build Coastguard Worker 
835*e5436536SAndroid Build Coastguard Worker   /* One Master Frame is sent every hTp->burstPeriod ms */
836*e5436536SAndroid Build Coastguard Worker   maxAU = hTp->burstPeriod * samplingFrequency + (samplesPerFrame * 1000 - 1);
837*e5436536SAndroid Build Coastguard Worker   maxAU = maxAU / (samplesPerFrame * 1000);
838*e5436536SAndroid Build Coastguard Worker   /* Subtract number of frames which were already held off. */
839*e5436536SAndroid Build Coastguard Worker   maxAU -= hTp->holdOffFrames;
840*e5436536SAndroid Build Coastguard Worker 
841*e5436536SAndroid Build Coastguard Worker   avgBitsPerFrame = hTp->avgBitRate * samplesPerFrame + (samplingFrequency - 1);
842*e5436536SAndroid Build Coastguard Worker   avgBitsPerFrame = avgBitsPerFrame / samplingFrequency;
843*e5436536SAndroid Build Coastguard Worker 
844*e5436536SAndroid Build Coastguard Worker   /* Consider worst case of bufferFullness quantization. */
845*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
846*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADIF:
847*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
848*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
849*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP0:
850*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP1:
851*e5436536SAndroid Build Coastguard Worker       bufferFullness += 31;
852*e5436536SAndroid Build Coastguard Worker       break;
853*e5436536SAndroid Build Coastguard Worker     default: /* added to avoid compiler warning */
854*e5436536SAndroid Build Coastguard Worker       break; /* added to avoid compiler warning */
855*e5436536SAndroid Build Coastguard Worker   }
856*e5436536SAndroid Build Coastguard Worker 
857*e5436536SAndroid Build Coastguard Worker   checkLengthBits = bufferFullness + (maxAU - 1) * avgBitsPerFrame;
858*e5436536SAndroid Build Coastguard Worker 
859*e5436536SAndroid Build Coastguard Worker   /* Check if buffer is big enough to fullfill buffer fullness condition */
860*e5436536SAndroid Build Coastguard Worker   if ((checkLengthBits /*+headerBits*/) > (((8192 * 4) << 3) - 7)) {
861*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_SYNC_ERROR;
862*e5436536SAndroid Build Coastguard Worker   }
863*e5436536SAndroid Build Coastguard Worker 
864*e5436536SAndroid Build Coastguard Worker   if (bitsAvail < checkLengthBits) {
865*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_NOT_ENOUGH_BITS;
866*e5436536SAndroid Build Coastguard Worker   } else {
867*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_OK;
868*e5436536SAndroid Build Coastguard Worker   }
869*e5436536SAndroid Build Coastguard Worker }
870*e5436536SAndroid Build Coastguard Worker 
transportDec_readHeader(HANDLE_TRANSPORTDEC hTp,HANDLE_FDK_BITSTREAM hBs,int syncLength,int ignoreBufferFullness,int * pRawDataBlockLength,int * pfTraverseMoreFrames,int * pSyncLayerFrameBits,int * pfConfigFound,int * pHeaderBits)871*e5436536SAndroid Build Coastguard Worker static TRANSPORTDEC_ERROR transportDec_readHeader(
872*e5436536SAndroid Build Coastguard Worker     HANDLE_TRANSPORTDEC hTp, HANDLE_FDK_BITSTREAM hBs, int syncLength,
873*e5436536SAndroid Build Coastguard Worker     int ignoreBufferFullness, int *pRawDataBlockLength,
874*e5436536SAndroid Build Coastguard Worker     int *pfTraverseMoreFrames, int *pSyncLayerFrameBits, int *pfConfigFound,
875*e5436536SAndroid Build Coastguard Worker     int *pHeaderBits) {
876*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
877*e5436536SAndroid Build Coastguard Worker   int rawDataBlockLength = *pRawDataBlockLength;
878*e5436536SAndroid Build Coastguard Worker   int fTraverseMoreFrames =
879*e5436536SAndroid Build Coastguard Worker       (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0;
880*e5436536SAndroid Build Coastguard Worker   int syncLayerFrameBits =
881*e5436536SAndroid Build Coastguard Worker       (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0;
882*e5436536SAndroid Build Coastguard Worker   int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0;
883*e5436536SAndroid Build Coastguard Worker   int startPos;
884*e5436536SAndroid Build Coastguard Worker 
885*e5436536SAndroid Build Coastguard Worker   startPos = (INT)FDKgetValidBits(hBs);
886*e5436536SAndroid Build Coastguard Worker 
887*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
888*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
889*e5436536SAndroid Build Coastguard Worker       if (hTp->numberOfRawDataBlocks <= 0) {
890*e5436536SAndroid Build Coastguard Worker         int i, errC;
891*e5436536SAndroid Build Coastguard Worker 
892*e5436536SAndroid Build Coastguard Worker         hTp->globalFramePos = FDKgetValidBits(hBs);
893*e5436536SAndroid Build Coastguard Worker 
894*e5436536SAndroid Build Coastguard Worker         UCHAR configChanged = 0;
895*e5436536SAndroid Build Coastguard Worker         UCHAR configMode = AC_CM_DET_CFG_CHANGE;
896*e5436536SAndroid Build Coastguard Worker 
897*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < 2; i++) {
898*e5436536SAndroid Build Coastguard Worker           if (i > 0) {
899*e5436536SAndroid Build Coastguard Worker             FDKpushBack(hBs,
900*e5436536SAndroid Build Coastguard Worker                         (INT)hTp->globalFramePos - (INT)FDKgetValidBits(hBs));
901*e5436536SAndroid Build Coastguard Worker             configMode = AC_CM_ALLOC_MEM;
902*e5436536SAndroid Build Coastguard Worker           }
903*e5436536SAndroid Build Coastguard Worker 
904*e5436536SAndroid Build Coastguard Worker           /* Parse ADTS header */
905*e5436536SAndroid Build Coastguard Worker           err = adtsRead_DecodeHeader(&hTp->parser.adts, &hTp->asc[0], hBs,
906*e5436536SAndroid Build Coastguard Worker                                       ignoreBufferFullness);
907*e5436536SAndroid Build Coastguard Worker           if (err != TRANSPORTDEC_OK) {
908*e5436536SAndroid Build Coastguard Worker             if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) {
909*e5436536SAndroid Build Coastguard Worker               err = TRANSPORTDEC_SYNC_ERROR;
910*e5436536SAndroid Build Coastguard Worker             }
911*e5436536SAndroid Build Coastguard Worker           } else {
912*e5436536SAndroid Build Coastguard Worker             errC = hTp->callbacks.cbUpdateConfig(
913*e5436536SAndroid Build Coastguard Worker                 hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode,
914*e5436536SAndroid Build Coastguard Worker                 &configChanged);
915*e5436536SAndroid Build Coastguard Worker             if (errC != 0) {
916*e5436536SAndroid Build Coastguard Worker               if (errC == TRANSPORTDEC_NEED_TO_RESTART) {
917*e5436536SAndroid Build Coastguard Worker                 err = TRANSPORTDEC_NEED_TO_RESTART;
918*e5436536SAndroid Build Coastguard Worker                 goto bail;
919*e5436536SAndroid Build Coastguard Worker               } else {
920*e5436536SAndroid Build Coastguard Worker                 err = TRANSPORTDEC_SYNC_ERROR;
921*e5436536SAndroid Build Coastguard Worker               }
922*e5436536SAndroid Build Coastguard Worker             } else {
923*e5436536SAndroid Build Coastguard Worker               fConfigFound = 1;
924*e5436536SAndroid Build Coastguard Worker               hTp->numberOfRawDataBlocks =
925*e5436536SAndroid Build Coastguard Worker                   hTp->parser.adts.bs.num_raw_blocks + 1;
926*e5436536SAndroid Build Coastguard Worker             }
927*e5436536SAndroid Build Coastguard Worker           }
928*e5436536SAndroid Build Coastguard Worker 
929*e5436536SAndroid Build Coastguard Worker           if (err == TRANSPORTDEC_OK) {
930*e5436536SAndroid Build Coastguard Worker             if ((i == 0) && configChanged) {
931*e5436536SAndroid Build Coastguard Worker               errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData,
932*e5436536SAndroid Build Coastguard Worker                                               &hTp->asc[0]);
933*e5436536SAndroid Build Coastguard Worker               if (errC != 0) {
934*e5436536SAndroid Build Coastguard Worker                 err = TRANSPORTDEC_PARSE_ERROR;
935*e5436536SAndroid Build Coastguard Worker               }
936*e5436536SAndroid Build Coastguard Worker             }
937*e5436536SAndroid Build Coastguard Worker           }
938*e5436536SAndroid Build Coastguard Worker           /* if an error is detected terminate config parsing to avoid that an
939*e5436536SAndroid Build Coastguard Worker            * invalid config is accepted in the second pass */
940*e5436536SAndroid Build Coastguard Worker           if (err != TRANSPORTDEC_OK) {
941*e5436536SAndroid Build Coastguard Worker             break;
942*e5436536SAndroid Build Coastguard Worker           }
943*e5436536SAndroid Build Coastguard Worker         }
944*e5436536SAndroid Build Coastguard Worker       } else {
945*e5436536SAndroid Build Coastguard Worker         /* Reset CRC because the next bits are the beginning of a
946*e5436536SAndroid Build Coastguard Worker          * raw_data_block() */
947*e5436536SAndroid Build Coastguard Worker         FDKcrcReset(&hTp->parser.adts.crcInfo);
948*e5436536SAndroid Build Coastguard Worker         hTp->parser.adts.bs.num_pce_bits = 0;
949*e5436536SAndroid Build Coastguard Worker       }
950*e5436536SAndroid Build Coastguard Worker       if (err == TRANSPORTDEC_OK) {
951*e5436536SAndroid Build Coastguard Worker         hTp->numberOfRawDataBlocks--;
952*e5436536SAndroid Build Coastguard Worker         rawDataBlockLength = adtsRead_GetRawDataBlockLength(
953*e5436536SAndroid Build Coastguard Worker             &hTp->parser.adts,
954*e5436536SAndroid Build Coastguard Worker             (hTp->parser.adts.bs.num_raw_blocks - hTp->numberOfRawDataBlocks));
955*e5436536SAndroid Build Coastguard Worker         if (rawDataBlockLength <= 0) {
956*e5436536SAndroid Build Coastguard Worker           /* No further frame traversal possible. */
957*e5436536SAndroid Build Coastguard Worker           fTraverseMoreFrames = 0;
958*e5436536SAndroid Build Coastguard Worker         }
959*e5436536SAndroid Build Coastguard Worker         syncLayerFrameBits = (hTp->parser.adts.bs.frame_length << 3) -
960*e5436536SAndroid Build Coastguard Worker                              (startPos - (INT)FDKgetValidBits(hBs)) -
961*e5436536SAndroid Build Coastguard Worker                              syncLength;
962*e5436536SAndroid Build Coastguard Worker         if (syncLayerFrameBits <= 0) {
963*e5436536SAndroid Build Coastguard Worker           err = TRANSPORTDEC_SYNC_ERROR;
964*e5436536SAndroid Build Coastguard Worker         }
965*e5436536SAndroid Build Coastguard Worker       } else {
966*e5436536SAndroid Build Coastguard Worker         hTp->numberOfRawDataBlocks = 0;
967*e5436536SAndroid Build Coastguard Worker       }
968*e5436536SAndroid Build Coastguard Worker       break;
969*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
970*e5436536SAndroid Build Coastguard Worker       if (hTp->numberOfRawDataBlocks <= 0) {
971*e5436536SAndroid Build Coastguard Worker         syncLayerFrameBits = (INT)FDKreadBits(hBs, 13);
972*e5436536SAndroid Build Coastguard Worker         hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits;
973*e5436536SAndroid Build Coastguard Worker         syncLayerFrameBits <<= 3;
974*e5436536SAndroid Build Coastguard Worker       }
975*e5436536SAndroid Build Coastguard Worker       FDK_FALLTHROUGH;
976*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP1:
977*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP0:
978*e5436536SAndroid Build Coastguard Worker       if (hTp->numberOfRawDataBlocks <= 0) {
979*e5436536SAndroid Build Coastguard Worker         hTp->globalFramePos = FDKgetValidBits(hBs);
980*e5436536SAndroid Build Coastguard Worker 
981*e5436536SAndroid Build Coastguard Worker         err = CLatmDemux_Read(hBs, &hTp->parser.latm, hTp->transportFmt,
982*e5436536SAndroid Build Coastguard Worker                               &hTp->callbacks, hTp->asc, &fConfigFound,
983*e5436536SAndroid Build Coastguard Worker                               ignoreBufferFullness);
984*e5436536SAndroid Build Coastguard Worker 
985*e5436536SAndroid Build Coastguard Worker         if (err != TRANSPORTDEC_OK) {
986*e5436536SAndroid Build Coastguard Worker           if ((err != TRANSPORTDEC_NOT_ENOUGH_BITS) &&
987*e5436536SAndroid Build Coastguard Worker               !TPDEC_IS_FATAL_ERROR(err)) {
988*e5436536SAndroid Build Coastguard Worker             err = TRANSPORTDEC_SYNC_ERROR;
989*e5436536SAndroid Build Coastguard Worker           }
990*e5436536SAndroid Build Coastguard Worker         } else {
991*e5436536SAndroid Build Coastguard Worker           hTp->numberOfRawDataBlocks =
992*e5436536SAndroid Build Coastguard Worker               CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
993*e5436536SAndroid Build Coastguard Worker           if (hTp->transportFmt == TT_MP4_LOAS) {
994*e5436536SAndroid Build Coastguard Worker             syncLayerFrameBits -= startPos - (INT)FDKgetValidBits(hBs) - (13);
995*e5436536SAndroid Build Coastguard Worker             if (syncLayerFrameBits <= 0) {
996*e5436536SAndroid Build Coastguard Worker               err = TRANSPORTDEC_SYNC_ERROR;
997*e5436536SAndroid Build Coastguard Worker             }
998*e5436536SAndroid Build Coastguard Worker           }
999*e5436536SAndroid Build Coastguard Worker         }
1000*e5436536SAndroid Build Coastguard Worker       } else {
1001*e5436536SAndroid Build Coastguard Worker         err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm);
1002*e5436536SAndroid Build Coastguard Worker         if (err != TRANSPORTDEC_OK) {
1003*e5436536SAndroid Build Coastguard Worker           err = TRANSPORTDEC_SYNC_ERROR;
1004*e5436536SAndroid Build Coastguard Worker         }
1005*e5436536SAndroid Build Coastguard Worker       }
1006*e5436536SAndroid Build Coastguard Worker       if (err == TRANSPORTDEC_OK) {
1007*e5436536SAndroid Build Coastguard Worker         int layer;
1008*e5436536SAndroid Build Coastguard Worker         rawDataBlockLength = 0;
1009*e5436536SAndroid Build Coastguard Worker         for (layer = 0;
1010*e5436536SAndroid Build Coastguard Worker              layer < (int)CLatmDemux_GetNrOfLayers(&hTp->parser.latm, 0);
1011*e5436536SAndroid Build Coastguard Worker              layer += 1) {
1012*e5436536SAndroid Build Coastguard Worker           rawDataBlockLength +=
1013*e5436536SAndroid Build Coastguard Worker               CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm, 0, layer);
1014*e5436536SAndroid Build Coastguard Worker         }
1015*e5436536SAndroid Build Coastguard Worker         hTp->numberOfRawDataBlocks--;
1016*e5436536SAndroid Build Coastguard Worker       } else {
1017*e5436536SAndroid Build Coastguard Worker         hTp->numberOfRawDataBlocks = 0;
1018*e5436536SAndroid Build Coastguard Worker       }
1019*e5436536SAndroid Build Coastguard Worker       break;
1020*e5436536SAndroid Build Coastguard Worker     default: { syncLayerFrameBits = 0; } break;
1021*e5436536SAndroid Build Coastguard Worker   }
1022*e5436536SAndroid Build Coastguard Worker 
1023*e5436536SAndroid Build Coastguard Worker bail:
1024*e5436536SAndroid Build Coastguard Worker 
1025*e5436536SAndroid Build Coastguard Worker   *pRawDataBlockLength = rawDataBlockLength;
1026*e5436536SAndroid Build Coastguard Worker 
1027*e5436536SAndroid Build Coastguard Worker   if (pHeaderBits != NULL) {
1028*e5436536SAndroid Build Coastguard Worker     *pHeaderBits += startPos - (INT)FDKgetValidBits(hBs);
1029*e5436536SAndroid Build Coastguard Worker   }
1030*e5436536SAndroid Build Coastguard Worker 
1031*e5436536SAndroid Build Coastguard Worker   for (int i = 0; i < (1 * 1); i++) {
1032*e5436536SAndroid Build Coastguard Worker     /* If parsing error while config found, clear ctrlCFGChange-struct */
1033*e5436536SAndroid Build Coastguard Worker     if (hTp->ctrlCFGChange[i].cfgChanged && err != TRANSPORTDEC_OK) {
1034*e5436536SAndroid Build Coastguard Worker       hTp->numberOfRawDataBlocks = 0;
1035*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[i].flushCnt = 0;
1036*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[i].flushStatus = TPDEC_FLUSH_OFF;
1037*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[i].buildUpCnt = 0;
1038*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[i].buildUpStatus = TPDEC_BUILD_UP_OFF;
1039*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[i].cfgChanged = 0;
1040*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[i].contentChanged = 0;
1041*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[i].forceCfgChange = 0;
1042*e5436536SAndroid Build Coastguard Worker 
1043*e5436536SAndroid Build Coastguard Worker       hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData,
1044*e5436536SAndroid Build Coastguard Worker                                      &hTp->ctrlCFGChange[i]);
1045*e5436536SAndroid Build Coastguard Worker     }
1046*e5436536SAndroid Build Coastguard Worker   }
1047*e5436536SAndroid Build Coastguard Worker 
1048*e5436536SAndroid Build Coastguard Worker   if (pfConfigFound != NULL) {
1049*e5436536SAndroid Build Coastguard Worker     *pfConfigFound = fConfigFound;
1050*e5436536SAndroid Build Coastguard Worker   }
1051*e5436536SAndroid Build Coastguard Worker 
1052*e5436536SAndroid Build Coastguard Worker   if (pfTraverseMoreFrames != NULL) {
1053*e5436536SAndroid Build Coastguard Worker     *pfTraverseMoreFrames = fTraverseMoreFrames;
1054*e5436536SAndroid Build Coastguard Worker   }
1055*e5436536SAndroid Build Coastguard Worker   if (pSyncLayerFrameBits != NULL) {
1056*e5436536SAndroid Build Coastguard Worker     *pSyncLayerFrameBits = syncLayerFrameBits;
1057*e5436536SAndroid Build Coastguard Worker   }
1058*e5436536SAndroid Build Coastguard Worker 
1059*e5436536SAndroid Build Coastguard Worker   return err;
1060*e5436536SAndroid Build Coastguard Worker }
1061*e5436536SAndroid Build Coastguard Worker 
1062*e5436536SAndroid Build Coastguard Worker /* How many bits to advance for synchronization search. */
1063*e5436536SAndroid Build Coastguard Worker #define TPDEC_SYNCSKIP 8
1064*e5436536SAndroid Build Coastguard Worker 
synchronization(HANDLE_TRANSPORTDEC hTp,INT * pHeaderBits)1065*e5436536SAndroid Build Coastguard Worker static TRANSPORTDEC_ERROR synchronization(HANDLE_TRANSPORTDEC hTp,
1066*e5436536SAndroid Build Coastguard Worker                                           INT *pHeaderBits) {
1067*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK;
1068*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
1069*e5436536SAndroid Build Coastguard Worker 
1070*e5436536SAndroid Build Coastguard Worker   INT syncLayerFrameBits = 0; /* Length of sync layer frame (i.e. LOAS) */
1071*e5436536SAndroid Build Coastguard Worker   INT rawDataBlockLength = 0, rawDataBlockLengthPrevious;
1072*e5436536SAndroid Build Coastguard Worker   INT totalBits;
1073*e5436536SAndroid Build Coastguard Worker   INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious;
1074*e5436536SAndroid Build Coastguard Worker   INT numFramesTraversed = 0, fTraverseMoreFrames,
1075*e5436536SAndroid Build Coastguard Worker       fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1;
1076*e5436536SAndroid Build Coastguard Worker   INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious,
1077*e5436536SAndroid Build Coastguard Worker       globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0;
1078*e5436536SAndroid Build Coastguard Worker   INT ignoreBufferFullness =
1079*e5436536SAndroid Build Coastguard Worker       hTp->flags &
1080*e5436536SAndroid Build Coastguard Worker       (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS | TPDEC_SYNCOK);
1081*e5436536SAndroid Build Coastguard Worker   UINT endTpFrameBitsPrevious = 0;
1082*e5436536SAndroid Build Coastguard Worker 
1083*e5436536SAndroid Build Coastguard Worker   /* Synch parameters */
1084*e5436536SAndroid Build Coastguard Worker   INT syncLength; /* Length of sync word in bits */
1085*e5436536SAndroid Build Coastguard Worker   UINT syncWord;  /* Sync word to be found */
1086*e5436536SAndroid Build Coastguard Worker   UINT syncMask;  /* Mask for sync word (for adding one bit, so comprising one
1087*e5436536SAndroid Build Coastguard Worker                      bit less) */
1088*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1);
1089*e5436536SAndroid Build Coastguard Worker 
1090*e5436536SAndroid Build Coastguard Worker   totalBits = (INT)FDKgetValidBits(hBs);
1091*e5436536SAndroid Build Coastguard Worker 
1092*e5436536SAndroid Build Coastguard Worker   if (totalBits <= 0) {
1093*e5436536SAndroid Build Coastguard Worker     err = TRANSPORTDEC_NOT_ENOUGH_BITS;
1094*e5436536SAndroid Build Coastguard Worker     goto bail;
1095*e5436536SAndroid Build Coastguard Worker   }
1096*e5436536SAndroid Build Coastguard Worker 
1097*e5436536SAndroid Build Coastguard Worker   fTraverseMoreFrames =
1098*e5436536SAndroid Build Coastguard Worker       (hTp->flags & (TPDEC_MINIMIZE_DELAY | TPDEC_EARLY_CONFIG)) &&
1099*e5436536SAndroid Build Coastguard Worker       !(hTp->flags & TPDEC_SYNCOK);
1100*e5436536SAndroid Build Coastguard Worker 
1101*e5436536SAndroid Build Coastguard Worker   /* Set transport specific sync parameters */
1102*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
1103*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
1104*e5436536SAndroid Build Coastguard Worker       syncWord = ADTS_SYNCWORD;
1105*e5436536SAndroid Build Coastguard Worker       syncLength = ADTS_SYNCLENGTH;
1106*e5436536SAndroid Build Coastguard Worker       break;
1107*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
1108*e5436536SAndroid Build Coastguard Worker       syncWord = 0x2B7;
1109*e5436536SAndroid Build Coastguard Worker       syncLength = 11;
1110*e5436536SAndroid Build Coastguard Worker       break;
1111*e5436536SAndroid Build Coastguard Worker     default:
1112*e5436536SAndroid Build Coastguard Worker       syncWord = 0;
1113*e5436536SAndroid Build Coastguard Worker       syncLength = 0;
1114*e5436536SAndroid Build Coastguard Worker       break;
1115*e5436536SAndroid Build Coastguard Worker   }
1116*e5436536SAndroid Build Coastguard Worker 
1117*e5436536SAndroid Build Coastguard Worker   syncMask = (1 << syncLength) - 1;
1118*e5436536SAndroid Build Coastguard Worker 
1119*e5436536SAndroid Build Coastguard Worker   do {
1120*e5436536SAndroid Build Coastguard Worker     INT bitsAvail = 0;   /* Bits available in bitstream buffer    */
1121*e5436536SAndroid Build Coastguard Worker     INT checkLengthBits; /* Helper to check remaining bits and buffer boundaries
1122*e5436536SAndroid Build Coastguard Worker                           */
1123*e5436536SAndroid Build Coastguard Worker     UINT synch;          /* Current sync word read from bitstream */
1124*e5436536SAndroid Build Coastguard Worker 
1125*e5436536SAndroid Build Coastguard Worker     headerBitsPrevious = headerBits;
1126*e5436536SAndroid Build Coastguard Worker 
1127*e5436536SAndroid Build Coastguard Worker     bitsAvail = (INT)FDKgetValidBits(hBs);
1128*e5436536SAndroid Build Coastguard Worker 
1129*e5436536SAndroid Build Coastguard Worker     if (hTp->numberOfRawDataBlocks == 0) {
1130*e5436536SAndroid Build Coastguard Worker       /* search synchword */
1131*e5436536SAndroid Build Coastguard Worker 
1132*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT((bitsAvail % TPDEC_SYNCSKIP) == 0);
1133*e5436536SAndroid Build Coastguard Worker 
1134*e5436536SAndroid Build Coastguard Worker       if ((bitsAvail - syncLength) < TPDEC_SYNCSKIP) {
1135*e5436536SAndroid Build Coastguard Worker         err = TRANSPORTDEC_NOT_ENOUGH_BITS;
1136*e5436536SAndroid Build Coastguard Worker         headerBits = 0;
1137*e5436536SAndroid Build Coastguard Worker       } else {
1138*e5436536SAndroid Build Coastguard Worker         synch = FDKreadBits(hBs, syncLength);
1139*e5436536SAndroid Build Coastguard Worker 
1140*e5436536SAndroid Build Coastguard Worker         if (!(hTp->flags & TPDEC_SYNCOK)) {
1141*e5436536SAndroid Build Coastguard Worker           for (; (bitsAvail - syncLength) >= TPDEC_SYNCSKIP;
1142*e5436536SAndroid Build Coastguard Worker                bitsAvail -= TPDEC_SYNCSKIP) {
1143*e5436536SAndroid Build Coastguard Worker             if (synch == syncWord) {
1144*e5436536SAndroid Build Coastguard Worker               break;
1145*e5436536SAndroid Build Coastguard Worker             }
1146*e5436536SAndroid Build Coastguard Worker             synch = ((synch << TPDEC_SYNCSKIP) & syncMask) |
1147*e5436536SAndroid Build Coastguard Worker                     FDKreadBits(hBs, TPDEC_SYNCSKIP);
1148*e5436536SAndroid Build Coastguard Worker           }
1149*e5436536SAndroid Build Coastguard Worker         }
1150*e5436536SAndroid Build Coastguard Worker         if (synch != syncWord) {
1151*e5436536SAndroid Build Coastguard Worker           /* No correct syncword found. */
1152*e5436536SAndroid Build Coastguard Worker           err = TRANSPORTDEC_SYNC_ERROR;
1153*e5436536SAndroid Build Coastguard Worker         } else {
1154*e5436536SAndroid Build Coastguard Worker           err = TRANSPORTDEC_OK;
1155*e5436536SAndroid Build Coastguard Worker         }
1156*e5436536SAndroid Build Coastguard Worker         headerBits = syncLength;
1157*e5436536SAndroid Build Coastguard Worker       }
1158*e5436536SAndroid Build Coastguard Worker     } else {
1159*e5436536SAndroid Build Coastguard Worker       headerBits = 0;
1160*e5436536SAndroid Build Coastguard Worker     }
1161*e5436536SAndroid Build Coastguard Worker 
1162*e5436536SAndroid Build Coastguard Worker     /* Save previous raw data block data */
1163*e5436536SAndroid Build Coastguard Worker     rawDataBlockLengthPrevious = rawDataBlockLength;
1164*e5436536SAndroid Build Coastguard Worker     numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks;
1165*e5436536SAndroid Build Coastguard Worker 
1166*e5436536SAndroid Build Coastguard Worker     /* Parse transport header (raw data block granularity) */
1167*e5436536SAndroid Build Coastguard Worker 
1168*e5436536SAndroid Build Coastguard Worker     if (err == TRANSPORTDEC_OK) {
1169*e5436536SAndroid Build Coastguard Worker       err = transportDec_readHeader(hTp, hBs, syncLength, ignoreBufferFullness,
1170*e5436536SAndroid Build Coastguard Worker                                     &rawDataBlockLength, &fTraverseMoreFrames,
1171*e5436536SAndroid Build Coastguard Worker                                     &syncLayerFrameBits, &fConfigFound,
1172*e5436536SAndroid Build Coastguard Worker                                     &headerBits);
1173*e5436536SAndroid Build Coastguard Worker       if (headerBits > bitsAvail) {
1174*e5436536SAndroid Build Coastguard Worker         err = (headerBits < (INT)hBs->hBitBuf.bufBits)
1175*e5436536SAndroid Build Coastguard Worker                   ? TRANSPORTDEC_NOT_ENOUGH_BITS
1176*e5436536SAndroid Build Coastguard Worker                   : TRANSPORTDEC_SYNC_ERROR;
1177*e5436536SAndroid Build Coastguard Worker       }
1178*e5436536SAndroid Build Coastguard Worker       if (TPDEC_IS_FATAL_ERROR(err)) {
1179*e5436536SAndroid Build Coastguard Worker         /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead
1180*e5436536SAndroid Build Coastguard Worker          * next time. Ensure that the bit amount lands at a multiple of
1181*e5436536SAndroid Build Coastguard Worker          * TPDEC_SYNCSKIP. */
1182*e5436536SAndroid Build Coastguard Worker         FDKpushBiDirectional(
1183*e5436536SAndroid Build Coastguard Worker             hBs, -headerBits + TPDEC_SYNCSKIP + (bitsAvail % TPDEC_SYNCSKIP));
1184*e5436536SAndroid Build Coastguard Worker 
1185*e5436536SAndroid Build Coastguard Worker         goto bail;
1186*e5436536SAndroid Build Coastguard Worker       }
1187*e5436536SAndroid Build Coastguard Worker     }
1188*e5436536SAndroid Build Coastguard Worker 
1189*e5436536SAndroid Build Coastguard Worker     bitsAvail -= headerBits;
1190*e5436536SAndroid Build Coastguard Worker 
1191*e5436536SAndroid Build Coastguard Worker     checkLengthBits = syncLayerFrameBits;
1192*e5436536SAndroid Build Coastguard Worker 
1193*e5436536SAndroid Build Coastguard Worker     /* Check if the whole frame would fit the bitstream buffer */
1194*e5436536SAndroid Build Coastguard Worker     if (err == TRANSPORTDEC_OK) {
1195*e5436536SAndroid Build Coastguard Worker       if ((checkLengthBits + headerBits) > (((8192 * 4) << 3) - 7)) {
1196*e5436536SAndroid Build Coastguard Worker         /* We assume that the size of the transport bit buffer has been
1197*e5436536SAndroid Build Coastguard Worker            chosen to meet all system requirements, thus this condition
1198*e5436536SAndroid Build Coastguard Worker            is considered a synchronisation error. */
1199*e5436536SAndroid Build Coastguard Worker         err = TRANSPORTDEC_SYNC_ERROR;
1200*e5436536SAndroid Build Coastguard Worker       } else {
1201*e5436536SAndroid Build Coastguard Worker         if (bitsAvail < checkLengthBits) {
1202*e5436536SAndroid Build Coastguard Worker           err = TRANSPORTDEC_NOT_ENOUGH_BITS;
1203*e5436536SAndroid Build Coastguard Worker         }
1204*e5436536SAndroid Build Coastguard Worker       }
1205*e5436536SAndroid Build Coastguard Worker     }
1206*e5436536SAndroid Build Coastguard Worker 
1207*e5436536SAndroid Build Coastguard Worker     if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
1208*e5436536SAndroid Build Coastguard Worker       break;
1209*e5436536SAndroid Build Coastguard Worker     }
1210*e5436536SAndroid Build Coastguard Worker 
1211*e5436536SAndroid Build Coastguard Worker     if (err == TRANSPORTDEC_SYNC_ERROR) {
1212*e5436536SAndroid Build Coastguard Worker       int bits;
1213*e5436536SAndroid Build Coastguard Worker 
1214*e5436536SAndroid Build Coastguard Worker       /* Enforce re-sync of transport headers. */
1215*e5436536SAndroid Build Coastguard Worker       hTp->numberOfRawDataBlocks = 0;
1216*e5436536SAndroid Build Coastguard Worker 
1217*e5436536SAndroid Build Coastguard Worker       /* Ensure that the bit amount lands at a multiple of TPDEC_SYNCSKIP */
1218*e5436536SAndroid Build Coastguard Worker       bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP;
1219*e5436536SAndroid Build Coastguard Worker       /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead
1220*e5436536SAndroid Build Coastguard Worker        * next time. */
1221*e5436536SAndroid Build Coastguard Worker       FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits);
1222*e5436536SAndroid Build Coastguard Worker       headerBits = 0;
1223*e5436536SAndroid Build Coastguard Worker     }
1224*e5436536SAndroid Build Coastguard Worker 
1225*e5436536SAndroid Build Coastguard Worker     /* Frame traversal */
1226*e5436536SAndroid Build Coastguard Worker     if (fTraverseMoreFrames) {
1227*e5436536SAndroid Build Coastguard Worker       /* Save parser context for early config discovery "rewind all frames" */
1228*e5436536SAndroid Build Coastguard Worker       if ((hTp->flags & TPDEC_EARLY_CONFIG) &&
1229*e5436536SAndroid Build Coastguard Worker           !(hTp->flags & TPDEC_MINIMIZE_DELAY)) {
1230*e5436536SAndroid Build Coastguard Worker         /* ignore buffer fullness if just traversing additional frames for ECD
1231*e5436536SAndroid Build Coastguard Worker          */
1232*e5436536SAndroid Build Coastguard Worker         ignoreBufferFullness = 1;
1233*e5436536SAndroid Build Coastguard Worker 
1234*e5436536SAndroid Build Coastguard Worker         /* Save context in order to return later */
1235*e5436536SAndroid Build Coastguard Worker         if (err == TRANSPORTDEC_OK && startPosFirstFrame == -1) {
1236*e5436536SAndroid Build Coastguard Worker           startPosFirstFrame = FDKgetValidBits(hBs);
1237*e5436536SAndroid Build Coastguard Worker           numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks;
1238*e5436536SAndroid Build Coastguard Worker           globalFramePosFirstFrame = hTp->globalFramePos;
1239*e5436536SAndroid Build Coastguard Worker           rawDataBlockLengthFirstFrame = rawDataBlockLength;
1240*e5436536SAndroid Build Coastguard Worker           headerBitsFirstFrame = headerBits;
1241*e5436536SAndroid Build Coastguard Worker           errFirstFrame = err;
1242*e5436536SAndroid Build Coastguard Worker           FDKmemcpy(contextFirstFrame, &hTp->parser,
1243*e5436536SAndroid Build Coastguard Worker                     sizeof(transportdec_parser_t));
1244*e5436536SAndroid Build Coastguard Worker         }
1245*e5436536SAndroid Build Coastguard Worker 
1246*e5436536SAndroid Build Coastguard Worker         /* Break when config was found or it is not possible anymore to find a
1247*e5436536SAndroid Build Coastguard Worker          * config */
1248*e5436536SAndroid Build Coastguard Worker         if (startPosFirstFrame != -1 &&
1249*e5436536SAndroid Build Coastguard Worker             (fConfigFound || err != TRANSPORTDEC_OK)) {
1250*e5436536SAndroid Build Coastguard Worker           /* In case of ECD and sync error, do not rewind anywhere. */
1251*e5436536SAndroid Build Coastguard Worker           if (err == TRANSPORTDEC_SYNC_ERROR) {
1252*e5436536SAndroid Build Coastguard Worker             startPosFirstFrame = -1;
1253*e5436536SAndroid Build Coastguard Worker             fConfigFound = 0;
1254*e5436536SAndroid Build Coastguard Worker             numFramesTraversed = 0;
1255*e5436536SAndroid Build Coastguard Worker           }
1256*e5436536SAndroid Build Coastguard Worker           break;
1257*e5436536SAndroid Build Coastguard Worker         }
1258*e5436536SAndroid Build Coastguard Worker       }
1259*e5436536SAndroid Build Coastguard Worker 
1260*e5436536SAndroid Build Coastguard Worker       if (err == TRANSPORTDEC_OK) {
1261*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, rawDataBlockLength);
1262*e5436536SAndroid Build Coastguard Worker         numFramesTraversed++;
1263*e5436536SAndroid Build Coastguard Worker         endTpFrameBitsPrevious = (INT)FDKgetValidBits(hBs);
1264*e5436536SAndroid Build Coastguard Worker         /* Ignore error here itentionally. */
1265*e5436536SAndroid Build Coastguard Worker         transportDec_AdjustEndOfAccessUnit(hTp);
1266*e5436536SAndroid Build Coastguard Worker         endTpFrameBitsPrevious -= FDKgetValidBits(hBs);
1267*e5436536SAndroid Build Coastguard Worker       }
1268*e5436536SAndroid Build Coastguard Worker     }
1269*e5436536SAndroid Build Coastguard Worker   } while (fTraverseMoreFrames ||
1270*e5436536SAndroid Build Coastguard Worker            (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK)));
1271*e5436536SAndroid Build Coastguard Worker 
1272*e5436536SAndroid Build Coastguard Worker   /* Restore context in case of ECD frame traversal */
1273*e5436536SAndroid Build Coastguard Worker   if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) {
1274*e5436536SAndroid Build Coastguard Worker     FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame);
1275*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t));
1276*e5436536SAndroid Build Coastguard Worker     hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame;
1277*e5436536SAndroid Build Coastguard Worker     hTp->globalFramePos = globalFramePosFirstFrame;
1278*e5436536SAndroid Build Coastguard Worker     rawDataBlockLength = rawDataBlockLengthFirstFrame;
1279*e5436536SAndroid Build Coastguard Worker     headerBits = headerBitsFirstFrame;
1280*e5436536SAndroid Build Coastguard Worker     err = errFirstFrame;
1281*e5436536SAndroid Build Coastguard Worker     numFramesTraversed = 0;
1282*e5436536SAndroid Build Coastguard Worker   }
1283*e5436536SAndroid Build Coastguard Worker 
1284*e5436536SAndroid Build Coastguard Worker   /* Additional burst data mode buffer fullness check. */
1285*e5436536SAndroid Build Coastguard Worker   if (!(hTp->flags & (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS |
1286*e5436536SAndroid Build Coastguard Worker                       TPDEC_SYNCOK)) &&
1287*e5436536SAndroid Build Coastguard Worker       err == TRANSPORTDEC_OK) {
1288*e5436536SAndroid Build Coastguard Worker     err =
1289*e5436536SAndroid Build Coastguard Worker         additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp),
1290*e5436536SAndroid Build Coastguard Worker                                 (INT)FDKgetValidBits(hBs) - syncLayerFrameBits);
1291*e5436536SAndroid Build Coastguard Worker     if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
1292*e5436536SAndroid Build Coastguard Worker       hTp->holdOffFrames++;
1293*e5436536SAndroid Build Coastguard Worker     }
1294*e5436536SAndroid Build Coastguard Worker   }
1295*e5436536SAndroid Build Coastguard Worker 
1296*e5436536SAndroid Build Coastguard Worker   /* Rewind for retry because of not enough bits */
1297*e5436536SAndroid Build Coastguard Worker   if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) {
1298*e5436536SAndroid Build Coastguard Worker     FDKpushBack(hBs, headerBits);
1299*e5436536SAndroid Build Coastguard Worker     hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious;
1300*e5436536SAndroid Build Coastguard Worker     headerBits = 0;
1301*e5436536SAndroid Build Coastguard Worker     rawDataBlockLength = rawDataBlockLengthPrevious;
1302*e5436536SAndroid Build Coastguard Worker   } else {
1303*e5436536SAndroid Build Coastguard Worker     /* reset hold off frame counter */
1304*e5436536SAndroid Build Coastguard Worker     hTp->holdOffFrames = 0;
1305*e5436536SAndroid Build Coastguard Worker   }
1306*e5436536SAndroid Build Coastguard Worker 
1307*e5436536SAndroid Build Coastguard Worker   /* Return to last good frame in case of frame traversal but not ECD. */
1308*e5436536SAndroid Build Coastguard Worker   if (numFramesTraversed > 0) {
1309*e5436536SAndroid Build Coastguard Worker     FDKpushBack(hBs, rawDataBlockLengthPrevious + endTpFrameBitsPrevious);
1310*e5436536SAndroid Build Coastguard Worker     if (err != TRANSPORTDEC_OK) {
1311*e5436536SAndroid Build Coastguard Worker       hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious;
1312*e5436536SAndroid Build Coastguard Worker       headerBits = headerBitsPrevious;
1313*e5436536SAndroid Build Coastguard Worker       rawDataBlockLength = rawDataBlockLengthPrevious;
1314*e5436536SAndroid Build Coastguard Worker     }
1315*e5436536SAndroid Build Coastguard Worker     err = TRANSPORTDEC_OK;
1316*e5436536SAndroid Build Coastguard Worker   }
1317*e5436536SAndroid Build Coastguard Worker 
1318*e5436536SAndroid Build Coastguard Worker bail:
1319*e5436536SAndroid Build Coastguard Worker   hTp->auLength[0] = rawDataBlockLength;
1320*e5436536SAndroid Build Coastguard Worker 
1321*e5436536SAndroid Build Coastguard Worker   /* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, where the bit
1322*e5436536SAndroid Build Coastguard Worker      buffer is already full, or no new burst packet fits. Recover by advancing
1323*e5436536SAndroid Build Coastguard Worker      the bit buffer. */
1324*e5436536SAndroid Build Coastguard Worker   if ((totalBits > 0) && (TRANSPORTDEC_NOT_ENOUGH_BITS == err) &&
1325*e5436536SAndroid Build Coastguard Worker       (FDKgetValidBits(hBs) >=
1326*e5436536SAndroid Build Coastguard Worker        (((8192 * 4) * 8 - ((hTp->avgBitRate * hTp->burstPeriod) / 1000)) -
1327*e5436536SAndroid Build Coastguard Worker         7))) {
1328*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, TPDEC_SYNCSKIP);
1329*e5436536SAndroid Build Coastguard Worker     err = TRANSPORTDEC_SYNC_ERROR;
1330*e5436536SAndroid Build Coastguard Worker   }
1331*e5436536SAndroid Build Coastguard Worker 
1332*e5436536SAndroid Build Coastguard Worker   if (err == TRANSPORTDEC_OK) {
1333*e5436536SAndroid Build Coastguard Worker     hTp->flags |= TPDEC_SYNCOK;
1334*e5436536SAndroid Build Coastguard Worker   }
1335*e5436536SAndroid Build Coastguard Worker 
1336*e5436536SAndroid Build Coastguard Worker   if (fConfigFound) {
1337*e5436536SAndroid Build Coastguard Worker     hTp->flags |= TPDEC_CONFIG_FOUND;
1338*e5436536SAndroid Build Coastguard Worker   }
1339*e5436536SAndroid Build Coastguard Worker 
1340*e5436536SAndroid Build Coastguard Worker   if (pHeaderBits != NULL) {
1341*e5436536SAndroid Build Coastguard Worker     *pHeaderBits = headerBits;
1342*e5436536SAndroid Build Coastguard Worker   }
1343*e5436536SAndroid Build Coastguard Worker 
1344*e5436536SAndroid Build Coastguard Worker   if (err == TRANSPORTDEC_SYNC_ERROR) {
1345*e5436536SAndroid Build Coastguard Worker     hTp->flags &= ~TPDEC_SYNCOK;
1346*e5436536SAndroid Build Coastguard Worker   }
1347*e5436536SAndroid Build Coastguard Worker 
1348*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(contextFirstFrame, transportdec_parser_t, 1);
1349*e5436536SAndroid Build Coastguard Worker 
1350*e5436536SAndroid Build Coastguard Worker   return err;
1351*e5436536SAndroid Build Coastguard Worker }
1352*e5436536SAndroid Build Coastguard Worker 
1353*e5436536SAndroid Build Coastguard Worker /**
1354*e5436536SAndroid Build Coastguard Worker  * \brief Synchronize to stream and estimate the amount of missing access units
1355*e5436536SAndroid Build Coastguard Worker  * due to a current synchronization error in case of constant average bit rate.
1356*e5436536SAndroid Build Coastguard Worker  */
transportDec_readStream(HANDLE_TRANSPORTDEC hTp,const UINT layer)1357*e5436536SAndroid Build Coastguard Worker static TRANSPORTDEC_ERROR transportDec_readStream(HANDLE_TRANSPORTDEC hTp,
1358*e5436536SAndroid Build Coastguard Worker                                                   const UINT layer) {
1359*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK;
1360*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[layer];
1361*e5436536SAndroid Build Coastguard Worker 
1362*e5436536SAndroid Build Coastguard Worker   INT headerBits;
1363*e5436536SAndroid Build Coastguard Worker   INT bitDistance, bfDelta;
1364*e5436536SAndroid Build Coastguard Worker 
1365*e5436536SAndroid Build Coastguard Worker   /* Obtain distance to next synch word */
1366*e5436536SAndroid Build Coastguard Worker   bitDistance = (INT)FDKgetValidBits(hBs);
1367*e5436536SAndroid Build Coastguard Worker   error = synchronization(hTp, &headerBits);
1368*e5436536SAndroid Build Coastguard Worker   bitDistance -= (INT)FDKgetValidBits(hBs);
1369*e5436536SAndroid Build Coastguard Worker 
1370*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(bitDistance >= 0);
1371*e5436536SAndroid Build Coastguard Worker 
1372*e5436536SAndroid Build Coastguard Worker   INT nAU = -1;
1373*e5436536SAndroid Build Coastguard Worker 
1374*e5436536SAndroid Build Coastguard Worker   if (error == TRANSPORTDEC_SYNC_ERROR ||
1375*e5436536SAndroid Build Coastguard Worker       (hTp->flags & TPDEC_LOST_FRAMES_PENDING)) {
1376*e5436536SAndroid Build Coastguard Worker     /* Check if estimating lost access units is feasible. */
1377*e5436536SAndroid Build Coastguard Worker     if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 &&
1378*e5436536SAndroid Build Coastguard Worker         hTp->asc[0].m_samplingFrequency > 0) {
1379*e5436536SAndroid Build Coastguard Worker       if (error == TRANSPORTDEC_OK) {
1380*e5436536SAndroid Build Coastguard Worker         int aj;
1381*e5436536SAndroid Build Coastguard Worker 
1382*e5436536SAndroid Build Coastguard Worker         aj = transportDec_GetBufferFullness(hTp);
1383*e5436536SAndroid Build Coastguard Worker         if (aj > 0) {
1384*e5436536SAndroid Build Coastguard Worker           bfDelta = aj;
1385*e5436536SAndroid Build Coastguard Worker         } else {
1386*e5436536SAndroid Build Coastguard Worker           bfDelta = 0;
1387*e5436536SAndroid Build Coastguard Worker         }
1388*e5436536SAndroid Build Coastguard Worker         /* sync was ok: last of a series of bad access units. */
1389*e5436536SAndroid Build Coastguard Worker         hTp->flags &= ~TPDEC_LOST_FRAMES_PENDING;
1390*e5436536SAndroid Build Coastguard Worker         /* Add up bitDistance until end of the current frame. Later we substract
1391*e5436536SAndroid Build Coastguard Worker            this frame from the grand total, since this current successfully
1392*e5436536SAndroid Build Coastguard Worker            synchronized frame should not be skipped of course; but it must be
1393*e5436536SAndroid Build Coastguard Worker            accounted into the bufferfulness math. */
1394*e5436536SAndroid Build Coastguard Worker         bitDistance += hTp->auLength[0];
1395*e5436536SAndroid Build Coastguard Worker       } else {
1396*e5436536SAndroid Build Coastguard Worker         if (!(hTp->flags & TPDEC_LOST_FRAMES_PENDING)) {
1397*e5436536SAndroid Build Coastguard Worker           /* sync not ok: one of many bad access units. */
1398*e5436536SAndroid Build Coastguard Worker           hTp->flags |= TPDEC_LOST_FRAMES_PENDING;
1399*e5436536SAndroid Build Coastguard Worker           bfDelta = -(INT)hTp->lastValidBufferFullness;
1400*e5436536SAndroid Build Coastguard Worker         } else {
1401*e5436536SAndroid Build Coastguard Worker           bfDelta = 0;
1402*e5436536SAndroid Build Coastguard Worker         }
1403*e5436536SAndroid Build Coastguard Worker       }
1404*e5436536SAndroid Build Coastguard Worker 
1405*e5436536SAndroid Build Coastguard Worker       {
1406*e5436536SAndroid Build Coastguard Worker         int num, denom;
1407*e5436536SAndroid Build Coastguard Worker 
1408*e5436536SAndroid Build Coastguard Worker         /* Obtain estimate of number of lost frames */
1409*e5436536SAndroid Build Coastguard Worker         num = (INT)hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) +
1410*e5436536SAndroid Build Coastguard Worker               hTp->remainder;
1411*e5436536SAndroid Build Coastguard Worker         denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame;
1412*e5436536SAndroid Build Coastguard Worker         if (num > 0) {
1413*e5436536SAndroid Build Coastguard Worker           nAU = num / denom;
1414*e5436536SAndroid Build Coastguard Worker           hTp->remainder = num % denom;
1415*e5436536SAndroid Build Coastguard Worker         } else {
1416*e5436536SAndroid Build Coastguard Worker           hTp->remainder = num;
1417*e5436536SAndroid Build Coastguard Worker         }
1418*e5436536SAndroid Build Coastguard Worker 
1419*e5436536SAndroid Build Coastguard Worker         if (error == TRANSPORTDEC_OK) {
1420*e5436536SAndroid Build Coastguard Worker           /* Final adjustment of remainder, taken -1 into account because
1421*e5436536SAndroid Build Coastguard Worker              current frame should not be skipped, thus substract -1 or do
1422*e5436536SAndroid Build Coastguard Worker              nothing instead of +1-1 accordingly. */
1423*e5436536SAndroid Build Coastguard Worker           if ((denom - hTp->remainder) >= hTp->remainder) {
1424*e5436536SAndroid Build Coastguard Worker             nAU--;
1425*e5436536SAndroid Build Coastguard Worker           }
1426*e5436536SAndroid Build Coastguard Worker 
1427*e5436536SAndroid Build Coastguard Worker           if (nAU < 0) {
1428*e5436536SAndroid Build Coastguard Worker             /* There was one frame too much concealed, so unfortunately we will
1429*e5436536SAndroid Build Coastguard Worker              * have to skip one good frame. */
1430*e5436536SAndroid Build Coastguard Worker             transportDec_EndAccessUnit(hTp);
1431*e5436536SAndroid Build Coastguard Worker             error = synchronization(hTp, &headerBits);
1432*e5436536SAndroid Build Coastguard Worker             nAU = -1;
1433*e5436536SAndroid Build Coastguard Worker           }
1434*e5436536SAndroid Build Coastguard Worker           hTp->remainder = 0;
1435*e5436536SAndroid Build Coastguard Worker           /* Enforce last missed frames to be concealed. */
1436*e5436536SAndroid Build Coastguard Worker           if (nAU > 0) {
1437*e5436536SAndroid Build Coastguard Worker             FDKpushBack(hBs, headerBits);
1438*e5436536SAndroid Build Coastguard Worker           }
1439*e5436536SAndroid Build Coastguard Worker         }
1440*e5436536SAndroid Build Coastguard Worker       }
1441*e5436536SAndroid Build Coastguard Worker     }
1442*e5436536SAndroid Build Coastguard Worker   }
1443*e5436536SAndroid Build Coastguard Worker 
1444*e5436536SAndroid Build Coastguard Worker   /* Be sure that lost frames are handled correctly. This is necessary due to
1445*e5436536SAndroid Build Coastguard Worker      some sync error sequences where later it turns out that there is not enough
1446*e5436536SAndroid Build Coastguard Worker      data, but the bits upto the sync word are discarded, thus causing a value
1447*e5436536SAndroid Build Coastguard Worker      of nAU > 0 */
1448*e5436536SAndroid Build Coastguard Worker   if (nAU > 0) {
1449*e5436536SAndroid Build Coastguard Worker     error = TRANSPORTDEC_SYNC_ERROR;
1450*e5436536SAndroid Build Coastguard Worker   }
1451*e5436536SAndroid Build Coastguard Worker 
1452*e5436536SAndroid Build Coastguard Worker   hTp->missingAccessUnits = nAU;
1453*e5436536SAndroid Build Coastguard Worker 
1454*e5436536SAndroid Build Coastguard Worker   return error;
1455*e5436536SAndroid Build Coastguard Worker }
1456*e5436536SAndroid Build Coastguard Worker 
1457*e5436536SAndroid Build Coastguard Worker /* returns error code */
transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp,const UINT layer)1458*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp,
1459*e5436536SAndroid Build Coastguard Worker                                                const UINT layer) {
1460*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
1461*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs;
1462*e5436536SAndroid Build Coastguard Worker 
1463*e5436536SAndroid Build Coastguard Worker   if (!hTp) {
1464*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_INVALID_PARAMETER;
1465*e5436536SAndroid Build Coastguard Worker   }
1466*e5436536SAndroid Build Coastguard Worker 
1467*e5436536SAndroid Build Coastguard Worker   hBs = &hTp->bitStream[layer];
1468*e5436536SAndroid Build Coastguard Worker 
1469*e5436536SAndroid Build Coastguard Worker   if ((INT)FDKgetValidBits(hBs) <= 0) {
1470*e5436536SAndroid Build Coastguard Worker     /* This is only relevant for RAW and ADIF cases.
1471*e5436536SAndroid Build Coastguard Worker      * For streaming formats err will get overwritten. */
1472*e5436536SAndroid Build Coastguard Worker     err = TRANSPORTDEC_NOT_ENOUGH_BITS;
1473*e5436536SAndroid Build Coastguard Worker     hTp->numberOfRawDataBlocks = 0;
1474*e5436536SAndroid Build Coastguard Worker   }
1475*e5436536SAndroid Build Coastguard Worker 
1476*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
1477*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADIF:
1478*e5436536SAndroid Build Coastguard Worker       /* Read header if not already done */
1479*e5436536SAndroid Build Coastguard Worker       if (!(hTp->flags & TPDEC_CONFIG_FOUND)) {
1480*e5436536SAndroid Build Coastguard Worker         int i;
1481*e5436536SAndroid Build Coastguard Worker         CProgramConfig *pce;
1482*e5436536SAndroid Build Coastguard Worker         INT bsStart = FDKgetValidBits(hBs);
1483*e5436536SAndroid Build Coastguard Worker         UCHAR configChanged = 0;
1484*e5436536SAndroid Build Coastguard Worker         UCHAR configMode = AC_CM_DET_CFG_CHANGE;
1485*e5436536SAndroid Build Coastguard Worker 
1486*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < 2; i++) {
1487*e5436536SAndroid Build Coastguard Worker           if (i > 0) {
1488*e5436536SAndroid Build Coastguard Worker             FDKpushBack(hBs, bsStart - (INT)FDKgetValidBits(hBs));
1489*e5436536SAndroid Build Coastguard Worker             configMode = AC_CM_ALLOC_MEM;
1490*e5436536SAndroid Build Coastguard Worker           }
1491*e5436536SAndroid Build Coastguard Worker 
1492*e5436536SAndroid Build Coastguard Worker           AudioSpecificConfig_Init(&hTp->asc[0]);
1493*e5436536SAndroid Build Coastguard Worker           pce = &hTp->asc[0].m_progrConfigElement;
1494*e5436536SAndroid Build Coastguard Worker           err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs);
1495*e5436536SAndroid Build Coastguard Worker           if (err) goto bail;
1496*e5436536SAndroid Build Coastguard Worker 
1497*e5436536SAndroid Build Coastguard Worker           /* Map adif header to ASC */
1498*e5436536SAndroid Build Coastguard Worker           hTp->asc[0].m_aot = (AUDIO_OBJECT_TYPE)(pce->Profile + 1);
1499*e5436536SAndroid Build Coastguard Worker           hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex;
1500*e5436536SAndroid Build Coastguard Worker           hTp->asc[0].m_samplingFrequency =
1501*e5436536SAndroid Build Coastguard Worker               SamplingRateTable[pce->SamplingFrequencyIndex];
1502*e5436536SAndroid Build Coastguard Worker           hTp->asc[0].m_channelConfiguration = 0;
1503*e5436536SAndroid Build Coastguard Worker           hTp->asc[0].m_samplesPerFrame = 1024;
1504*e5436536SAndroid Build Coastguard Worker           hTp->avgBitRate = hTp->parser.adif.BitRate;
1505*e5436536SAndroid Build Coastguard Worker 
1506*e5436536SAndroid Build Coastguard Worker           /* Call callback to decoder. */
1507*e5436536SAndroid Build Coastguard Worker           {
1508*e5436536SAndroid Build Coastguard Worker             int errC;
1509*e5436536SAndroid Build Coastguard Worker 
1510*e5436536SAndroid Build Coastguard Worker             errC = hTp->callbacks.cbUpdateConfig(
1511*e5436536SAndroid Build Coastguard Worker                 hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode,
1512*e5436536SAndroid Build Coastguard Worker                 &configChanged);
1513*e5436536SAndroid Build Coastguard Worker             if (errC == 0) {
1514*e5436536SAndroid Build Coastguard Worker               hTp->flags |= TPDEC_CONFIG_FOUND;
1515*e5436536SAndroid Build Coastguard Worker             } else {
1516*e5436536SAndroid Build Coastguard Worker               err = TRANSPORTDEC_PARSE_ERROR;
1517*e5436536SAndroid Build Coastguard Worker               goto bail;
1518*e5436536SAndroid Build Coastguard Worker             }
1519*e5436536SAndroid Build Coastguard Worker           }
1520*e5436536SAndroid Build Coastguard Worker 
1521*e5436536SAndroid Build Coastguard Worker           if (err == TRANSPORTDEC_OK) {
1522*e5436536SAndroid Build Coastguard Worker             if ((i == 0) && configChanged) {
1523*e5436536SAndroid Build Coastguard Worker               int errC;
1524*e5436536SAndroid Build Coastguard Worker               errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData,
1525*e5436536SAndroid Build Coastguard Worker                                               &hTp->asc[0]);
1526*e5436536SAndroid Build Coastguard Worker               if (errC != 0) {
1527*e5436536SAndroid Build Coastguard Worker                 err = TRANSPORTDEC_PARSE_ERROR;
1528*e5436536SAndroid Build Coastguard Worker               }
1529*e5436536SAndroid Build Coastguard Worker             }
1530*e5436536SAndroid Build Coastguard Worker           }
1531*e5436536SAndroid Build Coastguard Worker         }
1532*e5436536SAndroid Build Coastguard Worker       }
1533*e5436536SAndroid Build Coastguard Worker       hTp->auLength[layer] = -1; /* Access Unit data length is unknown. */
1534*e5436536SAndroid Build Coastguard Worker       break;
1535*e5436536SAndroid Build Coastguard Worker 
1536*e5436536SAndroid Build Coastguard Worker     case TT_MP4_RAW:
1537*e5436536SAndroid Build Coastguard Worker     case TT_DRM:
1538*e5436536SAndroid Build Coastguard Worker       /* One Access Unit was filled into buffer.
1539*e5436536SAndroid Build Coastguard Worker          So get the length out of the buffer. */
1540*e5436536SAndroid Build Coastguard Worker       hTp->auLength[layer] = FDKgetValidBits(hBs);
1541*e5436536SAndroid Build Coastguard Worker       hTp->flags |= TPDEC_SYNCOK;
1542*e5436536SAndroid Build Coastguard Worker       break;
1543*e5436536SAndroid Build Coastguard Worker 
1544*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP0:
1545*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP1:
1546*e5436536SAndroid Build Coastguard Worker       if (err == TRANSPORTDEC_OK) {
1547*e5436536SAndroid Build Coastguard Worker         int fConfigFound = hTp->flags & TPDEC_CONFIG_FOUND;
1548*e5436536SAndroid Build Coastguard Worker         err = transportDec_readHeader(hTp, hBs, 0, 1, &hTp->auLength[layer],
1549*e5436536SAndroid Build Coastguard Worker                                       NULL, NULL, &fConfigFound, NULL);
1550*e5436536SAndroid Build Coastguard Worker         if (fConfigFound) {
1551*e5436536SAndroid Build Coastguard Worker           hTp->flags |= TPDEC_CONFIG_FOUND;
1552*e5436536SAndroid Build Coastguard Worker         }
1553*e5436536SAndroid Build Coastguard Worker       }
1554*e5436536SAndroid Build Coastguard Worker       break;
1555*e5436536SAndroid Build Coastguard Worker 
1556*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
1557*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
1558*e5436536SAndroid Build Coastguard Worker       err = transportDec_readStream(hTp, layer);
1559*e5436536SAndroid Build Coastguard Worker       break;
1560*e5436536SAndroid Build Coastguard Worker 
1561*e5436536SAndroid Build Coastguard Worker     default:
1562*e5436536SAndroid Build Coastguard Worker       err = TRANSPORTDEC_UNSUPPORTED_FORMAT;
1563*e5436536SAndroid Build Coastguard Worker       break;
1564*e5436536SAndroid Build Coastguard Worker   }
1565*e5436536SAndroid Build Coastguard Worker 
1566*e5436536SAndroid Build Coastguard Worker   if (err == TRANSPORTDEC_OK) {
1567*e5436536SAndroid Build Coastguard Worker     hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs);
1568*e5436536SAndroid Build Coastguard Worker   } else {
1569*e5436536SAndroid Build Coastguard Worker     hTp->accessUnitAnchor[layer] = 0;
1570*e5436536SAndroid Build Coastguard Worker   }
1571*e5436536SAndroid Build Coastguard Worker 
1572*e5436536SAndroid Build Coastguard Worker bail:
1573*e5436536SAndroid Build Coastguard Worker   return err;
1574*e5436536SAndroid Build Coastguard Worker }
1575*e5436536SAndroid Build Coastguard Worker 
transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp,const UINT layer,CSAudioSpecificConfig * asc)1576*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp,
1577*e5436536SAndroid Build Coastguard Worker                                        const UINT layer,
1578*e5436536SAndroid Build Coastguard Worker                                        CSAudioSpecificConfig *asc) {
1579*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
1580*e5436536SAndroid Build Coastguard Worker 
1581*e5436536SAndroid Build Coastguard Worker   if (hTp != NULL) {
1582*e5436536SAndroid Build Coastguard Worker     *asc = hTp->asc[layer];
1583*e5436536SAndroid Build Coastguard Worker     err = TRANSPORTDEC_OK;
1584*e5436536SAndroid Build Coastguard Worker   } else {
1585*e5436536SAndroid Build Coastguard Worker     err = TRANSPORTDEC_INVALID_PARAMETER;
1586*e5436536SAndroid Build Coastguard Worker   }
1587*e5436536SAndroid Build Coastguard Worker   return err;
1588*e5436536SAndroid Build Coastguard Worker }
1589*e5436536SAndroid Build Coastguard Worker 
transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp,const UINT layer)1590*e5436536SAndroid Build Coastguard Worker INT transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp,
1591*e5436536SAndroid Build Coastguard Worker                                     const UINT layer) {
1592*e5436536SAndroid Build Coastguard Worker   INT bits;
1593*e5436536SAndroid Build Coastguard Worker 
1594*e5436536SAndroid Build Coastguard Worker   if (hTp->accessUnitAnchor[layer] > 0 && hTp->auLength[layer] > 0) {
1595*e5436536SAndroid Build Coastguard Worker     bits = (INT)FDKgetValidBits(&hTp->bitStream[layer]);
1596*e5436536SAndroid Build Coastguard Worker     if (bits >= 0) {
1597*e5436536SAndroid Build Coastguard Worker       bits = hTp->auLength[layer] - ((INT)hTp->accessUnitAnchor[layer] - bits);
1598*e5436536SAndroid Build Coastguard Worker     }
1599*e5436536SAndroid Build Coastguard Worker   } else {
1600*e5436536SAndroid Build Coastguard Worker     bits = FDKgetValidBits(&hTp->bitStream[layer]);
1601*e5436536SAndroid Build Coastguard Worker   }
1602*e5436536SAndroid Build Coastguard Worker 
1603*e5436536SAndroid Build Coastguard Worker   return bits;
1604*e5436536SAndroid Build Coastguard Worker }
1605*e5436536SAndroid Build Coastguard Worker 
transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp,const UINT layer)1606*e5436536SAndroid Build Coastguard Worker INT transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp,
1607*e5436536SAndroid Build Coastguard Worker                                 const UINT layer) {
1608*e5436536SAndroid Build Coastguard Worker   return hTp->auLength[layer];
1609*e5436536SAndroid Build Coastguard Worker }
1610*e5436536SAndroid Build Coastguard Worker 
transportDec_GetMissingAccessUnitCount(INT * pNAccessUnits,HANDLE_TRANSPORTDEC hTp)1611*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount(
1612*e5436536SAndroid Build Coastguard Worker     INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp) {
1613*e5436536SAndroid Build Coastguard Worker   *pNAccessUnits = hTp->missingAccessUnits;
1614*e5436536SAndroid Build Coastguard Worker 
1615*e5436536SAndroid Build Coastguard Worker   return TRANSPORTDEC_OK;
1616*e5436536SAndroid Build Coastguard Worker }
1617*e5436536SAndroid Build Coastguard Worker 
1618*e5436536SAndroid Build Coastguard Worker /* Inform the transportDec layer that reading of access unit has finished. */
transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp)1619*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp) {
1620*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK;
1621*e5436536SAndroid Build Coastguard Worker 
1622*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
1623*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LOAS:
1624*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP0:
1625*e5436536SAndroid Build Coastguard Worker     case TT_MP4_LATM_MCP1: {
1626*e5436536SAndroid Build Coastguard Worker       HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0];
1627*e5436536SAndroid Build Coastguard Worker       if (hTp->numberOfRawDataBlocks == 0) {
1628*e5436536SAndroid Build Coastguard Worker         /* Read other data if available. */
1629*e5436536SAndroid Build Coastguard Worker         if (CLatmDemux_GetOtherDataPresentFlag(&hTp->parser.latm)) {
1630*e5436536SAndroid Build Coastguard Worker           int otherDataLen = CLatmDemux_GetOtherDataLength(&hTp->parser.latm);
1631*e5436536SAndroid Build Coastguard Worker 
1632*e5436536SAndroid Build Coastguard Worker           if ((INT)FDKgetValidBits(hBs) >= otherDataLen) {
1633*e5436536SAndroid Build Coastguard Worker             FDKpushFor(hBs, otherDataLen);
1634*e5436536SAndroid Build Coastguard Worker           } else {
1635*e5436536SAndroid Build Coastguard Worker             /* Do byte align at the end of AudioMuxElement. */
1636*e5436536SAndroid Build Coastguard Worker             if (hTp->numberOfRawDataBlocks == 0) {
1637*e5436536SAndroid Build Coastguard Worker               FDKbyteAlign(hBs, hTp->globalFramePos);
1638*e5436536SAndroid Build Coastguard Worker             }
1639*e5436536SAndroid Build Coastguard Worker             return TRANSPORTDEC_NOT_ENOUGH_BITS;
1640*e5436536SAndroid Build Coastguard Worker           }
1641*e5436536SAndroid Build Coastguard Worker         }
1642*e5436536SAndroid Build Coastguard Worker       } else {
1643*e5436536SAndroid Build Coastguard Worker         /* If bit buffer has not more bits but hTp->numberOfRawDataBlocks > 0
1644*e5436536SAndroid Build Coastguard Worker            then too many bits were read and obviously no more RawDataBlocks can
1645*e5436536SAndroid Build Coastguard Worker            be read. Set numberOfRawDataBlocks to zero to attempt a new sync
1646*e5436536SAndroid Build Coastguard Worker            attempt. */
1647*e5436536SAndroid Build Coastguard Worker         if ((INT)FDKgetValidBits(hBs) <= 0) {
1648*e5436536SAndroid Build Coastguard Worker           hTp->numberOfRawDataBlocks = 0;
1649*e5436536SAndroid Build Coastguard Worker         }
1650*e5436536SAndroid Build Coastguard Worker       }
1651*e5436536SAndroid Build Coastguard Worker     } break;
1652*e5436536SAndroid Build Coastguard Worker     default:
1653*e5436536SAndroid Build Coastguard Worker       break;
1654*e5436536SAndroid Build Coastguard Worker   }
1655*e5436536SAndroid Build Coastguard Worker 
1656*e5436536SAndroid Build Coastguard Worker   err = transportDec_AdjustEndOfAccessUnit(hTp);
1657*e5436536SAndroid Build Coastguard Worker 
1658*e5436536SAndroid Build Coastguard Worker   switch (hTp->transportFmt) {
1659*e5436536SAndroid Build Coastguard Worker     default:
1660*e5436536SAndroid Build Coastguard Worker       break;
1661*e5436536SAndroid Build Coastguard Worker   }
1662*e5436536SAndroid Build Coastguard Worker 
1663*e5436536SAndroid Build Coastguard Worker   return err;
1664*e5436536SAndroid Build Coastguard Worker }
1665*e5436536SAndroid Build Coastguard Worker 
transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp,const TPDEC_PARAM param,const INT value)1666*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp,
1667*e5436536SAndroid Build Coastguard Worker                                          const TPDEC_PARAM param,
1668*e5436536SAndroid Build Coastguard Worker                                          const INT value) {
1669*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK;
1670*e5436536SAndroid Build Coastguard Worker 
1671*e5436536SAndroid Build Coastguard Worker   if (hTp == NULL) {
1672*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_INVALID_PARAMETER;
1673*e5436536SAndroid Build Coastguard Worker   }
1674*e5436536SAndroid Build Coastguard Worker 
1675*e5436536SAndroid Build Coastguard Worker   switch (param) {
1676*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_MINIMIZE_DELAY:
1677*e5436536SAndroid Build Coastguard Worker       if (value) {
1678*e5436536SAndroid Build Coastguard Worker         hTp->flags |= TPDEC_MINIMIZE_DELAY;
1679*e5436536SAndroid Build Coastguard Worker       } else {
1680*e5436536SAndroid Build Coastguard Worker         hTp->flags &= ~TPDEC_MINIMIZE_DELAY;
1681*e5436536SAndroid Build Coastguard Worker       }
1682*e5436536SAndroid Build Coastguard Worker       break;
1683*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_EARLY_CONFIG:
1684*e5436536SAndroid Build Coastguard Worker       if (value) {
1685*e5436536SAndroid Build Coastguard Worker         hTp->flags |= TPDEC_EARLY_CONFIG;
1686*e5436536SAndroid Build Coastguard Worker       } else {
1687*e5436536SAndroid Build Coastguard Worker         hTp->flags &= ~TPDEC_EARLY_CONFIG;
1688*e5436536SAndroid Build Coastguard Worker       }
1689*e5436536SAndroid Build Coastguard Worker       break;
1690*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_IGNORE_BUFFERFULLNESS:
1691*e5436536SAndroid Build Coastguard Worker       if (value) {
1692*e5436536SAndroid Build Coastguard Worker         hTp->flags |= TPDEC_IGNORE_BUFFERFULLNESS;
1693*e5436536SAndroid Build Coastguard Worker       } else {
1694*e5436536SAndroid Build Coastguard Worker         hTp->flags &= ~TPDEC_IGNORE_BUFFERFULLNESS;
1695*e5436536SAndroid Build Coastguard Worker       }
1696*e5436536SAndroid Build Coastguard Worker       break;
1697*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_SET_BITRATE:
1698*e5436536SAndroid Build Coastguard Worker       hTp->avgBitRate = value;
1699*e5436536SAndroid Build Coastguard Worker       break;
1700*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_BURST_PERIOD:
1701*e5436536SAndroid Build Coastguard Worker       hTp->burstPeriod = value;
1702*e5436536SAndroid Build Coastguard Worker       break;
1703*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_RESET: {
1704*e5436536SAndroid Build Coastguard Worker       int i;
1705*e5436536SAndroid Build Coastguard Worker 
1706*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < (1 * 1); i++) {
1707*e5436536SAndroid Build Coastguard Worker         FDKresetBitbuffer(&hTp->bitStream[i]);
1708*e5436536SAndroid Build Coastguard Worker         hTp->auLength[i] = 0;
1709*e5436536SAndroid Build Coastguard Worker         hTp->accessUnitAnchor[i] = 0;
1710*e5436536SAndroid Build Coastguard Worker       }
1711*e5436536SAndroid Build Coastguard Worker       hTp->flags &= ~(TPDEC_SYNCOK | TPDEC_LOST_FRAMES_PENDING);
1712*e5436536SAndroid Build Coastguard Worker       if (hTp->transportFmt != TT_MP4_ADIF) {
1713*e5436536SAndroid Build Coastguard Worker         hTp->flags &= ~TPDEC_CONFIG_FOUND;
1714*e5436536SAndroid Build Coastguard Worker       }
1715*e5436536SAndroid Build Coastguard Worker       hTp->remainder = 0;
1716*e5436536SAndroid Build Coastguard Worker       hTp->avgBitRate = 0;
1717*e5436536SAndroid Build Coastguard Worker       hTp->missingAccessUnits = 0;
1718*e5436536SAndroid Build Coastguard Worker       hTp->numberOfRawDataBlocks = 0;
1719*e5436536SAndroid Build Coastguard Worker       hTp->globalFramePos = 0;
1720*e5436536SAndroid Build Coastguard Worker       hTp->holdOffFrames = 0;
1721*e5436536SAndroid Build Coastguard Worker     } break;
1722*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_TARGETLAYOUT:
1723*e5436536SAndroid Build Coastguard Worker       hTp->targetLayout = value;
1724*e5436536SAndroid Build Coastguard Worker       break;
1725*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_FORCE_CONFIG_CHANGE:
1726*e5436536SAndroid Build Coastguard Worker       hTp->ctrlCFGChange[value].forceCfgChange = TPDEC_FORCE_CONFIG_CHANGE;
1727*e5436536SAndroid Build Coastguard Worker       break;
1728*e5436536SAndroid Build Coastguard Worker     case TPDEC_PARAM_USE_ELEM_SKIPPING:
1729*e5436536SAndroid Build Coastguard Worker       if (value) {
1730*e5436536SAndroid Build Coastguard Worker         hTp->flags |= TPDEC_USE_ELEM_SKIPPING;
1731*e5436536SAndroid Build Coastguard Worker       } else {
1732*e5436536SAndroid Build Coastguard Worker         hTp->flags &= ~TPDEC_USE_ELEM_SKIPPING;
1733*e5436536SAndroid Build Coastguard Worker       }
1734*e5436536SAndroid Build Coastguard Worker       break;
1735*e5436536SAndroid Build Coastguard Worker   }
1736*e5436536SAndroid Build Coastguard Worker 
1737*e5436536SAndroid Build Coastguard Worker   return error;
1738*e5436536SAndroid Build Coastguard Worker }
1739*e5436536SAndroid Build Coastguard Worker 
transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp)1740*e5436536SAndroid Build Coastguard Worker UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp) {
1741*e5436536SAndroid Build Coastguard Worker   UINT nSubFrames = 0;
1742*e5436536SAndroid Build Coastguard Worker 
1743*e5436536SAndroid Build Coastguard Worker   if (hTp == NULL) return 0;
1744*e5436536SAndroid Build Coastguard Worker 
1745*e5436536SAndroid Build Coastguard Worker   if (hTp->transportFmt == TT_MP4_LATM_MCP1 ||
1746*e5436536SAndroid Build Coastguard Worker       hTp->transportFmt == TT_MP4_LATM_MCP0 || hTp->transportFmt == TT_MP4_LOAS)
1747*e5436536SAndroid Build Coastguard Worker     nSubFrames = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm);
1748*e5436536SAndroid Build Coastguard Worker   else if (hTp->transportFmt == TT_MP4_ADTS)
1749*e5436536SAndroid Build Coastguard Worker     nSubFrames = hTp->parser.adts.bs.num_raw_blocks;
1750*e5436536SAndroid Build Coastguard Worker 
1751*e5436536SAndroid Build Coastguard Worker   return nSubFrames;
1752*e5436536SAndroid Build Coastguard Worker }
1753*e5436536SAndroid Build Coastguard Worker 
transportDec_Close(HANDLE_TRANSPORTDEC * phTp)1754*e5436536SAndroid Build Coastguard Worker void transportDec_Close(HANDLE_TRANSPORTDEC *phTp) {
1755*e5436536SAndroid Build Coastguard Worker   if (phTp != NULL) {
1756*e5436536SAndroid Build Coastguard Worker     if (*phTp != NULL) {
1757*e5436536SAndroid Build Coastguard Worker       FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer);
1758*e5436536SAndroid Build Coastguard Worker       FreeRam_TransportDecoder(phTp);
1759*e5436536SAndroid Build Coastguard Worker     }
1760*e5436536SAndroid Build Coastguard Worker   }
1761*e5436536SAndroid Build Coastguard Worker }
1762*e5436536SAndroid Build Coastguard Worker 
transportDec_GetLibInfo(LIB_INFO * info)1763*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info) {
1764*e5436536SAndroid Build Coastguard Worker   int i;
1765*e5436536SAndroid Build Coastguard Worker 
1766*e5436536SAndroid Build Coastguard Worker   if (info == NULL) {
1767*e5436536SAndroid Build Coastguard Worker     return TRANSPORTDEC_UNKOWN_ERROR;
1768*e5436536SAndroid Build Coastguard Worker   }
1769*e5436536SAndroid Build Coastguard Worker 
1770*e5436536SAndroid Build Coastguard Worker   /* search for next free tab */
1771*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < FDK_MODULE_LAST; i++) {
1772*e5436536SAndroid Build Coastguard Worker     if (info[i].module_id == FDK_NONE) break;
1773*e5436536SAndroid Build Coastguard Worker   }
1774*e5436536SAndroid Build Coastguard Worker   if (i == FDK_MODULE_LAST) return TRANSPORTDEC_UNKOWN_ERROR;
1775*e5436536SAndroid Build Coastguard Worker   info += i;
1776*e5436536SAndroid Build Coastguard Worker 
1777*e5436536SAndroid Build Coastguard Worker   info->module_id = FDK_TPDEC;
1778*e5436536SAndroid Build Coastguard Worker #ifdef SUPPRESS_BUILD_DATE_INFO
1779*e5436536SAndroid Build Coastguard Worker   info->build_date = "";
1780*e5436536SAndroid Build Coastguard Worker   info->build_time = "";
1781*e5436536SAndroid Build Coastguard Worker #else
1782*e5436536SAndroid Build Coastguard Worker   info->build_date = __DATE__;
1783*e5436536SAndroid Build Coastguard Worker   info->build_time = __TIME__;
1784*e5436536SAndroid Build Coastguard Worker #endif
1785*e5436536SAndroid Build Coastguard Worker   info->title = TP_LIB_TITLE;
1786*e5436536SAndroid Build Coastguard Worker   info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2);
1787*e5436536SAndroid Build Coastguard Worker   LIB_VERSION_STRING(info);
1788*e5436536SAndroid Build Coastguard Worker   info->flags = 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS |
1789*e5436536SAndroid Build Coastguard Worker                 CAPF_RAWPACKETS | CAPF_DRM;
1790*e5436536SAndroid Build Coastguard Worker 
1791*e5436536SAndroid Build Coastguard Worker   return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */
1792*e5436536SAndroid Build Coastguard Worker }
1793*e5436536SAndroid Build Coastguard Worker 
transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp,INT mBits)1794*e5436536SAndroid Build Coastguard Worker int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits) {
1795*e5436536SAndroid Build Coastguard Worker   switch (pTp->transportFmt) {
1796*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
1797*e5436536SAndroid Build Coastguard Worker       return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits);
1798*e5436536SAndroid Build Coastguard Worker     case TT_DRM:
1799*e5436536SAndroid Build Coastguard Worker       return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits);
1800*e5436536SAndroid Build Coastguard Worker     default:
1801*e5436536SAndroid Build Coastguard Worker       return -1;
1802*e5436536SAndroid Build Coastguard Worker   }
1803*e5436536SAndroid Build Coastguard Worker }
1804*e5436536SAndroid Build Coastguard Worker 
transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp,INT reg)1805*e5436536SAndroid Build Coastguard Worker void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg) {
1806*e5436536SAndroid Build Coastguard Worker   switch (pTp->transportFmt) {
1807*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
1808*e5436536SAndroid Build Coastguard Worker       adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg);
1809*e5436536SAndroid Build Coastguard Worker       break;
1810*e5436536SAndroid Build Coastguard Worker     case TT_DRM:
1811*e5436536SAndroid Build Coastguard Worker       drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg);
1812*e5436536SAndroid Build Coastguard Worker       break;
1813*e5436536SAndroid Build Coastguard Worker     default:
1814*e5436536SAndroid Build Coastguard Worker       break;
1815*e5436536SAndroid Build Coastguard Worker   }
1816*e5436536SAndroid Build Coastguard Worker }
1817*e5436536SAndroid Build Coastguard Worker 
transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp)1818*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) {
1819*e5436536SAndroid Build Coastguard Worker   switch (pTp->transportFmt) {
1820*e5436536SAndroid Build Coastguard Worker     case TT_MP4_ADTS:
1821*e5436536SAndroid Build Coastguard Worker       if ((pTp->parser.adts.bs.num_raw_blocks > 0) &&
1822*e5436536SAndroid Build Coastguard Worker           (pTp->parser.adts.bs.protection_absent == 0)) {
1823*e5436536SAndroid Build Coastguard Worker         transportDec_AdjustEndOfAccessUnit(pTp);
1824*e5436536SAndroid Build Coastguard Worker       }
1825*e5436536SAndroid Build Coastguard Worker       return adtsRead_CrcCheck(&pTp->parser.adts);
1826*e5436536SAndroid Build Coastguard Worker     case TT_DRM:
1827*e5436536SAndroid Build Coastguard Worker       return drmRead_CrcCheck(&pTp->parser.drm);
1828*e5436536SAndroid Build Coastguard Worker     default:
1829*e5436536SAndroid Build Coastguard Worker       return TRANSPORTDEC_OK;
1830*e5436536SAndroid Build Coastguard Worker   }
1831*e5436536SAndroid Build Coastguard Worker }
1832*e5436536SAndroid Build Coastguard Worker 
transportDec_DrmRawSdcAudioConfig_Check(UCHAR * conf,const UINT length)1833*e5436536SAndroid Build Coastguard Worker TRANSPORTDEC_ERROR transportDec_DrmRawSdcAudioConfig_Check(UCHAR *conf,
1834*e5436536SAndroid Build Coastguard Worker                                                            const UINT length) {
1835*e5436536SAndroid Build Coastguard Worker   CSAudioSpecificConfig asc;
1836*e5436536SAndroid Build Coastguard Worker   FDK_BITSTREAM bs;
1837*e5436536SAndroid Build Coastguard Worker   HANDLE_FDK_BITSTREAM hBs = &bs;
1838*e5436536SAndroid Build Coastguard Worker 
1839*e5436536SAndroid Build Coastguard Worker   FDKinitBitStream(hBs, conf, BUFSIZE_DUMMY_VALUE, length << 3, BS_READER);
1840*e5436536SAndroid Build Coastguard Worker 
1841*e5436536SAndroid Build Coastguard Worker   TRANSPORTDEC_ERROR err =
1842*e5436536SAndroid Build Coastguard Worker       DrmRawSdcAudioConfig_Parse(&asc, hBs, NULL, (UCHAR)AC_CM_ALLOC_MEM, 0);
1843*e5436536SAndroid Build Coastguard Worker 
1844*e5436536SAndroid Build Coastguard Worker   return err;
1845*e5436536SAndroid Build Coastguard Worker }
1846