blob: d184927fcc8c0ffef464c4554bbb92678fb2a8a7
1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Source last modified: $Id: aac_decode.c,v 1.2.2.1 2005/05/04 18:21:58 hubbe Exp $ |
3 | * |
4 | * REALNETWORKS CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM |
5 | * Portions Copyright (c) 1995-2005 RealNetworks, Inc. |
6 | * All Rights Reserved. |
7 | * |
8 | * The contents of this file, and the files included with this file, |
9 | * are subject to the current version of the Real Format Source Code |
10 | * Porting and Optimization License, available at |
11 | * https://helixcommunity.org/2005/license/realformatsource (unless |
12 | * RealNetworks otherwise expressly agrees in writing that you are |
13 | * subject to a different license). You may also obtain the license |
14 | * terms directly from RealNetworks. You may not use this file except |
15 | * in compliance with the Real Format Source Code Porting and |
16 | * Optimization License. There are no redistribution rights for the |
17 | * source code of this file. Please see the Real Format Source Code |
18 | * Porting and Optimization License for the rights, obligations and |
19 | * limitations governing use of the contents of the file. |
20 | * |
21 | * RealNetworks is the developer of the Original Code and owns the |
22 | * copyrights in the portions it created. |
23 | * |
24 | * This file, and the files included with this file, is distributed and |
25 | * made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, |
26 | * EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL |
27 | * SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF |
28 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT |
29 | * OR NON-INFRINGEMENT. |
30 | * |
31 | * Technology Compatibility Kit Test Suite(s) Location: |
32 | * https://rarvcode-tck.helixcommunity.org |
33 | * |
34 | * Contributor(s): |
35 | * |
36 | * ***** END LICENSE BLOCK ***** */ |
37 | |
38 | #include <string.h> |
39 | #include "include/helix_types.h" |
40 | #include "include/helix_result.h" |
41 | #include "aac_decode.h" |
42 | #include "include/ra_format_info.h" |
43 | #include "ga_config.h" |
44 | #include "aac_bitstream.h" |
45 | #include "aac_reorder.h" |
46 | #include "aac_decode.h" |
47 | #include "aacdec.h" |
48 | #include <stdio.h> |
49 | //#include <core/dsp.h> |
50 | |
51 | /* |
52 | * aac_decode_init |
53 | */ |
54 | HX_RESULT |
55 | aac_decode_init(void* pInitParams, |
56 | UINT32 ulInitParamsSize, |
57 | ra_format_info* pStreamInfo, |
58 | void** pDecode, |
59 | void* pUserMem, |
60 | rm_malloc_func_ptr fpMalloc, |
61 | rm_free_func_ptr fpFree) |
62 | { |
63 | HX_RESULT result = HXR_OK; |
64 | aac_decode* pDec; |
65 | AACFrameInfo *frameInfo; |
66 | ga_config_data configData; |
67 | UCHAR *pData; |
68 | UCHAR *inBuf; |
69 | INT16 *temp; |
70 | UINT32 numBytes, numBits; |
71 | UINT32 cfgType; |
72 | |
73 | /* for MP4 bitstream parsing */ |
74 | struct BITSTREAM *pBs = 0; |
75 | |
76 | /* allocate the aac_decode struct */ |
77 | pDec = (aac_decode*) fpMalloc(pUserMem, sizeof(aac_decode)); |
78 | if (pDec == HXNULL) { |
79 | return HXR_OUTOFMEMORY; |
80 | } |
81 | |
82 | memset(pDec, 0, sizeof(aac_decode)); |
83 | *pDecode = (void *)pDec; |
84 | |
85 | /* allocate the frame info struct */ |
86 | pDec->pFrameInfo = fpMalloc(pUserMem, sizeof(AACFrameInfo)); |
87 | frameInfo = (AACFrameInfo *) pDec->pFrameInfo; |
88 | /* allocate the decoder backend instance */ |
89 | pDec->pDecoder = AACInitDecoder(1); |
90 | if (pDec->pFrameInfo == HXNULL || pDec->pDecoder == HXNULL) { |
91 | return HXR_OUTOFMEMORY; |
92 | } |
93 | |
94 | /* save the stream info and init data we'll need later */ |
95 | pDec->ulNumChannels = (UINT32)pStreamInfo->usNumChannels; |
96 | pDec->ulBlockSize = pStreamInfo->ulGranularity; |
97 | pDec->ulFrameSize = pStreamInfo->ulBitsPerFrame; |
98 | pDec->ulFramesPerBlock = pDec->ulBlockSize / pDec->ulFrameSize; |
99 | /* output frame size is doubled for safety in case of implicit SBR */ |
100 | pDec->ulSamplesPerFrame = 1024 * pStreamInfo->usNumChannels * 2; |
101 | pDec->ulSampleRateCore = pStreamInfo->ulSampleRate; |
102 | pDec->ulSampleRateOut = pStreamInfo->ulActualRate; |
103 | if (pStreamInfo->ulOpaqueDataSize < 1) { |
104 | return HXR_FAIL; /* insufficient config data */ |
105 | } |
106 | |
107 | /* get the config data */ |
108 | pData = (UCHAR *)pStreamInfo->pOpaqueData; |
109 | cfgType = pData[0]; |
110 | inBuf = pData + 1; |
111 | numBytes = pStreamInfo->ulOpaqueDataSize - 1; |
112 | |
113 | if (cfgType == 1) { /* ADTS Frame */ |
114 | /* allocate temp buffer for decoding first ADTS frame */ |
115 | temp = (INT16 *)fpMalloc(pUserMem, sizeof(INT16) * pDec->ulSamplesPerFrame); |
116 | if (temp == HXNULL) { |
117 | return HXR_OUTOFMEMORY; |
118 | } else { |
119 | /* decode ADTS frame from opaque data to get config data */ |
120 | result = AACDecode(pDec->pDecoder, &inBuf, (INT32*)&numBytes, temp); |
121 | /* free the temp buffer */ |
122 | fpFree(pUserMem, temp); |
123 | } |
124 | |
125 | if (result == HXR_OK) { |
126 | /* get the config data struct from the decoder */ |
127 | AACGetLastFrameInfo(pDec->pDecoder, frameInfo); |
128 | |
129 | pDec->ulNumChannels = frameInfo->nChans; |
130 | pDec->ulSamplesPerFrame = frameInfo->outputSamps; |
131 | pDec->ulSampleRateCore = frameInfo->sampRateCore; |
132 | pDec->ulSampleRateOut = frameInfo->sampRateOut; |
133 | pDec->bSBR = (pDec->ulSampleRateCore != pDec->ulSampleRateOut); |
134 | } |
135 | } else if (cfgType == 2) { /* MP4 Audio Specific Config Data */ |
136 | numBits = numBytes * 8; |
137 | |
138 | if (newBitstream(&pBs, numBits, pUserMem, fpMalloc)) { |
139 | return HXR_FAIL; |
140 | } |
141 | |
142 | feedBitstream(pBs, (const UCHAR *)inBuf, numBits); |
143 | setAtBitstream(pBs, 0, 1); |
144 | result = ga_config_get_data(pBs, &configData); |
145 | deleteBitstream(pBs, pUserMem, fpFree); |
146 | if (result != HXR_OK) { /* config data error */ |
147 | return HXR_FAIL; |
148 | } |
149 | |
150 | pDec->ulNumChannels = configData.numChannels; |
151 | pDec->ulSampleRateCore = configData.samplingFrequency; |
152 | pDec->ulSampleRateOut = configData.extensionSamplingFrequency; |
153 | pDec->bSBR = configData.bSBR; |
154 | |
155 | /* ulSamplesPerFrame is set to the maximum possible output length. |
156 | * The config data has the initial output length, which might |
157 | * be doubled once the first frame is handed in (if AAC+ is |
158 | * signalled implicitly). |
159 | */ |
160 | pDec->ulSamplesPerFrame = 2 * configData.frameLength * configData.numChannels; |
161 | |
162 | /* setup decoder to handle raw data blocks */ |
163 | frameInfo->nChans = pDec->ulNumChannels; |
164 | frameInfo->sampRateCore = pDec->ulSampleRateCore; |
165 | |
166 | /* see MPEG4 spec for index of each object type */ |
167 | if (configData.audioObjectType == 2) { |
168 | frameInfo->profile = AAC_PROFILE_LC; |
169 | } else if (configData.audioObjectType == 1) { |
170 | frameInfo->profile = AAC_PROFILE_MP; |
171 | } else if (configData.audioObjectType == 3) { |
172 | frameInfo->profile = AAC_PROFILE_SSR; |
173 | } else { |
174 | frameInfo->profile = AAC_PROFILE_LC; /* don't know - assume LC */ |
175 | } |
176 | frameInfo->audio_send_by_frame = 0; |
177 | } else { /* unsupported config type */ |
178 | return HXR_FAIL; |
179 | } |
180 | |
181 | /* make certain that all the channels can be handled */ |
182 | if (pDec->ulNumChannels > AAC_MAX_NCHANS) { |
183 | return HXR_UNSUPPORTED_AUDIO; |
184 | } |
185 | |
186 | /* set the channel mask - custom maps not supported */ |
187 | switch (pDec->ulNumChannels) { |
188 | case 1: |
189 | pDec->ulChannelMask = 0x00004; /* FC */ |
190 | case 2: |
191 | pDec->ulChannelMask = 0x00003; /* FL,FR */ |
192 | case 3: |
193 | pDec->ulChannelMask = 0x00007; /* FL,FR,FC */ |
194 | case 4: |
195 | pDec->ulChannelMask = 0x00107; /* FL,FR,FC,BC */ |
196 | case 5: |
197 | pDec->ulChannelMask = 0x00037; /* FL,FR,FC,BL,BR */ |
198 | case 6: |
199 | pDec->ulChannelMask = 0x0003F; /* FL,FR,FC,LF,BL,BR */ |
200 | default: |
201 | pDec->ulChannelMask = 0xFFFFF; /* Unknown */ |
202 | } |
203 | |
204 | /* set the delay samples */ |
205 | pDec->ulDelayRemaining = pDec->ulSamplesPerFrame; |
206 | |
207 | /* set decoder to handle raw data blocks */ |
208 | AACSetRawBlockParams(pDec->pDecoder, 0, frameInfo); |
209 | |
210 | |
211 | return HXR_OK; |
212 | } |
213 | |
214 | HX_RESULT |
215 | aac_decode_reset(void* pDecode, |
216 | UINT16* pSamplesOut, |
217 | UINT32 ulNumSamplesAvail, |
218 | UINT32* pNumSamplesOut) |
219 | { |
220 | aac_decode* pDec = (aac_decode*) pDecode; |
221 | AACFlushCodec(pDec->pDecoder); |
222 | *pNumSamplesOut = 0; |
223 | pDec->ulSamplesToConceal = 0; |
224 | |
225 | /* reset the delay compensation */ |
226 | pDec->ulDelayRemaining = pDec->ulSamplesPerFrame; |
227 | |
228 | return HXR_OK; |
229 | } |
230 | |
231 | HX_RESULT |
232 | aac_decode_conceal(void* pDecode, |
233 | UINT32 ulNumSamples) |
234 | { |
235 | aac_decode* pDec = (aac_decode*) pDecode; |
236 | if (pDec->bSBR) { |
237 | pDec->ulSamplesToConceal = (ulNumSamples + 2 * AAC_MAX_NSAMPS - 1) / (2 * AAC_MAX_NSAMPS); |
238 | } else { |
239 | pDec->ulSamplesToConceal = (ulNumSamples + AAC_MAX_NSAMPS - 1) / AAC_MAX_NSAMPS; |
240 | } |
241 | |
242 | return HXR_OK; |
243 | } |
244 | |
245 | HX_RESULT |
246 | aac_decode_decode(void* pDecode, |
247 | UINT8* pData, |
248 | UINT32 ulNumBytes, |
249 | UINT32* pNumBytesConsumed, |
250 | UINT16* pSamplesOut, |
251 | UINT32 ulNumSamplesAvail, |
252 | UINT32* pNumSamplesOut, |
253 | UINT32 ulFlags, |
254 | UINT32 ulTimeStamp) |
255 | { |
256 | HX_RESULT retVal = HXR_FAIL; |
257 | aac_decode* pDec = (aac_decode*) pDecode; |
258 | AACFrameInfo *frameInfo = pDec->pFrameInfo; |
259 | UINT32 lostFlag, maxSamplesOut; |
260 | UINT32 ulNumBytesRemaining; |
261 | UINT8* inBuf = pData; |
262 | UINT16* outBuf = pSamplesOut; |
263 | |
264 | ulNumBytesRemaining = ulNumBytes; |
265 | *pNumBytesConsumed = 0; |
266 | *pNumSamplesOut = 0; |
267 | |
268 | lostFlag = !(ulFlags & 1); |
269 | |
270 | if (pDec->ulSamplesToConceal || lostFlag) { |
271 | if (lostFlag) { /* conceal one frame */ |
272 | *pNumSamplesOut = pDec->ulSamplesPerFrame; |
273 | } else { |
274 | maxSamplesOut = pDec->ulSamplesPerFrame * pDec->ulFramesPerBlock; |
275 | *pNumSamplesOut = maxSamplesOut; |
276 | if (pDec->ulSamplesToConceal < maxSamplesOut) { |
277 | *pNumSamplesOut = pDec->ulSamplesToConceal; |
278 | } |
279 | pDec->ulSamplesToConceal -= *pNumSamplesOut; |
280 | } |
281 | /* just fill with silence */ |
282 | memset(pSamplesOut, 0, *pNumSamplesOut * sizeof(INT16)); |
283 | AACFlushCodec(pDec->pDecoder); |
284 | |
285 | *pNumBytesConsumed = 0; |
286 | return HXR_OK; |
287 | } |
288 | |
289 | retVal = AACDecode(pDec->pDecoder, &inBuf, |
290 | (INT32*)&ulNumBytesRemaining, (INT16*)outBuf); |
291 | if (retVal == ERR_AAC_NONE) { |
292 | AACGetLastFrameInfo(pDec->pDecoder, frameInfo); |
293 | AACReorderPCMChannels((INT16*)outBuf, frameInfo->outputSamps, frameInfo->nChans); |
294 | pDec->ulSampleRateCore = frameInfo->sampRateCore; |
295 | pDec->ulSampleRateOut = frameInfo->sampRateOut; |
296 | pDec->ulNumChannels = frameInfo->nChans; |
297 | *pNumSamplesOut = frameInfo->outputSamps; |
298 | *pNumBytesConsumed = ulNumBytes - ulNumBytesRemaining; |
299 | retVal = HXR_OK; |
300 | } else if (retVal == ERR_AAC_INDATA_UNDERFLOW) { |
301 | retVal = HXR_NO_DATA; |
302 | } else { |
303 | retVal = HXR_FAIL; |
304 | } |
305 | |
306 | /* Zero out invalid output samples */ |
307 | if (*pNumSamplesOut == 0) { |
308 | /* protect consumer ears by zeroing the output buffer */ |
309 | memset(pSamplesOut, 0, pDec->ulSamplesPerFrame * sizeof(UINT16)); |
310 | } else if (pDec->ulDelayRemaining > 0) { /* delay samples */ |
311 | if (pDec->ulDelayRemaining >= *pNumSamplesOut) { |
312 | pDec->ulDelayRemaining -= *pNumSamplesOut; |
313 | *pNumSamplesOut = 0; |
314 | } else { |
315 | *pNumSamplesOut -= pDec->ulDelayRemaining; |
316 | memmove(pSamplesOut, pSamplesOut + pDec->ulDelayRemaining, *pNumSamplesOut); |
317 | pDec->ulDelayRemaining = 0; |
318 | } |
319 | } |
320 | |
321 | return retVal; |
322 | } |
323 | |
324 | HX_RESULT |
325 | aac_decode_getmaxsize(void* pDecode, |
326 | UINT32* pNumSamples) |
327 | { |
328 | aac_decode* pDec = (aac_decode *)pDecode; |
329 | *pNumSamples = pDec->ulSamplesPerFrame * pDec->ulFramesPerBlock; |
330 | |
331 | return HXR_OK; |
332 | } |
333 | |
334 | HX_RESULT |
335 | aac_decode_getchannels(void* pDecode, |
336 | UINT32* pNumChannels) |
337 | { |
338 | aac_decode* pDec = (aac_decode *)pDecode; |
339 | *pNumChannels = pDec->ulNumChannels; |
340 | |
341 | return HXR_OK; |
342 | } |
343 | |
344 | HX_RESULT |
345 | aac_decode_getchannelmask(void* pDecode, |
346 | UINT32* pChannelMask) |
347 | { |
348 | aac_decode* pDec = (aac_decode *)pDecode; |
349 | *pChannelMask = pDec->ulChannelMask; |
350 | |
351 | return HXR_OK; |
352 | } |
353 | |
354 | HX_RESULT |
355 | aac_decode_getrate(void* pDecode, |
356 | UINT32* pSampleRate) |
357 | { |
358 | aac_decode* pDec = (aac_decode *)pDecode; |
359 | *pSampleRate = pDec->ulSampleRateOut; |
360 | |
361 | return HXR_OK; |
362 | } |
363 | |
364 | HX_RESULT |
365 | aac_decode_getdelay(void* pDecode, |
366 | UINT32* pNumSamples) |
367 | { |
368 | aac_decode* pDec = (aac_decode *)pDecode; |
369 | /* delay compensation is handled internally */ |
370 | *pNumSamples = 0; |
371 | |
372 | return HXR_OK; |
373 | } |
374 | |
375 | HX_RESULT |
376 | aac_decode_close(void* pDecode, |
377 | void* pUserMem, |
378 | rm_free_func_ptr fpFree) |
379 | { |
380 | aac_decode* pDec = (aac_decode *)pDecode; |
381 | /* free the aac decoder */ |
382 | if (pDec->pDecoder) { |
383 | AACFreeDecoder(pDec->pDecoder); |
384 | pDec->pDecoder = HXNULL; |
385 | } |
386 | /* free the frame info struct */ |
387 | if (pDec->pFrameInfo) { |
388 | fpFree(pUserMem, pDec->pFrameInfo); |
389 | pDec->pFrameInfo = HXNULL; |
390 | } |
391 | /* free the aac backend */ |
392 | fpFree(pUserMem, pDec); |
393 | pDec = HXNULL; |
394 | |
395 | return HXR_OK; |
396 | } |
397 |