|
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 |
|
25 |
|
26 // CONSTANTS |
|
27 |
|
28 // ============================ MEMBER FUNCTIONS =============================== |
|
29 |
|
30 // ----------------------------------------------------------------------------- |
|
31 // C++ default constructor can NOT contain any code, that |
|
32 // might leave. |
|
33 // ----------------------------------------------------------------------------- |
|
34 // |
|
35 EXPORT_C CAdvancedAudioDecoder::CAdvancedAudioDecoder( |
|
36 TInt aPriority) |
|
37 : CActive(aPriority), |
|
38 iState(EIdle), |
|
39 iSharedBuffers(NULL), |
|
40 iMMFDevSound(NULL), |
|
41 iObserver(NULL) |
|
42 { |
|
43 DP0(_L("CAdvancedAudioDecoder::CAdvancedAudioDecoder()")); |
|
44 |
|
45 iDecoderUtilityObserver = NULL; |
|
46 iFrameTable = NULL; |
|
47 } |
|
48 |
|
49 // Destructor |
|
50 EXPORT_C CAdvancedAudioDecoder::~CAdvancedAudioDecoder() |
|
51 { |
|
52 DP0(_L("CAdvancedAudioDecoder::~CAdvancedAudioDecoder()")); |
|
53 iRenderEnableConfig.Close(); |
|
54 iRenderDisableConfig.Close(); |
|
55 iMarkPlayEndConfig.Close(); |
|
56 iUnMarkPlayEndConfig.Close(); |
|
57 iEnableConfig.Close(); |
|
58 iDisableConfig.Close(); |
|
59 delete iConvertBuffer; |
|
60 delete iChannelAndSampleRateConverterFactory; |
|
61 } |
|
62 |
|
63 // ----------------------------------------------------------------------------- |
|
64 // CAdvancedAudioDecoder::SetDevSound |
|
65 // Sets the DevSound instance. |
|
66 // ----------------------------------------------------------------------------- |
|
67 // |
|
68 EXPORT_C void CAdvancedAudioDecoder::SetDevSound( |
|
69 CMMFDevSound& aDevSound) |
|
70 { |
|
71 iMMFDevSound = &aDevSound; |
|
72 } |
|
73 |
|
74 // ----------------------------------------------------------------------------- |
|
75 // CAdvancedAudioDecoder::SetObserver |
|
76 // Sets the observer instance. |
|
77 // ----------------------------------------------------------------------------- |
|
78 // |
|
79 EXPORT_C void CAdvancedAudioDecoder::SetObserver( |
|
80 MAdvancedAudioDecoderObserver& aObserver) |
|
81 { |
|
82 iObserver = &aObserver; |
|
83 } |
|
84 |
|
85 // ----------------------------------------------------------------------------- |
|
86 // CAdvancedAudioDecoder::SetDecoderUtilityObserver |
|
87 // Sets the observer instance. |
|
88 // ----------------------------------------------------------------------------- |
|
89 // |
|
90 EXPORT_C void CAdvancedAudioDecoder::SetDecoderUtilityObserver(MAdvancedAudioDecoderUtilityObserver& aDecoderUtilityObserver) |
|
91 { |
|
92 iDecoderUtilityObserver = &aDecoderUtilityObserver; |
|
93 } |
|
94 |
|
95 // ----------------------------------------------------------------------------- |
|
96 // CAdvancedAudioDecoder::SetSourceBuffers |
|
97 // Sets the source buffer for conversion operations. |
|
98 // ----------------------------------------------------------------------------- |
|
99 // |
|
100 EXPORT_C void CAdvancedAudioDecoder::SetSourceBuffers( |
|
101 RPointerArray<CMMFDataBuffer>* aBuffers) |
|
102 { |
|
103 iSharedBuffers = aBuffers; |
|
104 } |
|
105 |
|
106 // ----------------------------------------------------------------------------- |
|
107 // CAdvancedAudioDecoder::SetConfigL |
|
108 // Sets audio decoder settings and attributes |
|
109 // ----------------------------------------------------------------------------- |
|
110 // |
|
111 EXPORT_C void CAdvancedAudioDecoder::SetConfigL( |
|
112 TUint aSourceSampleRate, |
|
113 TUint aSourceChannels, |
|
114 TUint aSWConvertSampleRate, |
|
115 TUint aSWConvertChannels, |
|
116 const RArray<TInt>& aCodecConfigData, |
|
117 TInt aIndex) |
|
118 { |
|
119 DP0(_L("CAdvancedAudioDecoder::SetConfigL")); |
|
120 |
|
121 CodecConfig(const_cast<RArray<TInt>&>(aCodecConfigData)); |
|
122 |
|
123 QueueThisBuffer(aIndex); // will set iNextBuffer (current buffer) and update iSharedBufferIndex (to next buffer) |
|
124 |
|
125 if(aSourceSampleRate != aSWConvertSampleRate) // Sampling Rate Conversion is needed |
|
126 { |
|
127 if (!iChannelAndSampleRateConverterFactory) |
|
128 { |
|
129 iChannelAndSampleRateConverterFactory = new(ELeave) CMMFChannelAndSampleRateConverterFactory; |
|
130 iChannelAndSampleRateConverter = iChannelAndSampleRateConverterFactory->CreateConverterL(aSourceSampleRate, aSourceChannels, |
|
131 aSWConvertSampleRate, aSWConvertChannels); |
|
132 } |
|
133 iNeedsSWConversion = ETrue; |
|
134 } |
|
135 |
|
136 Enable(); |
|
137 } |
|
138 |
|
139 // ----------------------------------------------------------------------------- |
|
140 // CAdvancedAudioDecoder::FillBuffer |
|
141 // Request to fill the specified buffer with converted data. |
|
142 // ----------------------------------------------------------------------------- |
|
143 // |
|
144 EXPORT_C void CAdvancedAudioDecoder::FillBufferL( |
|
145 CMMFBuffer* aBuffer) |
|
146 { |
|
147 DP0(_L("CAdvancedAudioDecoder::FillBufferL")); |
|
148 iBufferToFill = aBuffer; |
|
149 iState = EDecoding; |
|
150 iStatus = KRequestPending; // service request would be made here and pending set by service provider |
|
151 SetActive(); |
|
152 Ready(KErrNone); |
|
153 } |
|
154 |
|
155 // ----------------------------------------------------------------------------- |
|
156 // CAdvancedAudioDecoder::Stop |
|
157 // Stops decoding process. |
|
158 // ----------------------------------------------------------------------------- |
|
159 // |
|
160 EXPORT_C void CAdvancedAudioDecoder::Stop() |
|
161 { |
|
162 DP0(_L("CAdvancedAudioDecoder::Stop")); |
|
163 |
|
164 iState = EIdle; |
|
165 Disable(); |
|
166 RenderEnable(); |
|
167 iEventPos = 0; |
|
168 |
|
169 // cancel any outstanding FrameTable Seeking event callback |
|
170 if (iFrameTable) |
|
171 { |
|
172 TInt err = iFrameTable->UnRegisterForEvent(CFrameTable::EPosReached, this); |
|
173 // Fix for the error ou1cimx1#137567 - SXUU-7S9SLD |
|
174 //TInt err1 = iFrameTable->UnRegisterForEvent(CFrameTable::EPlayWindowEndPosReached, this); |
|
175 //if (err|err1 != KErrNone) |
|
176 if (err != KErrNone) |
|
177 { |
|
178 //DP2(_L("CAdvancedAudioDecoder::Stop, UnRegisterForEvent errs[%d][%d]"), err, err1); |
|
179 DP1(_L("CAdvancedAudioDecoder::Stop, UnRegisterForEvent err[%d]"), err); |
|
180 } |
|
181 } |
|
182 } |
|
183 |
|
184 EXPORT_C TInt CAdvancedAudioDecoder::SetSourceReference(TUint aTimeMs, TUint aPos) |
|
185 { |
|
186 if (!iFrameTable) |
|
187 return KErrNotSupported; |
|
188 |
|
189 return iFrameTable->SetSourceReference(aTimeMs, aPos); |
|
190 } |
|
191 |
|
192 // ----------------------------------------------------------------------------- |
|
193 // CAdvancedAudioDecoder::FindFramePosFromTime |
|
194 // ----------------------------------------------------------------------------- |
|
195 // |
|
196 EXPORT_C TInt CAdvancedAudioDecoder::FindFramePosFromTime(TUint& aTimeMs, TUint& aPos) |
|
197 { |
|
198 if (!iFrameTable) |
|
199 return KErrNotSupported; |
|
200 |
|
201 return iFrameTable->FindFramePosFromTime(aTimeMs, aPos); |
|
202 } |
|
203 |
|
204 EXPORT_C TInt CAdvancedAudioDecoder::FindFrameTimeFromPos(TUint& aTime, TUint& aPos) |
|
205 { |
|
206 if (!iFrameTable) |
|
207 return KErrNotSupported; |
|
208 |
|
209 return iFrameTable->FindFrameTimeFromPos(aTime, aPos); |
|
210 } |
|
211 |
|
212 |
|
213 // ----------------------------------------------------------------------------- |
|
214 // CAdvancedAudioDecoder::LastFramePos |
|
215 // ----------------------------------------------------------------------------- |
|
216 // |
|
217 EXPORT_C TInt CAdvancedAudioDecoder::LastFramePos(TUint& aPos) |
|
218 { |
|
219 if (!iFrameTable) |
|
220 return KErrNotSupported; |
|
221 |
|
222 return iFrameTable->LastFramePos(aPos); |
|
223 } |
|
224 |
|
225 // ----------------------------------------------------------------------------- |
|
226 // CAdvancedAudioDecoder::LastFrameTime |
|
227 // ----------------------------------------------------------------------------- |
|
228 // |
|
229 EXPORT_C TInt CAdvancedAudioDecoder::LastFrameTime(TUint& aTimeMs) |
|
230 { |
|
231 if (!iFrameTable) |
|
232 return KErrNotSupported; |
|
233 |
|
234 return iFrameTable->LastFrameTime(aTimeMs); |
|
235 } |
|
236 |
|
237 // ----------------------------------------------------------------------------- |
|
238 // CAdvancedAudioDecoder::ResetTable |
|
239 // ----------------------------------------------------------------------------- |
|
240 // |
|
241 EXPORT_C TInt CAdvancedAudioDecoder::ResetTable() |
|
242 { |
|
243 if (!iFrameTable) |
|
244 return KErrNotSupported; |
|
245 |
|
246 iFrameTable->ResetTable(); |
|
247 return KErrNone; |
|
248 } |
|
249 |
|
250 // ----------------------------------------------------------------------------- |
|
251 // CAdvancedAudioDecoder::SeekToTimeMs |
|
252 // ----------------------------------------------------------------------------- |
|
253 // |
|
254 EXPORT_C TInt CAdvancedAudioDecoder::SeekToTimeMs(TUint aTimeMs) |
|
255 { |
|
256 if (!iFrameTable) |
|
257 return KErrNotSupported; |
|
258 if (aTimeMs == KMaxTUint) |
|
259 { |
|
260 // Only other place that we unregister is when we stop the decoder. |
|
261 // Here we need to unregister explicitly such as when there is an outstanding |
|
262 // seek and we seek again, but if we are not playing yet, we won't stop the output |
|
263 // and unregister outstanding events by stopping the output. |
|
264 DP0(_L("CAdvancedAudioDecoder::SeekToTimeMs unregistering events")); |
|
265 TInt status1 = iFrameTable->UnRegisterForEvent(CFrameTable::EPosReached, this); |
|
266 return status1; |
|
267 } |
|
268 |
|
269 RenderDisable(); |
|
270 iSeekToTimeMs = aTimeMs; |
|
271 return iFrameTable->RegisterForEvent(CFrameTable::EPosReached, this, aTimeMs); |
|
272 } |
|
273 |
|
274 // ----------------------------------------------------------------------------- |
|
275 // CAdvancedAudioDecoder::SetPlayEndTimeMs |
|
276 // ----------------------------------------------------------------------------- |
|
277 // |
|
278 EXPORT_C TInt CAdvancedAudioDecoder::SetPlayWindowEndTimeMs(TUint aTimeMs) |
|
279 { |
|
280 TInt status = KErrNotSupported; |
|
281 if (iFrameTable) |
|
282 { |
|
283 if (aTimeMs == 0) |
|
284 { |
|
285 status = iFrameTable->UnRegisterForEvent(CFrameTable::EPlayWindowEndPosReached, this); |
|
286 } |
|
287 else |
|
288 { |
|
289 status = iFrameTable->RegisterForEvent(CFrameTable::EPlayWindowEndPosReached, this, aTimeMs); |
|
290 } |
|
291 } |
|
292 return status; |
|
293 } |
|
294 |
|
295 // ----------------------------------------------------------------------------- |
|
296 // CAdvancedAudioDecoder::BitRate |
|
297 // ----------------------------------------------------------------------------- |
|
298 // |
|
299 EXPORT_C TInt CAdvancedAudioDecoder::BitRate() |
|
300 { |
|
301 if (!iFrameTable) |
|
302 return KErrNotSupported; |
|
303 |
|
304 return iFrameTable->Bitrate(); |
|
305 } |
|
306 |
|
307 // ----------------------------------------------------------------------------- |
|
308 // CAdvancedAudioDecoder::EnableDecodeIntervalEvent |
|
309 // ----------------------------------------------------------------------------- |
|
310 // |
|
311 EXPORT_C TInt CAdvancedAudioDecoder::EnableDecodeIntervalEvent(TBool aEnable, TUint aTimeMs) |
|
312 { |
|
313 if (!iFrameTable) |
|
314 return KErrNotSupported; |
|
315 else |
|
316 { |
|
317 if (aEnable) |
|
318 return iFrameTable->RegisterForEvent(CFrameTable::EDecodeInterval, this, aTimeMs); |
|
319 else |
|
320 return iFrameTable->UnRegisterForEvent(CFrameTable::EDecodeInterval, this); |
|
321 } |
|
322 } |
|
323 |
|
324 |
|
325 // ----------------------------------------------------------------------------- |
|
326 // CAdvancedAudioDecoder::HandleFrameTableEvent |
|
327 // ----------------------------------------------------------------------------- |
|
328 // |
|
329 EXPORT_C TInt CAdvancedAudioDecoder::HandleFrameTableEvent(CFrameTable::TFrameTableEvent aEvent) |
|
330 { |
|
331 TInt status = KErrNone; |
|
332 switch (aEvent) |
|
333 { |
|
334 case CFrameTable::EPlayWindowEndPosReached: |
|
335 case CFrameTable::EPosReached: |
|
336 RenderEnable(); |
|
337 if (iDecoderUtilityObserver) |
|
338 { |
|
339 if (aEvent == CFrameTable::EPosReached) |
|
340 { |
|
341 DP0(_L("CAdvancedAudioDecoder::HandleFrameTableEvent, EPosReached")); |
|
342 // to allow the iTimePositionInMicroSecs to be updated to seek time in controller |
|
343 TInt offsets; |
|
344 TUint pos; |
|
345 status = iDecoderUtilityObserver->GetOffsets(offsets); |
|
346 status = iFrameTable->GetLastPosEvent(pos); |
|
347 DP2(_L("CAdvancedAudioDecoder::HandleFrameTableEvent, pos = %U, offsets = %U"),pos,offsets); |
|
348 iEventPos = pos + offsets; |
|
349 iDecoderUtilityObserver->SeekPositionReached(iSeekToTimeMs); |
|
350 } |
|
351 else |
|
352 { // play window end |
|
353 DP0(_L("CAdvancedAudioDecoder::HandleFrameTableEvent play window end reached")); |
|
354 iDecoderUtilityObserver->PlayWindowEndPositionReached(); |
|
355 MarkPlayEnd(); |
|
356 } |
|
357 } |
|
358 break; |
|
359 |
|
360 case CFrameTable::EDecodeInterval: |
|
361 DP0(_L("CAdvancedAudioDecoder::HandleFrameTableEvent, EDecodeInterval")); |
|
362 |
|
363 if (iDecoderUtilityObserver) |
|
364 { |
|
365 iDecoderUtilityObserver->DecodeIntervalEvent(); |
|
366 } |
|
367 |
|
368 break; |
|
369 |
|
370 default: |
|
371 User::Panic(_L("CAdvancedAudioDecoder::HandleFrameTableEvent, Unexpected event"), KErrArgument); |
|
372 break; |
|
373 } |
|
374 |
|
375 return status; |
|
376 } |
|
377 |
|
378 // ----------------------------------------------------------------------------- |
|
379 // CAdvancedAudioDecoder::Ready |
|
380 // Utility function to post a request complete |
|
381 // ----------------------------------------------------------------------------- |
|
382 // |
|
383 void CAdvancedAudioDecoder::Ready( |
|
384 const TInt aStatus) |
|
385 { |
|
386 TRequestStatus* stat = &iStatus; |
|
387 User::RequestComplete(stat, aStatus); |
|
388 } |
|
389 |
|
390 |
|
391 // ----------------------------------------------------------------------------- |
|
392 // CAdvancedAudioDecoder::QueueThisBuffer |
|
393 // gets buffer at aBufferIndex ready for decoding |
|
394 // ----------------------------------------------------------------------------- |
|
395 // |
|
396 EXPORT_C void CAdvancedAudioDecoder::QueueThisBuffer(TUint aBufferIndex) |
|
397 { |
|
398 iNextBuffer = (*iSharedBuffers)[aBufferIndex]; |
|
399 |
|
400 DP4(_L("CAdvancedAudioDecoder::QueueThisBuffer, Index[%d] [%x] last[%d] pos[%d]"), |
|
401 aBufferIndex, static_cast<CMMFDataBuffer*>(iNextBuffer)->Data().Ptr(), iNextBuffer->LastBuffer(), iNextBuffer->Position()); |
|
402 |
|
403 iSharedBufferIndex = aBufferIndex + 1; |
|
404 |
|
405 if (iSharedBufferIndex == iSharedBuffers->Count()) |
|
406 { |
|
407 iSharedBufferIndex = 0; |
|
408 } |
|
409 |
|
410 iFrameTable->ShrinkTable(); |
|
411 } |
|
412 |
|
413 // ----------------------------------------------------------------------------- |
|
414 // CAdvancedAudioDecoder::NextSharedBufferL |
|
415 // Determine the next available shared buffer from the pool of shared buffers |
|
416 // iNextBuffer is actually the current buffer in use |
|
417 // iSharedBufferIndex points to the next buffer to be used |
|
418 // ----------------------------------------------------------------------------- |
|
419 // |
|
420 void CAdvancedAudioDecoder::NextSharedBufferL() |
|
421 { |
|
422 CMMFBuffer* refillBuffer = NULL; |
|
423 // index is the next buffer, index-1 is current buffer, check 2 buffers back from the one being selected |
|
424 TInt checkBufIndex = iSharedBufferIndex-2; |
|
425 |
|
426 if (checkBufIndex < 0) |
|
427 { |
|
428 checkBufIndex = checkBufIndex+iSharedBuffers->Count(); |
|
429 } |
|
430 |
|
431 if ((*iSharedBuffers)[checkBufIndex]->Status() == EBeingEmptied) |
|
432 { |
|
433 if (iSharedBuffers->Count() <= 2) |
|
434 { |
|
435 DP1(_L("CAdvancedAudioDecoder::NextSharedBufferL leave, EBeingEmptied is used on Count[%d]"), iSharedBuffers->Count()); |
|
436 User::Leave(KErrAbort); |
|
437 } |
|
438 DP2(_L("CAdvancedAudioDecoder::NextSharedBufferL, index[%d] [%x] is EBeingEmptied"), |
|
439 checkBufIndex, static_cast<CMMFDataBuffer*>((*iSharedBuffers)[checkBufIndex])->Data().Ptr() ); |
|
440 refillBuffer = (*iSharedBuffers)[checkBufIndex]; |
|
441 } |
|
442 if (refillBuffer) |
|
443 { |
|
444 iObserver->RefillBuffer(refillBuffer); |
|
445 } |
|
446 if ((*iSharedBuffers)[iSharedBufferIndex]->Status() == EFull) |
|
447 { |
|
448 QueueThisBuffer(iSharedBufferIndex); |
|
449 DP1(_L("CAdvancedAudioDecoder::NextSharedBufferL, After Increment, index[%d]"), iSharedBufferIndex); |
|
450 } |
|
451 else |
|
452 { |
|
453 DP2(_L("CAdvancedAudioDecoder::NextSharedBufferL - not ready, Index[%d] [%x]"), |
|
454 iSharedBufferIndex, static_cast<CMMFDataBuffer*>((*iSharedBuffers)[iSharedBufferIndex])->Data().Ptr() ); |
|
455 QueueThisBuffer(iSharedBufferIndex); // we should still have the buffer ready to be used when it is filled |
|
456 User::Leave(KErrBufferNotReady); |
|
457 } |
|
458 } |
|
459 |
|
460 // ----------------------------------------------------------------------------- |
|
461 // CAdvancedAudioDecoder::RunL |
|
462 // Invoke by the active scheduler when a request completes |
|
463 // ----------------------------------------------------------------------------- |
|
464 // |
|
465 EXPORT_C void CAdvancedAudioDecoder::RunL() |
|
466 { |
|
467 DP0(_L("CAdvancedAudioDecoder::RunL")); |
|
468 if (iState == EDecoding) |
|
469 { |
|
470 TRAPD(err,HandleFillBufferL()); |
|
471 if (err) // if error is encountered, an event is generated and the playback is paused. |
|
472 { |
|
473 iObserver->SendEvent(TMMFEvent(KMMFEventCategoryPlaybackComplete, err)); |
|
474 } |
|
475 } |
|
476 } |
|
477 |
|
478 // ----------------------------------------------------------------------------- |
|
479 // CAdvancedAudioDecoder::HandleFillBufferL |
|
480 // Handle the request to fill the specified buffer with converted data. |
|
481 // Fill next buffer with audio data. If soft codec, data must first be decoded. |
|
482 // If source buffer is depleted, a request to the controller is sent to refill |
|
483 // the buffer with more data and the next source buffer is used. |
|
484 // ----------------------------------------------------------------------------- |
|
485 // |
|
486 EXPORT_C void CAdvancedAudioDecoder::HandleFillBufferL() |
|
487 { |
|
488 DP3(_L("CAdvancedAudioDecoder::HandleFillBufferL ptr[%x] iRenderEnabled[%d] Position[%d]"), static_cast<CMMFDataBuffer*>(iNextBuffer)->Data().Ptr(), iRenderEnabled, iNextBuffer->Position()); |
|
489 DP3(_L("CAdvancedAudioDecoder::HandleFillBufferL frm#[%d] d0[%x] dp[%x]"), static_cast<CMMFDataBuffer*>(iNextBuffer)->FrameNumber(), static_cast<CMMFDataBuffer*>(iNextBuffer)->Data().Ptr()[0], |
|
490 static_cast<CMMFDataBuffer*>(iNextBuffer)->Data().Ptr()[iNextBuffer->Position()]); |
|
491 |
|
492 iBufferToFill->SetPosition(0); |
|
493 static_cast<CMMFDataBuffer*>(iBufferToFill)->Data().SetLength(0); |
|
494 iBufferToFill->SetLastBuffer(EFalse); |
|
495 |
|
496 TCodecProcessResult result; |
|
497 TBool moreProcessing = ETrue; |
|
498 |
|
499 while (moreProcessing) |
|
500 { |
|
501 TRAPD(err, result = ProcessL(*iNextBuffer, *iBufferToFill)); |
|
502 DP4(_L ("CAdvancedAudioDecoder::HandleFillBufferL - ProcessL stat[%d] result[%d] iEnabled[%d] iMarkPlayEnd[%d]"), |
|
503 err, result, iEnabled, iMarkPlayEnd); |
|
504 if (!iEnabled) |
|
505 { // output buffers are invalid when stopped - don't use them |
|
506 DP0(_L ("CAdvancedAudioDecoder::HandleFillBufferL - disabled - returning")); |
|
507 return; |
|
508 } |
|
509 |
|
510 if (err != 0) |
|
511 { |
|
512 if (err == KErrCorrupt) |
|
513 { // go ahead and use corrupt if the codec determines the data is corrupt. |
|
514 User::Leave(KErrCorrupt); |
|
515 } |
|
516 else |
|
517 { // don't use KErrDied or controller will pause |
|
518 User::Leave(KErrGeneral); |
|
519 } |
|
520 } |
|
521 |
|
522 if (iMarkPlayEnd) |
|
523 { |
|
524 DP0(_L ("CAdvancedAudioDecoder::HandleFillBufferL marking play end")); |
|
525 iNextBuffer->SetLastBuffer(ETrue); |
|
526 iMarkPlayEnd = EFalse; |
|
527 result.iStatus = TCodecProcessResult::EEndOfData; |
|
528 } |
|
529 // DP5(_L ("CAdvancedAudioDecoder::HandleFillBufferL after decode istatus[%d] iSrcBytesProcessed[%d] iDstBytesAdded[%d] srcPosition[%d] dstPosition[%d]"), |
|
530 // result.iStatus, result.iSrcBytesProcessed, result.iDstBytesAdded, iNextBuffer->Position(), iBufferToFill->Position()); |
|
531 |
|
532 TInt bytesInDstBuf = iBufferToFill->Position()+result.iDstBytesAdded; |
|
533 TInt bytesUsedFromSrcBuf = iNextBuffer->Position()+result.iSrcBytesProcessed; |
|
534 DP3(_L("CAdvancedAudioDecoder::HandleFillBufferL bytesUsedFromSrcBuf[%d] Position[%d] iSrcBytesProcessed[%d]"), |
|
535 bytesUsedFromSrcBuf, iNextBuffer->Position(), result.iSrcBytesProcessed); |
|
536 |
|
537 if ((result.iStatus == TCodecProcessResult::EProcessComplete || |
|
538 result.iStatus == TCodecProcessResult::EEndOfData || |
|
539 result.iStatus == TCodecProcessResult::EDstNotFilled) && iNextBuffer->LastBuffer()) |
|
540 { |
|
541 iBufferToFill->SetPosition(bytesInDstBuf); |
|
542 iNextBuffer->SetPosition(bytesUsedFromSrcBuf); |
|
543 DP2(_L("CAdvancedAudioDecoder::HandleFillBufferL set pos[%d] in src buf[0x%x]"), |
|
544 bytesUsedFromSrcBuf, static_cast<CMMFDataBuffer*>(iNextBuffer)->Data().Ptr()); |
|
545 |
|
546 DP0(_L ("CAdvancedAudioDecoder::HandleFillBufferL setting output buffer as last buffer")); |
|
547 iBufferToFill->SetLastBuffer(ETrue); |
|
548 moreProcessing = EFalse; |
|
549 } |
|
550 else |
|
551 { |
|
552 switch (result.iStatus) |
|
553 { |
|
554 case TCodecProcessResult::EProcessComplete: |
|
555 // finished processing input buffer, all data in output buffer |
|
556 case TCodecProcessResult::EDstNotFilled: |
|
557 // the output buffer is not full |
|
558 case TCodecProcessResult::EProcessIncomplete: |
|
559 // the output buffer was filled before all the input buffer was processed |
|
560 { |
|
561 iBufferToFill->SetPosition(bytesInDstBuf); |
|
562 iNextBuffer->SetPosition(bytesUsedFromSrcBuf); |
|
563 DP2(_L("CAdvancedAudioDecoder::HandleFillBufferL set pos[%d] in src buf[0x%x]"), |
|
564 bytesUsedFromSrcBuf, static_cast<CMMFDataBuffer*>(iNextBuffer)->Data().Ptr()); |
|
565 |
|
566 |
|
567 TInt srclength = static_cast<CMMFDataBuffer*>(iNextBuffer)->Data().Length(); |
|
568 TInt dstlength = static_cast<CMMFDataBuffer*>(iBufferToFill)->Data().Length(); |
|
569 TInt dstmaxlength = static_cast<CMMFDataBuffer*>(iBufferToFill)->Data().MaxLength(); |
|
570 |
|
571 // bytesUsedFromSrcBuf should always be <= iNextBuffer's length |
|
572 if (bytesUsedFromSrcBuf == srclength) |
|
573 { |
|
574 // all input buffer used |
|
575 if (iNextBuffer->LastBuffer()) |
|
576 { |
|
577 DP0(_L ("CAdvancedAudioDecoder::HandleFillBufferL all src used - setting output last buffer")); |
|
578 iBufferToFill->SetLastBuffer(ETrue); |
|
579 moreProcessing = EFalse; |
|
580 } |
|
581 else |
|
582 { |
|
583 // for streaming model keep this used buffer until we start decoding from the next buffer |
|
584 // so we can be sure to have entries in the seek table for the next buffer for pause resume cases |
|
585 // for which we have non-seekable sources. |
|
586 // if we did send it to be refilled, we might pause before we start decoding into the next buffer |
|
587 // we could be decoding from the temp holding buffer in the codec. |
|
588 // setting buffer status to EBeingEmptied indicates we are done with the buffer. |
|
589 // it will be sent for refill later by NextSharedBufferL(). |
|
590 static_cast<CMMFDataBuffer*>(iNextBuffer)->SetStatus(EBeingEmptied); |
|
591 NextSharedBufferL(); |
|
592 // length can only be <= maxlength |
|
593 if (dstlength == dstmaxlength) |
|
594 { |
|
595 moreProcessing = EFalse; |
|
596 } |
|
597 } |
|
598 } |
|
599 else |
|
600 { |
|
601 // length can only be <= maxlength |
|
602 if (dstlength == dstmaxlength) |
|
603 moreProcessing = EFalse; |
|
604 } |
|
605 |
|
606 break; |
|
607 } |
|
608 |
|
609 case TCodecProcessResult::EEndOfData: |
|
610 { |
|
611 DP0(_L("CAdvancedAudioDecoder::HandleFillBufferL, EEndOfData")); |
|
612 iBufferToFill->SetLastBuffer(ETrue); |
|
613 moreProcessing = EFalse; |
|
614 break; |
|
615 } |
|
616 |
|
617 default: |
|
618 { |
|
619 DP0(_L("CAdvancedAudioDecoder::HandleFillBufferL, leave on unexpected Result")); |
|
620 User::Leave(KErrGeneral); |
|
621 break; |
|
622 } |
|
623 } |
|
624 } |
|
625 |
|
626 // break the loop during seeking, in case desired position is already reach during ProcessL |
|
627 if (!iRenderEnabled) |
|
628 { |
|
629 moreProcessing = EFalse; |
|
630 } |
|
631 } |
|
632 |
|
633 if (iNeedsSWConversion && iRenderEnabled) |
|
634 { |
|
635 iBufferToEmpty = iBufferToFill; |
|
636 CMMFDataBuffer* audio; |
|
637 |
|
638 if (iConvertBuffer) |
|
639 { |
|
640 delete iConvertBuffer; |
|
641 iConvertBuffer = NULL; |
|
642 } |
|
643 |
|
644 iConvertBuffer = CMMFDataBuffer::NewL(static_cast<CMMFDataBuffer*>(iBufferToFill)->Data().Length()); |
|
645 iChannelAndSampleRateConverter->Convert(*(static_cast<CMMFDataBuffer*>(iBufferToFill)), *iConvertBuffer); |
|
646 audio = iConvertBuffer; |
|
647 |
|
648 //copy our converted data back into the real buffer to return to DevSound Output |
|
649 TDes8& dest = static_cast<CMMFDataBuffer*>(iBufferToFill)->Data(); |
|
650 dest.SetLength(0); |
|
651 dest.Copy(audio->Data()); |
|
652 } |
|
653 |
|
654 if (iRenderEnabled) |
|
655 { |
|
656 DP1(_L("CAdvancedAudioDecoder::HandleFillBufferL, iObserver->BufferFilled[%x]"), |
|
657 static_cast<CMMFDataBuffer*>(iBufferToFill)->Data().Ptr()); |
|
658 iObserver->BufferFilled(iBufferToFill); // send output buffer to devsound |
|
659 } |
|
660 else |
|
661 { |
|
662 if (iBufferToFill->LastBuffer()) |
|
663 { |
|
664 DP1(_L("CAdvancedAudioDecoder::HandleFillBufferL, iObserver->BufferFilled[%x] is last buffer"), |
|
665 static_cast<CMMFDataBuffer*>(iBufferToFill)->Data().Ptr()); |
|
666 iObserver->BufferFilled(iBufferToFill); // be sure to send a last buffer to DS |
|
667 } |
|
668 else |
|
669 { |
|
670 if (iState == EDecoding) |
|
671 { |
|
672 FillBufferL(iBufferToFill); |
|
673 } |
|
674 } |
|
675 } |
|
676 |
|
677 } |
|
678 |
|
679 // ----------------------------------------------------------------------------- |
|
680 // CAdvancedAudioDecoder::DoCancel |
|
681 // Cancels the current and any on going requests/tasks. |
|
682 // ----------------------------------------------------------------------------- |
|
683 // |
|
684 EXPORT_C void CAdvancedAudioDecoder::DoCancel() |
|
685 { |
|
686 } |
|
687 |
|
688 EXPORT_C void CAdvancedAudioDecoder::RenderDisable() |
|
689 { |
|
690 DP0(_L("CAdvancedAudioDecoder::RenderDisable")); |
|
691 iRenderEnabled = EFalse; |
|
692 CodecCmd(ERenderDisable); |
|
693 } |
|
694 |
|
695 EXPORT_C void CAdvancedAudioDecoder::RenderEnable() |
|
696 { |
|
697 DP0(_L("CAdvancedAudioDecoder::RenderEnable")); |
|
698 iRenderEnabled = ETrue; |
|
699 CodecCmd(ERenderEnable); |
|
700 } |
|
701 |
|
702 EXPORT_C void CAdvancedAudioDecoder::Disable() |
|
703 { |
|
704 DP0(_L("CAdvancedAudioDecoder::Disable")); |
|
705 iEnabled = EFalse; |
|
706 CodecCmd(EDisable); |
|
707 } |
|
708 |
|
709 EXPORT_C void CAdvancedAudioDecoder::Enable() |
|
710 { |
|
711 DP0(_L("CAdvancedAudioDecoder::Enable")); |
|
712 iEnabled = ETrue; |
|
713 CodecCmd(EEnable); |
|
714 } |
|
715 |
|
716 EXPORT_C void CAdvancedAudioDecoder::MarkPlayEnd() |
|
717 { |
|
718 DP0(_L("CAdvancedAudioDecoder::MarkPlayEnd")); |
|
719 iMarkPlayEnd = ETrue; |
|
720 CodecCmd(EMarkPlayEnd); |
|
721 } |
|
722 |
|
723 EXPORT_C void CAdvancedAudioDecoder::UnMarkPlayEnd() |
|
724 { |
|
725 DP0(_L("CAdvancedAudioDecoder::UnMarkPlayEnd")); |
|
726 iMarkPlayEnd = EFalse; |
|
727 CodecCmd(EUnMarkPlayEnd); |
|
728 } |
|
729 |
|
730 EXPORT_C TInt CAdvancedAudioDecoder::CodecConfig(RArray<TInt>& /*aConfig*/) |
|
731 { |
|
732 DP0(_L("CAdvancedAudioDecoder::CodecConfig not supported")); |
|
733 return KErrNotSupported; |
|
734 } |
|
735 |
|
736 //EXPORT_C TInt CAdvancedAudioDecoder::IsSeeking(TBool& aIsSeeking) |
|
737 // { |
|
738 // if (!iFrameTable) |
|
739 // return KErrNotSupported; |
|
740 // return iFrameTable->IsSeeking(aIsSeeking); |
|
741 // } |
|
742 |
|
743 EXPORT_C void CAdvancedAudioDecoder::ResetL() |
|
744 { |
|
745 DP0(_L("CAdvancedAudioDecoder::ResetL")); |
|
746 iSoftCodec->ResetL(); |
|
747 // Enable the decoder for processing, to resume playback |
|
748 Enable(); |
|
749 } |
|
750 |
|
751 EXPORT_C TBool CAdvancedAudioDecoder::IsHwAccelerated() |
|
752 { |
|
753 DP0(_L ("CAdvancedAudioDecoder::IsHwAccelerated false")); |
|
754 return EFalse; |
|
755 } |
|
756 |
|
757 EXPORT_C TCodecProcessResult CAdvancedAudioDecoder::ProcessL(CMMFBuffer& aSrc, CMMFBuffer& aDst) |
|
758 { |
|
759 DP0(_L ("CAdvancedAudioDecoder::ProcessL")); |
|
760 TCodecProcessResult result; |
|
761 result = iSoftCodec->ProcessL(aSrc, aDst); |
|
762 return result; |
|
763 } |
|
764 |
|
765 EXPORT_C TInt CAdvancedAudioDecoder::CodecCmd(TCodecCmd aCmd) |
|
766 { |
|
767 DP0(_L ("CAdvancedAudioDecoder::CodecCmd")); |
|
768 TInt stat = KErrNone; |
|
769 switch (aCmd) |
|
770 { |
|
771 case ERenderDisable: |
|
772 DP0(_L("CAdvancedAudioDecoder::CodecCmd RenderDisable")); |
|
773 TRAP(stat, iSoftCodec->ConfigureL(KUidConfig, reinterpret_cast<TDesC8&>(iRenderDisableConfig))); |
|
774 break; |
|
775 case ERenderEnable: |
|
776 DP0(_L("CAdvancedAudioDecoder::CodecCmd RenderEnable")); |
|
777 TRAP(stat, iSoftCodec->ConfigureL(KUidConfig, reinterpret_cast<TDesC8&>(iRenderEnableConfig))); |
|
778 break; |
|
779 case EDisable: |
|
780 DP0(_L("CAdvancedAudioDecoder::CodecCmd Disable")); |
|
781 TRAP(stat, iSoftCodec->ConfigureL(KUidConfig, reinterpret_cast<TDesC8&>(iDisableConfig))); |
|
782 break; |
|
783 case EEnable: |
|
784 DP0(_L("CAdvancedAudioDecoder::CodecCmd Enable")); |
|
785 TRAP(stat, iSoftCodec->ConfigureL(KUidConfig, reinterpret_cast<TDesC8&>(iEnableConfig))); |
|
786 break; |
|
787 case EMarkPlayEnd: |
|
788 DP0(_L("CAdvancedAudioDecoder::CodecCmd MarkPlayEnd")); |
|
789 TRAP(stat, iSoftCodec->ConfigureL(KUidConfig, reinterpret_cast<TDesC8&>(iMarkPlayEndConfig))); |
|
790 break; |
|
791 case EUnMarkPlayEnd: |
|
792 DP0(_L("CAdvancedAudioDecoder::CodecCmd UnMarkPlayEnd")); |
|
793 TRAP(stat, iSoftCodec->ConfigureL(KUidConfig, reinterpret_cast<TDesC8&>(iUnMarkPlayEndConfig))); |
|
794 break; |
|
795 default: |
|
796 break; |
|
797 } |
|
798 return stat; |
|
799 } |
|
800 |
|
801 |
|
802 // End of file |