/src/aac/libMpegTPDec/src/tpdec_latm.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /******************* MPEG transport format decoder library ********************* |
96 | | |
97 | | Author(s): Daniel Homm |
98 | | |
99 | | Description: |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "tpdec_latm.h" |
104 | | |
105 | | #include "FDK_bitstream.h" |
106 | | |
107 | 0 | #define TPDEC_TRACKINDEX(p, l) (1 * (p) + (l)) |
108 | | |
109 | 0 | static UINT CLatmDemux_GetValue(HANDLE_FDK_BITSTREAM bs) { |
110 | 0 | UCHAR bytesForValue = 0, tmp = 0; |
111 | 0 | int value = 0; |
112 | |
|
113 | 0 | bytesForValue = (UCHAR)FDKreadBits(bs, 2); |
114 | |
|
115 | 0 | for (UINT i = 0; i <= bytesForValue; i++) { |
116 | 0 | value <<= 8; |
117 | 0 | tmp = (UCHAR)FDKreadBits(bs, 8); |
118 | 0 | value += tmp; |
119 | 0 | } |
120 | |
|
121 | 0 | return value; |
122 | 0 | } |
123 | | |
124 | | static TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement( |
125 | | HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, int m_muxConfigPresent, |
126 | | CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, |
127 | 0 | int *pfConfigFound) { |
128 | 0 | TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; |
129 | |
|
130 | 0 | if (m_muxConfigPresent) { |
131 | 0 | pLatmDemux->m_useSameStreamMux = FDKreadBits(bs, 1); |
132 | |
|
133 | 0 | if (!pLatmDemux->m_useSameStreamMux) { |
134 | 0 | int i; |
135 | 0 | UCHAR configChanged = 0; |
136 | 0 | UCHAR configMode = 0; |
137 | |
|
138 | 0 | FDK_BITSTREAM bsAnchor; |
139 | |
|
140 | 0 | FDK_BITSTREAM bsAnchorDummyParse; |
141 | |
|
142 | 0 | if (!pLatmDemux->applyAsc) { |
143 | 0 | bsAnchorDummyParse = *bs; |
144 | 0 | pLatmDemux->newCfgHasAudioPreRoll = 0; |
145 | | /* do dummy-parsing of ASC to determine if there is an audioPreRoll */ |
146 | 0 | configMode |= AC_CM_DET_CFG_CHANGE; |
147 | 0 | if (TRANSPORTDEC_OK != |
148 | 0 | (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( |
149 | 0 | bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, |
150 | 0 | configMode, configChanged))) { |
151 | 0 | goto bail; |
152 | 0 | } |
153 | | |
154 | | /* Allow flushing only when audioPreroll functionality is enabled in |
155 | | * current and new config otherwise the new config can be applied |
156 | | * immediately. */ |
157 | 0 | if (pAsc->m_sc.m_usacConfig.element[0] |
158 | 0 | .extElement.usacExtElementHasAudioPreRoll && |
159 | 0 | pLatmDemux->newCfgHasAudioPreRoll) { |
160 | 0 | pLatmDemux->newCfgHasAudioPreRoll = 0; |
161 | | /* with audioPreRoll we must flush before applying new cfg */ |
162 | 0 | pLatmDemux->applyAsc = 0; |
163 | 0 | } else { |
164 | 0 | *bs = bsAnchorDummyParse; |
165 | 0 | pLatmDemux->applyAsc = 1; /* apply new config immediate */ |
166 | 0 | } |
167 | 0 | } |
168 | | |
169 | 0 | if (pLatmDemux->applyAsc) { |
170 | 0 | for (i = 0; i < 2; i++) { |
171 | 0 | configMode = 0; |
172 | |
|
173 | 0 | if (i == 0) { |
174 | 0 | configMode |= AC_CM_DET_CFG_CHANGE; |
175 | 0 | bsAnchor = *bs; |
176 | 0 | } else { |
177 | 0 | configMode |= AC_CM_ALLOC_MEM; |
178 | 0 | *bs = bsAnchor; |
179 | 0 | } |
180 | |
|
181 | 0 | if (TRANSPORTDEC_OK != |
182 | 0 | (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( |
183 | 0 | bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, |
184 | 0 | configMode, configChanged))) { |
185 | 0 | goto bail; |
186 | 0 | } |
187 | | |
188 | 0 | if (ErrorStatus == TRANSPORTDEC_OK) { |
189 | 0 | if ((i == 0) && (pAsc->AacConfigChanged || pAsc->SbrConfigChanged || |
190 | 0 | pAsc->SacConfigChanged)) { |
191 | 0 | int errC; |
192 | |
|
193 | 0 | configChanged = 1; |
194 | 0 | errC = pTpDecCallbacks->cbFreeMem(pTpDecCallbacks->cbFreeMemData, |
195 | 0 | pAsc); |
196 | 0 | if (errC != 0) { |
197 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
198 | 0 | goto bail; |
199 | 0 | } |
200 | 0 | } |
201 | 0 | } |
202 | 0 | } |
203 | 0 | } |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | | /* If there was no configuration read, its not possible to parse |
208 | | * PayloadLengthInfo below. */ |
209 | 0 | if (!*pfConfigFound) { |
210 | 0 | ErrorStatus = TRANSPORTDEC_SYNC_ERROR; |
211 | 0 | goto bail; |
212 | 0 | } |
213 | | |
214 | 0 | if (pLatmDemux->m_AudioMuxVersionA == 0) { |
215 | | /* Do only once per call, because parsing and decoding is done in-line. */ |
216 | 0 | if (TRANSPORTDEC_OK != |
217 | 0 | (ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs, pLatmDemux))) { |
218 | 0 | *pfConfigFound = 0; |
219 | 0 | goto bail; |
220 | 0 | } |
221 | 0 | } else { |
222 | | /* audioMuxVersionA > 0 is reserved for future extensions */ |
223 | 0 | ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; |
224 | 0 | *pfConfigFound = 0; |
225 | 0 | goto bail; |
226 | 0 | } |
227 | | |
228 | 0 | bail: |
229 | 0 | if (ErrorStatus != TRANSPORTDEC_OK) { |
230 | 0 | pLatmDemux->applyAsc = 1; |
231 | 0 | } |
232 | |
|
233 | 0 | return (ErrorStatus); |
234 | 0 | } |
235 | | |
236 | | TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs, |
237 | | CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt, |
238 | | CSTpCallBacks *pTpDecCallbacks, |
239 | | CSAudioSpecificConfig *pAsc, |
240 | | int *pfConfigFound, |
241 | 0 | const INT ignoreBufferFullness) { |
242 | 0 | UINT cntBits; |
243 | 0 | UINT cmpBufferFullness; |
244 | 0 | UINT audioMuxLengthBytesLast = 0; |
245 | 0 | TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; |
246 | |
|
247 | 0 | cntBits = FDKgetValidBits(bs); |
248 | |
|
249 | 0 | if ((INT)cntBits < MIN_LATM_HEADERLENGTH) { |
250 | 0 | return TRANSPORTDEC_NOT_ENOUGH_BITS; |
251 | 0 | } |
252 | | |
253 | 0 | if (TRANSPORTDEC_OK != (ErrorStatus = CLatmDemux_ReadAudioMuxElement( |
254 | 0 | bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), |
255 | 0 | pTpDecCallbacks, pAsc, pfConfigFound))) |
256 | 0 | return (ErrorStatus); |
257 | | |
258 | 0 | if (!ignoreBufferFullness) { |
259 | 0 | cmpBufferFullness = |
260 | 0 | 24 + audioMuxLengthBytesLast * 8 + |
261 | 0 | pLatmDemux->m_linfo[0][0].m_bufferFullness * |
262 | 0 | pAsc[TPDEC_TRACKINDEX(0, 0)].m_channelConfiguration * 32; |
263 | | |
264 | | /* evaluate buffer fullness */ |
265 | |
|
266 | 0 | if (pLatmDemux->m_linfo[0][0].m_bufferFullness != 0xFF) { |
267 | 0 | if (!pLatmDemux->BufferFullnessAchieved) { |
268 | 0 | if (cntBits < cmpBufferFullness) { |
269 | | /* condition for start of decoding is not fulfilled */ |
270 | | |
271 | | /* the current frame will not be decoded */ |
272 | 0 | return TRANSPORTDEC_NOT_ENOUGH_BITS; |
273 | 0 | } else { |
274 | 0 | pLatmDemux->BufferFullnessAchieved = 1; |
275 | 0 | } |
276 | 0 | } |
277 | 0 | } |
278 | 0 | } |
279 | | |
280 | 0 | return (ErrorStatus); |
281 | 0 | } |
282 | | |
283 | | TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( |
284 | | HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, |
285 | | CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, |
286 | 0 | int *pfConfigFound, UCHAR configMode, UCHAR configChanged) { |
287 | 0 | CSAudioSpecificConfig ascDummy; /* the actual config is needed for flushing, |
288 | | after that new config can be parsed */ |
289 | 0 | CSAudioSpecificConfig *pAscDummy; |
290 | 0 | pAscDummy = &ascDummy; |
291 | 0 | pLatmDemux->usacExplicitCfgChanged = 0; |
292 | 0 | LATM_LAYER_INFO *p_linfo = NULL; |
293 | 0 | TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; |
294 | 0 | UCHAR updateConfig[1 * 1] = {0}; |
295 | |
|
296 | 0 | pLatmDemux->m_AudioMuxVersion = FDKreadBits(bs, 1); |
297 | |
|
298 | 0 | if (pLatmDemux->m_AudioMuxVersion == 0) { |
299 | 0 | pLatmDemux->m_AudioMuxVersionA = 0; |
300 | 0 | } else { |
301 | 0 | pLatmDemux->m_AudioMuxVersionA = FDKreadBits(bs, 1); |
302 | 0 | } |
303 | |
|
304 | 0 | if (pLatmDemux->m_AudioMuxVersionA == 0) { |
305 | 0 | if (pLatmDemux->m_AudioMuxVersion == 1) { |
306 | 0 | pLatmDemux->m_taraBufferFullness = CLatmDemux_GetValue(bs); |
307 | 0 | } |
308 | 0 | pLatmDemux->m_allStreamsSameTimeFraming = FDKreadBits(bs, 1); |
309 | 0 | pLatmDemux->m_noSubFrames = FDKreadBits(bs, 6) + 1; |
310 | 0 | pLatmDemux->m_numProgram = FDKreadBits(bs, 4) + 1; |
311 | |
|
312 | 0 | if (pLatmDemux->m_numProgram > LATM_MAX_PROG) { |
313 | 0 | ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; |
314 | 0 | goto bail; |
315 | 0 | } |
316 | | |
317 | 0 | int idCnt = 0; |
318 | 0 | for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { |
319 | 0 | pLatmDemux->m_numLayer[prog] = FDKreadBits(bs, 3) + 1; |
320 | 0 | if (pLatmDemux->m_numLayer[prog] > LATM_MAX_LAYER) { |
321 | 0 | ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; |
322 | 0 | goto bail; |
323 | 0 | } |
324 | | |
325 | 0 | for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { |
326 | 0 | int useSameConfig; |
327 | 0 | p_linfo = &pLatmDemux->m_linfo[prog][lay]; |
328 | |
|
329 | 0 | p_linfo->m_streamID = idCnt++; |
330 | 0 | p_linfo->m_frameLengthInBits = 0; |
331 | |
|
332 | 0 | if ((prog == 0) && (lay == 0)) { |
333 | 0 | useSameConfig = 0; |
334 | 0 | } else { |
335 | 0 | useSameConfig = FDKreadBits(bs, 1); |
336 | 0 | } |
337 | |
|
338 | 0 | if (useSameConfig) { |
339 | 0 | if (lay > 0) { |
340 | 0 | FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)], |
341 | 0 | &pAsc[TPDEC_TRACKINDEX(prog, lay - 1)], |
342 | 0 | sizeof(CSAudioSpecificConfig)); |
343 | 0 | } else { |
344 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
345 | 0 | goto bail; |
346 | 0 | } |
347 | 0 | } else { |
348 | 0 | UINT usacConfigLengthPrev = 0; |
349 | 0 | UCHAR usacConfigPrev[TP_USAC_MAX_CONFIG_LEN]; |
350 | |
|
351 | 0 | if (!(pLatmDemux->applyAsc) && |
352 | 0 | (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_USAC)) { |
353 | 0 | usacConfigLengthPrev = |
354 | 0 | (UINT)(pAsc[TPDEC_TRACKINDEX(prog, lay)] |
355 | 0 | .m_sc.m_usacConfig.UsacConfigBits + |
356 | 0 | 7) >> |
357 | 0 | 3; /* store previous USAC config length */ |
358 | 0 | if (usacConfigLengthPrev > TP_USAC_MAX_CONFIG_LEN) { |
359 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
360 | 0 | goto bail; |
361 | 0 | } |
362 | 0 | FDKmemclear(usacConfigPrev, TP_USAC_MAX_CONFIG_LEN); |
363 | 0 | FDKmemcpy( |
364 | 0 | usacConfigPrev, |
365 | 0 | &pAsc[TPDEC_TRACKINDEX(prog, lay)].m_sc.m_usacConfig.UsacConfig, |
366 | 0 | usacConfigLengthPrev); /* store previous USAC config */ |
367 | 0 | } |
368 | 0 | if (pLatmDemux->m_AudioMuxVersion == 1) { |
369 | 0 | FDK_BITSTREAM tmpBs; |
370 | 0 | INT ascLen = 0; |
371 | 0 | ascLen = CLatmDemux_GetValue(bs); |
372 | | /* The ascLen could be wrong, so check if validBits<=bufBits*/ |
373 | 0 | if (ascLen < 0 || ascLen > (INT)FDKgetValidBits(bs)) { |
374 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
375 | 0 | goto bail; |
376 | 0 | } |
377 | 0 | FDKsyncCache(bs); |
378 | 0 | tmpBs = *bs; |
379 | 0 | tmpBs.hBitBuf.ValidBits = ascLen; |
380 | | |
381 | | /* Read ASC */ |
382 | 0 | if (pLatmDemux->applyAsc) { |
383 | 0 | if (TRANSPORTDEC_OK != |
384 | 0 | (ErrorStatus = AudioSpecificConfig_Parse( |
385 | 0 | &pAsc[TPDEC_TRACKINDEX(prog, lay)], &tmpBs, 1, |
386 | 0 | pTpDecCallbacks, configMode, configChanged, |
387 | 0 | AOT_NULL_OBJECT))) |
388 | 0 | goto bail; |
389 | 0 | } else { |
390 | 0 | if (TRANSPORTDEC_OK != |
391 | 0 | (ErrorStatus = AudioSpecificConfig_Parse( |
392 | 0 | pAscDummy, &tmpBs, 1, pTpDecCallbacks, configMode, |
393 | 0 | configChanged, AOT_NULL_OBJECT))) |
394 | 0 | goto bail; |
395 | 0 | } |
396 | | |
397 | | /* The field p_linfo->m_ascLen could be wrong, so check if */ |
398 | 0 | if (0 > (INT)FDKgetValidBits(&tmpBs)) { |
399 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
400 | 0 | goto bail; |
401 | 0 | } |
402 | 0 | FDKpushFor(bs, ascLen); /* position bitstream after ASC */ |
403 | 0 | } else { |
404 | | /* Read ASC */ |
405 | 0 | if (pLatmDemux->applyAsc) { |
406 | 0 | if (TRANSPORTDEC_OK != (ErrorStatus = AudioSpecificConfig_Parse( |
407 | 0 | &pAsc[TPDEC_TRACKINDEX(prog, lay)], |
408 | 0 | bs, 0, pTpDecCallbacks, configMode, |
409 | 0 | configChanged, AOT_NULL_OBJECT))) |
410 | 0 | goto bail; |
411 | 0 | } else { |
412 | 0 | if (TRANSPORTDEC_OK != |
413 | 0 | (ErrorStatus = AudioSpecificConfig_Parse( |
414 | 0 | pAscDummy, bs, 0, pTpDecCallbacks, configMode, |
415 | 0 | configChanged, AOT_NULL_OBJECT))) |
416 | 0 | goto bail; |
417 | 0 | } |
418 | 0 | } |
419 | 0 | if (!pLatmDemux->applyAsc) { |
420 | 0 | updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 0; |
421 | 0 | } else { |
422 | 0 | updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 1; |
423 | 0 | } |
424 | |
|
425 | 0 | if (!pLatmDemux->applyAsc) { |
426 | 0 | if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)].m_aot == |
427 | 0 | AOT_USAC) { /* flush in case SMC has changed */ |
428 | 0 | const UINT usacConfigLength = |
429 | 0 | (UINT)(pAscDummy->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3; |
430 | 0 | if (usacConfigLength > TP_USAC_MAX_CONFIG_LEN) { |
431 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
432 | 0 | goto bail; |
433 | 0 | } |
434 | 0 | if (usacConfigLength != usacConfigLengthPrev) { |
435 | 0 | FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] |
436 | 0 | .m_sc.m_usacConfig.UsacConfig, |
437 | 0 | TP_USAC_MAX_CONFIG_LEN); |
438 | 0 | FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] |
439 | 0 | .m_sc.m_usacConfig.UsacConfig, |
440 | 0 | &pAscDummy->m_sc.m_usacConfig.UsacConfig, |
441 | 0 | usacConfigLength); /* store new USAC config */ |
442 | 0 | pAsc[TPDEC_TRACKINDEX(prog, lay)] |
443 | 0 | .m_sc.m_usacConfig.UsacConfigBits = |
444 | 0 | pAscDummy->m_sc.m_usacConfig.UsacConfigBits; |
445 | 0 | pLatmDemux->usacExplicitCfgChanged = 1; |
446 | 0 | } else { |
447 | 0 | if (FDKmemcmp(usacConfigPrev, |
448 | 0 | pAscDummy->m_sc.m_usacConfig.UsacConfig, |
449 | 0 | usacConfigLengthPrev)) { |
450 | 0 | FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] |
451 | 0 | .m_sc.m_usacConfig.UsacConfig, |
452 | 0 | TP_USAC_MAX_CONFIG_LEN); |
453 | 0 | FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] |
454 | 0 | .m_sc.m_usacConfig.UsacConfig, |
455 | 0 | &pAscDummy->m_sc.m_usacConfig.UsacConfig, |
456 | 0 | usacConfigLength); /* store new USAC config */ |
457 | 0 | pAsc[TPDEC_TRACKINDEX(prog, lay)] |
458 | 0 | .m_sc.m_usacConfig.UsacConfigBits = |
459 | 0 | pAscDummy->m_sc.m_usacConfig.UsacConfigBits; |
460 | 0 | pLatmDemux->usacExplicitCfgChanged = 1; |
461 | 0 | } |
462 | 0 | } |
463 | |
|
464 | 0 | if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] |
465 | 0 | .m_sc.m_usacConfig.m_usacNumElements) { |
466 | 0 | if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] |
467 | 0 | .m_sc.m_usacConfig.element[0] |
468 | 0 | .extElement.usacExtElementHasAudioPreRoll) { |
469 | 0 | pLatmDemux->newCfgHasAudioPreRoll = |
470 | 0 | 1; /* if dummy parsed cfg has audioPreRoll we first flush |
471 | | before applying new cfg */ |
472 | 0 | } |
473 | 0 | } |
474 | 0 | } |
475 | 0 | } |
476 | 0 | } |
477 | | |
478 | 0 | p_linfo->m_frameLengthType = FDKreadBits(bs, 3); |
479 | 0 | switch (p_linfo->m_frameLengthType) { |
480 | 0 | case 0: |
481 | 0 | p_linfo->m_bufferFullness = FDKreadBits(bs, 8); |
482 | |
|
483 | 0 | if (!pLatmDemux->m_allStreamsSameTimeFraming) { |
484 | 0 | if ((lay > 0) && |
485 | 0 | (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_AAC_SCAL || |
486 | 0 | pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == |
487 | 0 | AOT_ER_AAC_SCAL) && |
488 | 0 | (pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == AOT_CELP || |
489 | 0 | pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == |
490 | 0 | AOT_ER_CELP)) { /* The layer maybe |
491 | | ignored later so |
492 | | read it anyway: */ |
493 | 0 | /* coreFrameOffset = */ FDKreadBits(bs, 6); |
494 | 0 | } |
495 | 0 | } |
496 | 0 | break; |
497 | 0 | case 1: |
498 | 0 | p_linfo->m_frameLengthInBits = FDKreadBits(bs, 9); |
499 | 0 | break; |
500 | 0 | case 3: |
501 | 0 | case 4: |
502 | 0 | case 5: |
503 | | /* CELP */ |
504 | 0 | case 6: |
505 | 0 | case 7: |
506 | | /* HVXC */ |
507 | 0 | default: |
508 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
509 | 0 | goto bail; |
510 | 0 | } /* switch framelengthtype*/ |
511 | |
|
512 | 0 | } /* layer loop */ |
513 | 0 | } /* prog loop */ |
514 | | |
515 | 0 | pLatmDemux->m_otherDataPresent = FDKreadBits(bs, 1); |
516 | 0 | pLatmDemux->m_otherDataLength = 0; |
517 | |
|
518 | 0 | if (pLatmDemux->m_otherDataPresent) { |
519 | 0 | if (pLatmDemux->m_AudioMuxVersion == 1) { |
520 | 0 | pLatmDemux->m_otherDataLength = CLatmDemux_GetValue(bs); |
521 | 0 | } else { |
522 | 0 | int otherDataLenEsc = 0; |
523 | 0 | do { |
524 | 0 | pLatmDemux->m_otherDataLength <<= 8; // *= 256 |
525 | 0 | otherDataLenEsc = FDKreadBits(bs, 1); |
526 | 0 | pLatmDemux->m_otherDataLength += FDKreadBits(bs, 8); |
527 | 0 | } while (otherDataLenEsc); |
528 | 0 | } |
529 | 0 | if (pLatmDemux->m_audioMuxLengthBytes < |
530 | 0 | (pLatmDemux->m_otherDataLength >> 3)) { |
531 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; |
532 | 0 | goto bail; |
533 | 0 | } |
534 | 0 | } |
535 | | |
536 | 0 | pLatmDemux->m_crcCheckPresent = FDKreadBits(bs, 1); |
537 | |
|
538 | 0 | if (pLatmDemux->m_crcCheckPresent) { |
539 | 0 | FDKreadBits(bs, 8); |
540 | 0 | } |
541 | |
|
542 | 0 | } else { |
543 | | /* audioMuxVersionA > 0 is reserved for future extensions */ |
544 | 0 | ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; |
545 | 0 | } |
546 | | |
547 | | /* Configure source decoder: */ |
548 | 0 | if (ErrorStatus == TRANSPORTDEC_OK) { |
549 | 0 | UINT prog; |
550 | 0 | for (prog = 0; prog < pLatmDemux->m_numProgram; prog++) { |
551 | 0 | UINT lay; |
552 | 0 | for (lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { |
553 | 0 | if (updateConfig[TPDEC_TRACKINDEX(prog, lay)] != 0) { |
554 | 0 | int cbError; |
555 | 0 | cbError = pTpDecCallbacks->cbUpdateConfig( |
556 | 0 | pTpDecCallbacks->cbUpdateConfigData, |
557 | 0 | &pAsc[TPDEC_TRACKINDEX(prog, lay)], |
558 | 0 | pAsc[TPDEC_TRACKINDEX(prog, lay)].configMode, |
559 | 0 | &pAsc[TPDEC_TRACKINDEX(prog, lay)].AacConfigChanged); |
560 | 0 | if (cbError == TRANSPORTDEC_NEED_TO_RESTART) { |
561 | 0 | *pfConfigFound = 0; |
562 | 0 | ErrorStatus = TRANSPORTDEC_NEED_TO_RESTART; |
563 | 0 | goto bail; |
564 | 0 | } |
565 | 0 | if (cbError != 0) { |
566 | 0 | *pfConfigFound = 0; |
567 | 0 | if (lay == 0) { |
568 | 0 | ErrorStatus = TRANSPORTDEC_SYNC_ERROR; |
569 | 0 | goto bail; |
570 | 0 | } |
571 | 0 | } else { |
572 | 0 | *pfConfigFound = 1; |
573 | 0 | } |
574 | 0 | } else { |
575 | 0 | *pfConfigFound = 1; |
576 | 0 | } |
577 | 0 | } |
578 | 0 | } |
579 | 0 | } |
580 | | |
581 | 0 | bail: |
582 | 0 | if (ErrorStatus != TRANSPORTDEC_OK) { |
583 | 0 | UCHAR applyAsc = pLatmDemux->applyAsc; |
584 | 0 | FDKmemclear(pLatmDemux, sizeof(CLatmDemux)); /* reset structure */ |
585 | 0 | pLatmDemux->applyAsc = applyAsc; |
586 | 0 | } else { |
587 | | /* no error and config parsing is finished */ |
588 | 0 | if (configMode == AC_CM_ALLOC_MEM) pLatmDemux->applyAsc = 0; |
589 | 0 | } |
590 | |
|
591 | 0 | return (ErrorStatus); |
592 | 0 | } |
593 | | |
594 | 0 | static int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) { |
595 | 0 | int len = 0, tmp = 255; |
596 | 0 | int validBytes = (int)FDKgetValidBits(bs) >> 3; |
597 | |
|
598 | 0 | while (tmp == 255 && validBytes-- > 0) { |
599 | 0 | tmp = (int)FDKreadBits(bs, 8); |
600 | 0 | len += tmp; |
601 | 0 | } |
602 | |
|
603 | 0 | return ((tmp == 255) ? -1 : (len << 3)); |
604 | 0 | } |
605 | | |
606 | | TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, |
607 | 0 | CLatmDemux *pLatmDemux) { |
608 | 0 | TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; |
609 | 0 | int totalPayloadBits = 0; |
610 | |
|
611 | 0 | if (pLatmDemux->m_allStreamsSameTimeFraming == 1) { |
612 | 0 | FDK_ASSERT(pLatmDemux->m_numProgram <= LATM_MAX_PROG); |
613 | 0 | for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { |
614 | 0 | FDK_ASSERT(pLatmDemux->m_numLayer[prog] <= LATM_MAX_LAYER); |
615 | 0 | for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { |
616 | 0 | LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay]; |
617 | 0 | int auChunkLengthInfo = 0; |
618 | |
|
619 | 0 | switch (p_linfo->m_frameLengthType) { |
620 | 0 | case 0: |
621 | 0 | auChunkLengthInfo = CLatmDemux_ReadAuChunkLengthInfo(bs); |
622 | 0 | if (auChunkLengthInfo >= 0) { |
623 | 0 | p_linfo->m_frameLengthInBits = (UINT)auChunkLengthInfo; |
624 | 0 | totalPayloadBits += p_linfo->m_frameLengthInBits; |
625 | 0 | } else { |
626 | 0 | return TRANSPORTDEC_PARSE_ERROR; |
627 | 0 | } |
628 | 0 | break; |
629 | 0 | case 3: |
630 | 0 | case 5: |
631 | 0 | case 7: |
632 | 0 | default: |
633 | 0 | return TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_INVALIDFRAMELENGTHTYPE; |
634 | 0 | } |
635 | 0 | } |
636 | 0 | } |
637 | 0 | } else { |
638 | 0 | ErrorStatus = TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_TIMEFRAMING; |
639 | 0 | } |
640 | 0 | if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 && |
641 | 0 | totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes * 8) { |
642 | 0 | return TRANSPORTDEC_PARSE_ERROR; |
643 | 0 | } |
644 | | |
645 | 0 | return (ErrorStatus); |
646 | 0 | } |
647 | | |
648 | | UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog, |
649 | 0 | const UINT layer) { |
650 | 0 | UINT nFrameLenBits = 0; |
651 | 0 | if (prog < pLatmDemux->m_numProgram) { |
652 | 0 | if (layer < pLatmDemux->m_numLayer[prog]) { |
653 | 0 | nFrameLenBits = pLatmDemux->m_linfo[prog][layer].m_frameLengthInBits; |
654 | 0 | } |
655 | 0 | } |
656 | 0 | return nFrameLenBits; |
657 | 0 | } |
658 | | |
659 | 0 | UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux) { |
660 | 0 | return pLatmDemux->m_otherDataPresent ? 1 : 0; |
661 | 0 | } |
662 | | |
663 | 0 | UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux) { |
664 | 0 | return pLatmDemux->m_otherDataLength; |
665 | 0 | } |
666 | | |
667 | 0 | UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux) { |
668 | 0 | return pLatmDemux->m_noSubFrames; |
669 | 0 | } |
670 | | |
671 | 0 | UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT prog) { |
672 | 0 | UINT numLayer = 0; |
673 | 0 | if (prog < pLatmDemux->m_numProgram) { |
674 | 0 | numLayer = pLatmDemux->m_numLayer[prog]; |
675 | 0 | } |
676 | 0 | return numLayer; |
677 | 0 | } |