|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: The functions in this module implements the common behavior |
|
15 * for the audio decoder base class. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include "AdvancedAudioDecoder.h" |
|
22 #include "DebugMacros.h" |
|
23 #include <mmfdatabuffer.h> |
|
24 //#include <Mmfcodec.h> |
|
25 |
|
26 EXPORT_C TCodecProcessResult CAdvancedAudioDecoder::ProcessHwL(CMMFBuffer& aSrc, CMMFBuffer& aDst) |
|
27 { |
|
28 DP0(_L ("CAdvancedAudioDecoder::ProcessAccelL ---start")); |
|
29 |
|
30 TMMFPtr8 codecSrc; |
|
31 TMMFPtr8 codecDst; |
|
32 |
|
33 TCodecProcessResult result; |
|
34 result.iStatus = TCodecProcessResult::EProcessIncomplete; |
|
35 |
|
36 //convert from generic CMMFBuffer to CMMFDataBuffer |
|
37 iSrc = static_cast<const CMMFDataBuffer*>(&aSrc); |
|
38 iDst = static_cast<CMMFDataBuffer*>(&aDst); |
|
39 |
|
40 const TUint srcLen = iSrc->Data().Length(); |
|
41 const TUint dstAvail = iDst->Data().MaxLength() - iDst->Position(); |
|
42 |
|
43 if (!dstAvail) |
|
44 User::Leave(KErrArgument); |
|
45 |
|
46 TUint dstAdded = 0; |
|
47 TUint srcUsed = 0; |
|
48 |
|
49 TInt srcPos = iSrc->Position(); |
|
50 TInt dstPos = iDst->Position(); |
|
51 |
|
52 // DP4(_L ("CAdvancedAudioDecoder::ProcessAccelL: srcLen[%d], srcPos[%d] dstPos[%d], dstAvailLen[%d]"), srcLen, srcPos, dstPos, dstAvailLen); |
|
53 |
|
54 while ((dstAdded < dstAvail) && (srcPos + srcUsed < srcLen)) |
|
55 { |
|
56 codecSrc.Set(iSrc->Data()); |
|
57 codecDst.Set(iDst->Data()); |
|
58 codecDst.SetLength(codecDst.MaxLength()); |
|
59 codecSrc.Shift(srcPos + srcUsed); |
|
60 codecDst.Shift(dstPos + dstAdded); |
|
61 |
|
62 // DP2(_L ("CAdvancedAudioDecoder::ProcessAccelL: before ProcessDecodeL offsetting srcptr to srcPos[%d]+srcUsed[%d]"), srcPos, srcUsed); |
|
63 |
|
64 ProcessParseL(&codecSrc, &codecDst); |
|
65 if (!iEnabled) |
|
66 { // output buffer is invalid when stopped - don't use it |
|
67 DP0(_L ("CAdvancedAudioDecoder::ProcessAccelL --- end - disabled - returning")); |
|
68 result.iStatus = TCodecProcessResult::EProcessComplete; |
|
69 return result; |
|
70 } |
|
71 |
|
72 dstAdded += codecDst.Length(); |
|
73 srcUsed += codecSrc.Length(); |
|
74 |
|
75 if (iMarkPlayEnd) |
|
76 { // don't parse any more data |
|
77 DP0(_L ("CAdvancedAudioDecoder::ProcessAccelL --- mark play end breaking")); |
|
78 break; |
|
79 } |
|
80 } |
|
81 |
|
82 result.iSrcBytesProcessed = srcUsed; |
|
83 result.iDstBytesAdded = dstAdded; |
|
84 |
|
85 if (result.iDstBytesAdded && (result.iSrcBytesProcessed + srcPos >= srcLen)) |
|
86 result.iStatus = TCodecProcessResult::EProcessComplete; |
|
87 else if (result.iDstBytesAdded < dstAvail) |
|
88 result.iStatus = TCodecProcessResult::EDstNotFilled; |
|
89 |
|
90 iDst->Data().SetLength(iDst->Position()+result.iDstBytesAdded); |
|
91 |
|
92 DP0(_L ("CAdvancedAudioDecoder::ProcessAccelL ---end")); |
|
93 return result; |
|
94 } |
|
95 |
|
96 // ----------------------------------------------------------------------------- |
|
97 // CAdvancedAudioDecoder::ProcessParseL |
|
98 // ProcessParseL method that shall be called from the ProcessL method to perform |
|
99 // the parsing of the encoded data |
|
100 // ----------------------------------------------------------------------------- |
|
101 EXPORT_C void CAdvancedAudioDecoder::ProcessParseL(TMMFPtr8* aSrc, TMMFPtr8* aDst) |
|
102 { |
|
103 DP0(_L ("CAdvancedAudioDecoder::ProcessParseL ---start")); |
|
104 TUint8* srcPtr = NULL; |
|
105 TUint8* dstPtr = NULL; |
|
106 TInt srcLen = aSrc->Length(); |
|
107 TInt dstAvail= aDst->Length(); |
|
108 TInt srcUsed = 0; |
|
109 TInt dstUsed = 0; |
|
110 |
|
111 //************************************************** |
|
112 //* Get Input Data: Only want to process more input |
|
113 //* data if the output buffer is empty. |
|
114 //************************************************** |
|
115 |
|
116 if(iOutBufferCount == 0) |
|
117 { |
|
118 srcPtr = (TUint8*) aSrc->Ptr(); |
|
119 |
|
120 //************************************************* |
|
121 //* If the input buffer is empty, and there is |
|
122 //* enough data in the input stream, then use the |
|
123 //* data from the input stream. Else must append |
|
124 //* available input data to the input buffer. |
|
125 //************************************************* |
|
126 |
|
127 srcPtr = PrepareInFrame(srcPtr, srcLen, srcUsed); |
|
128 |
|
129 if (iInBufferCount > 0) |
|
130 { |
|
131 srcLen = iInBufferCount; |
|
132 } |
|
133 } |
|
134 |
|
135 //************************************************* |
|
136 //* If there is enough input data, then determine |
|
137 //* where the output should go (output stream or |
|
138 //* output buffer if output stream doesn't have |
|
139 //* enough room). Then parse the data. |
|
140 //************************************************* |
|
141 |
|
142 if(srcPtr) |
|
143 { |
|
144 // Determine where to put output data |
|
145 dstPtr = (TUint8*) aDst->Ptr(); |
|
146 dstUsed = iOutFrameLength; |
|
147 TInt inLen, outLen; |
|
148 |
|
149 outLen = dstAvail; |
|
150 |
|
151 if(dstAvail < iOutFrameLength) |
|
152 { |
|
153 // DP2(_L ("CAdvancedAudioDecoder::ProcessParseL: dstAvail[%d], iOutFrameLength[%d]"), dstAvail, iOutFrameLength); |
|
154 |
|
155 dstPtr = iOutBuffer; |
|
156 outLen = iOutFrameLength; // Set the dst length to the new length |
|
157 } |
|
158 |
|
159 // Parse one frame |
|
160 inLen = srcLen; |
|
161 |
|
162 ParseL(srcPtr, inLen, dstPtr, outLen); |
|
163 if (!iEnabled) |
|
164 { // aDst and dstPtr invalid when stopped - don't use |
|
165 DP0(_L ("CAdvancedAudioDecoder::ProcessParseL --- end - disabled - returning")); |
|
166 return; |
|
167 } |
|
168 |
|
169 // adjust in counters |
|
170 if (iInBufferCount > 0) |
|
171 { |
|
172 // if parse from the temp buf, adjust indexes |
|
173 // DP3(_L ("CAdvancedAudioDecoder::ProcessParseL adjusting tempbuf after parse count[%d] indx[%d] used[%d]"), |
|
174 // iInBufferCount, iInBufferIndx, inLen); |
|
175 iInBufferCount -= inLen; |
|
176 iInBufferIndx += inLen; |
|
177 } |
|
178 else |
|
179 { |
|
180 srcUsed = inLen; |
|
181 } |
|
182 |
|
183 if ((inLen == 0) && (iSrc->LastBuffer())) |
|
184 { |
|
185 srcUsed = srcLen; |
|
186 dstUsed = 0; |
|
187 } |
|
188 |
|
189 // adjust out counters |
|
190 dstUsed = outLen; |
|
191 |
|
192 if (dstAvail < iOutFrameLength) |
|
193 iOutBufferCount = outLen; |
|
194 } |
|
195 |
|
196 //************************************************* |
|
197 //* If any data is stored in the output buffer, |
|
198 //* then output as much of it as well fit in the |
|
199 //* output stream. |
|
200 //************************************************* |
|
201 |
|
202 if(iOutBufferCount > 0) |
|
203 { |
|
204 dstUsed = Min (iOutBufferCount, dstAvail); |
|
205 TPtrC8 outPtr (iOutBufferPtr, dstUsed); |
|
206 |
|
207 aDst->SetLength(0); |
|
208 aDst->Append (outPtr); |
|
209 |
|
210 iOutBufferCount -= dstUsed; |
|
211 iOutBufferPtr += dstUsed; |
|
212 |
|
213 if(iOutBufferCount == 0) |
|
214 { |
|
215 iOutBufferPtr = iOutBuffer; |
|
216 } |
|
217 } |
|
218 |
|
219 |
|
220 //************************************************* |
|
221 //* Modify the length attributes of the source and |
|
222 //* destination data streams to inform the caller |
|
223 //* of how much data was used in each buffer. |
|
224 //************************************************* |
|
225 |
|
226 |
|
227 // DP2(_L ("CAdvancedAudioDecoder::ProcessParseL maxlen[%d] used[%d]"), aSrc->MaxLength(), srcUsed); |
|
228 aSrc->SetLength(srcUsed); |
|
229 aDst->SetLength(dstUsed); |
|
230 DP0(_L ("CAdvancedAudioDecoder::ProcessParseL ---end")); |
|
231 } |
|
232 |
|
233 // ----------------------------------------------------------------------------- |
|
234 // CAdvancedAudioDecoder::PrepareInFrame |
|
235 // ----------------------------------------------------------------------------- |
|
236 EXPORT_C TUint8* CAdvancedAudioDecoder::PrepareInFrame(TUint8* aSrc, TInt aSrcLen, TInt& aSrcUsed) |
|
237 { |
|
238 // DP0(_L ("CAdvancedAudioDecoder::PrepareInFrame ---start")); |
|
239 // note: aSrcUsed returns how much data is used from source buffer. |
|
240 // when it reaches the value of aSrcLen, we will be provided the next input buffer. |
|
241 // while we are decoding from the temp buf, we set it to 0 because we have not decoded any from |
|
242 // the current src buffer. |
|
243 TUint8* dataPtr = NULL; |
|
244 aSrcUsed = 0; |
|
245 |
|
246 if (iInBufferCount == 0) |
|
247 { |
|
248 // decoding from src buffer |
|
249 // DP2(_L("CAdvancedAudioDecoder::PrepareInFrame, aSrc[0x%x] aSrcLen[%d]"), aSrc, aSrcLen); |
|
250 |
|
251 iInBufferFilled = EFalse; |
|
252 iInBufferIndx = 0; |
|
253 |
|
254 if (aSrcLen >= iMaxFrameSize) |
|
255 { // if enough data in input buffer, just use input buffer |
|
256 // DP2(_L ("CAdvancedAudioDecoder::PrepareInFrame using input buffer[0x%x][0x%x]"), aSrc, aSrc[0]); |
|
257 dataPtr = aSrc; |
|
258 } |
|
259 else if (iSrc->LastBuffer()) |
|
260 { // if input buffer is last buffer, then use it |
|
261 // DP2(_L ("CAdvancedAudioDecoder::PrepareInFrame using last input buffer[0x%x][0x%x]"), aSrc, aSrc[0]); |
|
262 dataPtr = aSrc; |
|
263 } |
|
264 else |
|
265 { |
|
266 // save input data |
|
267 // When not enough data in input buffer, move it to temp buffer |
|
268 // DP5(_L ("CAdvancedAudioDecoder::PrepareInFrame moving to temp buffer[0x%x] src[0x%x]d0[0x%x]srclen[%d]dend[0x%x]"), |
|
269 // iInBuffer, aSrc, aSrc[0], aSrcLen, aSrc[aSrcLen-1]); |
|
270 Mem::Copy(iInBuffer, aSrc, aSrcLen); |
|
271 iInBufferCount = aSrcLen; |
|
272 aSrcUsed = aSrcLen; // inform that we used input buffer so we will get a new input buffer |
|
273 iInBufferIndx = 0; // index will move with amount of data decoded |
|
274 dataPtr = NULL; // NULL prevents decoder from decoding. We need to fill rest of temp buffer |
|
275 iUsedInBuffer = iInBufferCount; |
|
276 iSavedBytesCopiedFromSrc = 0; |
|
277 } |
|
278 } |
|
279 else |
|
280 { |
|
281 // decoding from temp buffer |
|
282 dataPtr = iInBuffer+iInBufferIndx; // index is adjusted after decode and ptr is data to decode |
|
283 // DP4(_L ("CAdvancedAudioDecoder::PrepareInFrame using temp buffer dataPtr[0x%x] iInBufferIndx[%d] iInBufferCount[%d] iInBufferFilled[%d]"), |
|
284 // dataPtr, iInBufferIndx, iInBufferCount, iInBufferFilled); |
|
285 |
|
286 if (!iInBufferFilled) |
|
287 { |
|
288 // need to fill rest of temp buffer |
|
289 TInt bytesToCopy = iSizeOfInBuffer-iUsedInBuffer; |
|
290 TInt bytesAvailable = aSrcLen; |
|
291 |
|
292 if (bytesAvailable < bytesToCopy) |
|
293 { |
|
294 bytesToCopy = bytesAvailable; |
|
295 } |
|
296 |
|
297 if (bytesToCopy) |
|
298 { |
|
299 // only do this once - partial input buffer means last buffer |
|
300 // DP5(_L ("CAdvancedAudioDecoder::PrepareInFrame putting more to temp buffer dstptr[0x%x] srcptr[0x%x]d0[0x%x]cnt[%d]dend[0x%x]"), |
|
301 // dataPtr+iUsedInBuffer, aSrc, aSrc[0], bytesToCopy, iInBuffer[KSizeOfInBuffer-1]); |
|
302 Mem::Copy(dataPtr+iUsedInBuffer, aSrc, bytesToCopy); |
|
303 iSavedBytesCopiedFromSrc = bytesToCopy; // save byte count used from this src buffer |
|
304 iInBufferCount += bytesToCopy; |
|
305 iUsedInBuffer += bytesToCopy; |
|
306 iInBufferFilled = ETrue; |
|
307 } |
|
308 } |
|
309 else |
|
310 { |
|
311 // temp buffer is filled and we are decoding from it |
|
312 TInt decodeOffsetIntoInputBuf = iSavedBytesCopiedFromSrc - iInBufferCount; |
|
313 // DP1(_L ("CAdvancedAudioDecoder::PrepareInFrame using temp buf aSrcUsed[%d]"), decodeOffsetIntoInputBuf); |
|
314 |
|
315 if (decodeOffsetIntoInputBuf >= 0) |
|
316 { |
|
317 // within the temp buffer, we have decoded all of the prior src buffer's data |
|
318 // we are decoding into the data copied from the current input buffer |
|
319 // so we can set the pointer to start using input buffer again |
|
320 dataPtr = NULL; // NULL prevents decoder from decoding. Need to let src get updated by aSrcUsed |
|
321 iInBufferCount = 0; |
|
322 aSrcUsed = decodeOffsetIntoInputBuf; |
|
323 // DP1(_L ("CAdvancedAudioDecoder::PrepareInFrame using inbuffer again, aSrcUsed[%d]"), aSrcUsed); |
|
324 } |
|
325 else |
|
326 { |
|
327 aSrcUsed = 0; // here references current src buffer that we are not decoding from yet. |
|
328 // DP1(_L ("CAdvancedAudioDecoder::PrepareInFrame using inbuffer again, aSrcUsed[%d] b"), aSrcUsed); |
|
329 } |
|
330 } |
|
331 } |
|
332 |
|
333 return dataPtr; |
|
334 } |
|
335 |
|
336 // ----------------------------------------------------------------------------- |
|
337 // CAdvancedAudioDecoder::ParseL |
|
338 // ----------------------------------------------------------------------------- |
|
339 EXPORT_C void CAdvancedAudioDecoder::ParseL(TUint8* aSrc, TInt& aSrcUsed, TUint8* aDst, TInt& aDstLen) |
|
340 { |
|
341 DP1(_L ("CAdvancedAudioDecoder::ParseL [0x%x]"), aSrc[0]); |
|
342 TInt savedLen = aSrcUsed; |
|
343 TInt err = KErrNone; |
|
344 TInt inLen = aSrcUsed; |
|
345 // TAudioFrameInfo frameInfo; |
|
346 TInt frameLen; |
|
347 |
|
348 // Parse one frame |
|
349 |
|
350 err = FrameLength(aSrc, inLen, frameLen); |
|
351 aSrcUsed = frameLen; |
|
352 if (aSrcUsed > savedLen) |
|
353 { // in case util reports more bytes used than what is available at the end of the content |
|
354 aSrcUsed = savedLen; |
|
355 } |
|
356 |
|
357 if (!iRenderEnabled) |
|
358 { // seeking |
|
359 aDstLen = 0; |
|
360 } |
|
361 else |
|
362 { |
|
363 if (err == KErrNone) |
|
364 { |
|
365 Mem::Copy(aDst, aSrc, aSrcUsed); |
|
366 aDstLen = aSrcUsed; |
|
367 } |
|
368 } |
|
369 |
|
370 if (err != KErrNone) |
|
371 { |
|
372 aSrcUsed = 0; |
|
373 err = KErrCorrupt; |
|
374 } |
|
375 |
|
376 // DP2(_L ("CAdvancedAudioDecoder::ParseL after decode aSrcUsed[%d] aDstLen[%d]"), aSrcUsed, aDstLen); |
|
377 |
|
378 DP1(_L ("CAdvancedAudioDecoder::ParseL err [%d]"),err); |
|
379 |
|
380 if (err == KErrNone) |
|
381 { |
|
382 if (iFrameTable) |
|
383 { |
|
384 iFrameTable->SubmitTableEntry(iAccLen); // to add an entry for the frame actually decoded |
|
385 } |
|
386 } |
|
387 |
|
388 if (err == KErrCorrupt) |
|
389 { |
|
390 aDstLen = 0; |
|
391 // decode was not successful at this position, need to move forward because sync may still be found here. |
|
392 TInt syncPos = SeekSync(aSrc+1, savedLen-1); // decoder's seek returns 0 if not found, so we need to use our own seek function |
|
393 if (syncPos == savedLen-1) |
|
394 { // search whole buffer - no sync found - so indicate the rest of the data has been used |
|
395 aSrcUsed = savedLen; |
|
396 } |
|
397 else |
|
398 { |
|
399 aSrcUsed = syncPos+1; |
|
400 } |
|
401 err = KErrNone; |
|
402 } |
|
403 |
|
404 iAccLen += aSrcUsed; |
|
405 |
|
406 if(err != KErrNone) |
|
407 { // unrecoverable error |
|
408 if (iSrc->LastBuffer()) |
|
409 { // don't have to error on last buffer, just indicate all the data was used |
|
410 aSrcUsed = savedLen; |
|
411 } |
|
412 else |
|
413 { |
|
414 User::Leave(err); |
|
415 } |
|
416 } |
|
417 } |
|
418 |
|
419 // ----------------------------------------------------------------------------- |
|
420 // CAdvancedAudioDecoder::SeekSync |
|
421 // ----------------------------------------------------------------------------- |
|
422 TInt CAdvancedAudioDecoder::SeekSync(TUint8* /*aBuf*/, TInt /*aBufLen*/) |
|
423 { |
|
424 return KErrNotSupported; |
|
425 } |
|
426 |
|
427 TInt CAdvancedAudioDecoder::FrameLength(const TUint8* /*aBuf*/, TInt /*aBufLen*/, TInt& /*aFrameLength*/) |
|
428 { |
|
429 return KErrNotSupported; |
|
430 } |
|
431 |
|
432 |
|
433 // End of file |