blob: 729d99c5ab7a25d4d3021de16ef01352a6d4ba82
1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Source last modified: $Id: ra8lbr_decode.c,v 1.2.2.1 2005/05/04 18:21:53 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 <core/dsp.h> |
40 | #include "helix_types.h" |
41 | #include "helix_result.h" |
42 | #include "ra8lbr_decode.h" |
43 | #include "ra_format_info.h" |
44 | #include "gecko2codec.h" |
45 | #include <stdio.h> |
46 | |
47 | #define GECKO_VERSION ((1L<<24)|(0L<<16)|(0L<<8)|(3L)) |
48 | #define GECKO_MC1_VERSION ((2L<<24)|(0L<<16)|(0L<<8)|(0L)) |
49 | |
50 | HX_RESULT ra8lbr_unpack_opaque_data(ra8lbr_data* pData, |
51 | UINT8* pBuf, |
52 | UINT32 ulLength); |
53 | |
54 | /* |
55 | * ra8lbr_decode_init |
56 | */ |
57 | HX_RESULT |
58 | ra8lbr_decode_init(void* pInitParams, |
59 | UINT32 ulInitParamsSize, |
60 | ra_format_info* pStreamInfo, |
61 | void** pDecode, |
62 | void* pUserMem, |
63 | rm_malloc_func_ptr fpMalloc, |
64 | rm_free_func_ptr fpFree) |
65 | { |
66 | HX_RESULT retVal = HXR_FAIL; |
67 | ra8lbr_decode* pDec; |
68 | ra8lbr_data unpackedData; |
69 | UINT32 nChannels, frameSizeInBits; |
70 | |
71 | pDec = (ra8lbr_decode*) fpMalloc(pUserMem, sizeof(ra8lbr_decode)); |
72 | |
73 | if (pDec) { |
74 | memset(pDec, 0, sizeof(ra8lbr_decode)); |
75 | *pDecode = (void *)pDec; |
76 | retVal = ra8lbr_unpack_opaque_data(&unpackedData, |
77 | pStreamInfo->pOpaqueData, |
78 | pStreamInfo->ulOpaqueDataSize); |
79 | |
80 | if (retVal == HXR_OK) { |
81 | /* save the stream info and init data we'll need later */ |
82 | pDec->ulNumChannels = (UINT32)pStreamInfo->usNumChannels; |
83 | pDec->ulFrameSize = pStreamInfo->ulBitsPerFrame; |
84 | pDec->ulFramesPerBlock = pStreamInfo->ulGranularity / pDec->ulFrameSize; |
85 | pDec->ulSamplesPerFrame = unpackedData.nSamples; |
86 | pDec->ulSampleRate = pStreamInfo->ulSampleRate; |
87 | |
88 | /* multichannel not supported, use simple logic for channel mask */ |
89 | if (pDec->ulNumChannels == 1) { |
90 | pDec->ulChannelMask = 0x00004; |
91 | } else if (pDec->ulNumChannels == 2) { |
92 | pDec->ulChannelMask = 0x00003; |
93 | } else { |
94 | pDec->ulChannelMask = 0x00003; |
95 | } |
96 | if (pDec->ulNumChannels > 2) { |
97 | pDec->ulNumChannels = 2; |
98 | } |
99 | nChannels = pDec->ulNumChannels; |
100 | frameSizeInBits = pDec->ulFrameSize * 8; |
101 | |
102 | /* initialize the decoder backend and save a reference to it */ |
103 | |
104 | pDec->pDecoder = Gecko2InitDecoder(pDec->ulSamplesPerFrame / nChannels, |
105 | nChannels, |
106 | unpackedData.nRegions, |
107 | frameSizeInBits, |
108 | pDec->ulSampleRate, |
109 | unpackedData.cplStart, |
110 | unpackedData.cplQBits, |
111 | (INT32 *)&pDec->ulDelayFrames); |
112 | |
113 | /* Allocate a dummy input frame for flushing the decoder */ |
114 | pDec->pFlushData = (UCHAR *) fpMalloc(pUserMem, pDec->ulFrameSize); |
115 | |
116 | if (pDec->pDecoder == HXNULL || pDec->pFlushData == HXNULL) { |
117 | retVal = HXR_FAIL; |
118 | } else { |
119 | /* fill the dummy input frame with zeros */ |
120 | memset(pDec->pFlushData, 0, pDec->ulFrameSize); |
121 | |
122 | /* Set number of delay samples to discard on decoder start */ |
123 | pDec->ulDelayRemaining = pDec->ulDelayFrames * pDec->ulSamplesPerFrame; |
124 | } |
125 | } |
126 | } |
127 | |
128 | return retVal; |
129 | } |
130 | |
131 | HX_RESULT |
132 | ra8lbr_decode_reset(void* pDecode, |
133 | UINT16* pSamplesOut, |
134 | UINT32 ulNumSamplesAvail, |
135 | UINT32* pNumSamplesOut) |
136 | { |
137 | HX_RESULT retVal = HXR_FAIL; |
138 | ra8lbr_decode* pDec = (ra8lbr_decode*) pDecode; |
139 | UINT32 n, framesToDecode; |
140 | |
141 | *pNumSamplesOut = 0; |
142 | |
143 | if (pSamplesOut != HXNULL) { |
144 | framesToDecode = pDec->ulDelayFrames; |
145 | if (framesToDecode * pDec->ulSamplesPerFrame > ulNumSamplesAvail) { |
146 | framesToDecode = ulNumSamplesAvail / pDec->ulSamplesPerFrame; |
147 | } |
148 | |
149 | for (n = 0; n < framesToDecode; n++) { |
150 | retVal = Gecko2Decode(pDec->pDecoder, pDec->pFlushData, |
151 | 0xFFFFFFFFUL, (INT16 *)pSamplesOut + *pNumSamplesOut, 0); |
152 | *pNumSamplesOut += pDec->ulSamplesPerFrame; |
153 | } |
154 | |
155 | /* reset the delay compensation */ |
156 | pDec->ulDelayRemaining = pDec->ulDelayFrames * pDec->ulSamplesPerFrame; |
157 | } |
158 | |
159 | return retVal; |
160 | } |
161 | |
162 | HX_RESULT |
163 | ra8lbr_decode_conceal(void* pDecode, |
164 | UINT32 ulNumSamples) |
165 | { |
166 | ra8lbr_decode* pDec = (ra8lbr_decode*) pDecode; |
167 | pDec->ulFramesToConceal = ulNumSamples / pDec->ulSamplesPerFrame; |
168 | |
169 | return HXR_OK; |
170 | } |
171 | |
172 | HX_RESULT |
173 | ra8lbr_decode_decode(void* pDecode, |
174 | UINT8* pData, |
175 | UINT32 ulNumBytes, |
176 | UINT32* pNumBytesConsumed, |
177 | UINT16* pSamplesOut, |
178 | UINT32 ulNumSamplesAvail, |
179 | UINT32* pNumSamplesOut, |
180 | UINT32 ulFlags, |
181 | UINT32 ulTimeStamp) |
182 | { |
183 | HX_RESULT retVal = HXR_FAIL; |
184 | ra8lbr_decode* pDec = (ra8lbr_decode*) pDecode; |
185 | UINT32 n, framesToDecode, lostFlag; |
186 | UINT8* inBuf = pData; |
187 | UINT16* outBuf = pSamplesOut; |
188 | |
189 | *pNumBytesConsumed = 0; |
190 | *pNumSamplesOut = 0; |
191 | framesToDecode = 0; |
192 | |
193 | if (pDec->ulFramesToConceal != 0) { |
194 | if (pDec->ulFramesToConceal > ulNumSamplesAvail / pDec->ulSamplesPerFrame) { |
195 | framesToDecode = ulNumSamplesAvail / pDec->ulSamplesPerFrame; |
196 | pDec->ulFramesToConceal -= framesToDecode; |
197 | } else { |
198 | framesToDecode = pDec->ulFramesToConceal; |
199 | pDec->ulFramesToConceal = 0; |
200 | } |
201 | |
202 | inBuf = pDec->pFlushData; |
203 | |
204 | for (n = 0; n < framesToDecode; n++) { |
205 | retVal = Gecko2Decode(pDec->pDecoder, inBuf, 0xFFFFFFFFUL, (INT16 *)outBuf, ulTimeStamp); |
206 | |
207 | if (retVal != 0) { |
208 | retVal = HXR_FAIL; |
209 | break; |
210 | } |
211 | |
212 | outBuf += pDec->ulSamplesPerFrame; |
213 | *pNumSamplesOut += pDec->ulSamplesPerFrame; |
214 | } |
215 | } else if (ulNumBytes % pDec->ulFrameSize == 0) { |
216 | framesToDecode = ulNumBytes / pDec->ulFrameSize; |
217 | |
218 | if (framesToDecode > ulNumSamplesAvail / pDec->ulSamplesPerFrame) { |
219 | framesToDecode = ulNumSamplesAvail / pDec->ulSamplesPerFrame; |
220 | } |
221 | |
222 | for (n = 0; n < framesToDecode; n++) { |
223 | lostFlag = !((ulFlags >> n) & 1); |
224 | |
225 | retVal = Gecko2Decode(pDec->pDecoder, inBuf, lostFlag, (INT16 *)outBuf, ulTimeStamp); |
226 | |
227 | if (retVal != 0) { |
228 | retVal = HXR_FAIL; |
229 | break; |
230 | } |
231 | |
232 | inBuf += pDec->ulFrameSize; |
233 | *pNumBytesConsumed += pDec->ulFrameSize; |
234 | outBuf += pDec->ulSamplesPerFrame; |
235 | *pNumSamplesOut += pDec->ulSamplesPerFrame; |
236 | } |
237 | } |
238 | |
239 | /* Discard invalid output samples */ |
240 | if (retVal == HXR_FAIL) { /* decoder error */ |
241 | *pNumSamplesOut = 0; |
242 | /* protect consumer ears by zeroing the output buffer, |
243 | just in case the error return code is disregarded. */ |
244 | memset(pSamplesOut, 0, pDec->ulSamplesPerFrame * framesToDecode * sizeof(UINT16)); |
245 | } else if (pDec->ulDelayRemaining > 0) { /* delay samples */ |
246 | if (pDec->ulDelayRemaining >= *pNumSamplesOut) { |
247 | pDec->ulDelayRemaining -= *pNumSamplesOut; |
248 | *pNumSamplesOut = 0; |
249 | } else { |
250 | *pNumSamplesOut -= pDec->ulDelayRemaining; |
251 | memmove(pSamplesOut, pSamplesOut + pDec->ulDelayRemaining, *pNumSamplesOut); |
252 | pDec->ulDelayRemaining = 0; |
253 | } |
254 | } |
255 | |
256 | return retVal; |
257 | } |
258 | |
259 | HX_RESULT |
260 | ra8lbr_decode_getmaxsize(void* pDecode, |
261 | UINT32* pNumSamples) |
262 | { |
263 | ra8lbr_decode* pDec = (ra8lbr_decode *)pDecode; |
264 | *pNumSamples = pDec->ulSamplesPerFrame * pDec->ulFramesPerBlock; |
265 | |
266 | return HXR_OK; |
267 | } |
268 | |
269 | HX_RESULT |
270 | ra8lbr_decode_getchannels(void* pDecode, |
271 | UINT32* pNumChannels) |
272 | { |
273 | ra8lbr_decode* pDec = (ra8lbr_decode *)pDecode; |
274 | *pNumChannels = pDec->ulNumChannels; |
275 | |
276 | return HXR_OK; |
277 | } |
278 | |
279 | HX_RESULT |
280 | ra8lbr_decode_getchannelmask(void* pDecode, |
281 | UINT32* pChannelMask) |
282 | { |
283 | ra8lbr_decode* pDec = (ra8lbr_decode *)pDecode; |
284 | *pChannelMask = pDec->ulChannelMask; |
285 | return HXR_OK; |
286 | } |
287 | |
288 | HX_RESULT |
289 | ra8lbr_decode_getrate(void* pDecode, |
290 | UINT32* pSampleRate) |
291 | { |
292 | ra8lbr_decode* pDec = (ra8lbr_decode *)pDecode; |
293 | *pSampleRate = pDec->ulSampleRate; |
294 | |
295 | return HXR_OK; |
296 | } |
297 | |
298 | HX_RESULT |
299 | ra8lbr_decode_getdelay(void* pDecode, |
300 | UINT32* pNumSamples) |
301 | { |
302 | ra8lbr_decode* pDec = (ra8lbr_decode *)pDecode; |
303 | /* delay compensation is handled internally */ |
304 | *pNumSamples = 0; |
305 | |
306 | return HXR_OK; |
307 | } |
308 | |
309 | HX_RESULT |
310 | ra8lbr_decode_close(void* pDecode, |
311 | void* pUserMem, |
312 | rm_free_func_ptr fpFree) |
313 | { |
314 | ra8lbr_decode* pDec = (ra8lbr_decode *)pDecode; |
315 | /* free the ra8lbr decoder */ |
316 | if (pDec->pDecoder) { |
317 | Gecko2FreeDecoder(pDec->pDecoder); |
318 | } |
319 | /* free the dummy input buffer */ |
320 | if (pDec->pFlushData) { |
321 | fpFree(pUserMem, pDec->pFlushData); |
322 | } |
323 | /* free the ra8lbr backend */ |
324 | fpFree(pUserMem, pDec); |
325 | |
326 | return HXR_OK; |
327 | } |
328 | |
329 | HX_RESULT |
330 | ra8lbr_unpack_opaque_data(ra8lbr_data* pData, |
331 | UINT8* pBuf, |
332 | UINT32 ulLength) |
333 | { |
334 | HX_RESULT retVal = HXR_FAIL; |
335 | UINT8* off = pBuf; |
336 | |
337 | if (pBuf != HXNULL && ulLength != 0) { |
338 | retVal = HXR_OK; |
339 | |
340 | pData->version = ((INT32) * off++) << 24; |
341 | pData->version |= ((INT32) * off++) << 16; |
342 | pData->version |= ((INT32) * off++) << 8; |
343 | pData->version |= ((INT32) * off++); |
344 | |
345 | pData->nSamples = *off++ << 8; |
346 | pData->nSamples |= *off++; |
347 | |
348 | pData->nRegions = *off++ << 8; |
349 | pData->nRegions |= *off++; |
350 | //printk("version %d, sample per frame %d \n",pData->version,pData->nSamples); |
351 | if (pData->version >= GECKO_VERSION) { |
352 | pData->delay = ((INT32) * off++) << 24; |
353 | pData->delay |= ((INT32) * off++) << 16; |
354 | pData->delay |= ((INT32) * off++) << 8; |
355 | pData->delay |= ((INT32) * off++); |
356 | |
357 | pData->cplStart = *off++ << 8; |
358 | pData->cplStart |= *off++; |
359 | |
360 | pData->cplQBits = *off++ << 8; |
361 | pData->cplQBits |= *off++; |
362 | } else { |
363 | /* the fixed point ra8lbr decoder supports dual-mono decoding with |
364 | a single decoder instance if cplQBits is set to zero. */ |
365 | pData->cplStart = 0; |
366 | pData->cplQBits = 0; |
367 | } |
368 | |
369 | if (pData->version == GECKO_MC1_VERSION) { |
370 | pData->channelMask = ((INT32) * off++) << 24; |
371 | pData->channelMask |= ((INT32) * off++) << 16; |
372 | pData->channelMask |= ((INT32) * off++) << 8; |
373 | pData->channelMask |= ((INT32) * off++); |
374 | } |
375 | } |
376 | |
377 | return retVal; |
378 | } |
379 |