|
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <e32debug.h> |
|
17 #include <stdio.h> |
|
18 #include <string.h> |
|
19 #include <stdlib.h> |
|
20 #include <openmax/il/khronos/v1_x/OMX_Core.h> |
|
21 #include <openmax/il/khronos/v1_x/OMX_Audio.h> |
|
22 |
|
23 #include "OmxImpl.h" |
|
24 #include "OmxPCMCodec.h" |
|
25 |
|
26 const TInt KPCMBufferSize = 4096; |
|
27 |
|
28 const TInt KThreadStackSize = 16384; |
|
29 |
|
30 const TInt KShutDownTime = 5000000; |
|
31 |
|
32 |
|
33 TInt ProcessingThread(TAny* aComponent) |
|
34 { |
|
35 // get our class |
|
36 CCodecProcessor* codecprocessor = static_cast<CCodecProcessor*>(aComponent); |
|
37 |
|
38 // run the thread |
|
39 TRAPD(err, codecprocessor->RunThreadL()); |
|
40 // thread has exited or failed to start so return error to the client. |
|
41 return err; |
|
42 } |
|
43 |
|
44 |
|
45 TInt COmxPCMCodec::CreateComponent(OMX_HANDLETYPE hComponent) |
|
46 { |
|
47 COmxPCMCodec* self = new COmxPCMCodec(hComponent); |
|
48 if (self==NULL) |
|
49 { |
|
50 return KErrNoMemory; |
|
51 } |
|
52 TRAPD(err, self->ConstructL()); |
|
53 // self is stored in the handle, so we won't return it |
|
54 return err; |
|
55 } |
|
56 |
|
57 OMX_ERRORTYPE COmxPCMCodec::GetComponentVersion( |
|
58 OMX_STRING /*pComponentName*/, |
|
59 OMX_VERSIONTYPE* /*pComponentVersion*/, |
|
60 OMX_VERSIONTYPE* /*pSpecVersion*/, |
|
61 OMX_UUIDTYPE* /*pComponentUUID*/) |
|
62 { |
|
63 // to be implemented |
|
64 return OMX_ErrorNone; |
|
65 } |
|
66 |
|
67 |
|
68 void COmxPCMCodec::ConstructL() |
|
69 { |
|
70 iCodecProcessor = CCodecProcessor::NewL(*this); |
|
71 iState = OMX_StateLoaded; |
|
72 } |
|
73 |
|
74 COmxPCMCodec::COmxPCMCodec(OMX_HANDLETYPE hComponent) |
|
75 :COmxComponentImpl(hComponent) |
|
76 { |
|
77 } |
|
78 |
|
79 COmxPCMCodec::~COmxPCMCodec() |
|
80 { |
|
81 if (iState == OMX_StateExecuting) |
|
82 { |
|
83 iCodecProcessor->Stop(); |
|
84 iState = OMX_StateIdle; |
|
85 } |
|
86 |
|
87 if (iCreatedThread &&(iProcessingThread.Handle() != KNullHandle) && (iProcessingThread.ExitType() == EExitPending)) |
|
88 { |
|
89 TRequestStatus logonStatus; |
|
90 TBool logonFailed = EFalse; |
|
91 iProcessingThread.Logon(logonStatus); |
|
92 if(logonStatus != KRequestPending) |
|
93 {//logon failed. Mostly due to no memory |
|
94 logonFailed = ETrue; |
|
95 } |
|
96 iCodecProcessor->Exit(); |
|
97 RTimer timer; |
|
98 TInt err = timer.CreateLocal(); |
|
99 if(err==KErrNone && !logonFailed) //both timer and logon successful |
|
100 { |
|
101 TRequestStatus timeout; |
|
102 timer.After(timeout, KShutDownTime); |
|
103 User::WaitForRequest(logonStatus, timeout); |
|
104 if(logonStatus==KRequestPending) |
|
105 {//Thread has not exited after the timeout. Kill it! |
|
106 iProcessingThread.LogonCancel(logonStatus); |
|
107 User::WaitForRequest(logonStatus); |
|
108 iProcessingThread.Kill(KErrDied); |
|
109 } |
|
110 else |
|
111 {//Thread exited. Cancel the timer |
|
112 timer.Cancel(); |
|
113 User::WaitForRequest(timeout); |
|
114 } |
|
115 } |
|
116 else |
|
117 {//either timer or Logon method has failed.Poll the thread status a maximum |
|
118 // of 10 times and kill the thread if it hasn't exited after the polling |
|
119 for (TInt i=0; i<10 && iProcessingThread.ExitType() == EExitPending; ++i) |
|
120 { |
|
121 User::After(KShutDownTime/10); // wait for a while |
|
122 } |
|
123 |
|
124 if (iProcessingThread.ExitType() == EExitPending) |
|
125 { |
|
126 // The polling hasn't been succesful so we kill the thread |
|
127 iProcessingThread.Kill(KErrDied); |
|
128 } |
|
129 if(!logonFailed) |
|
130 { |
|
131 User::WaitForRequest(logonStatus); |
|
132 } |
|
133 } |
|
134 iProcessingThread.Close(); |
|
135 } |
|
136 delete iCodecProcessor; |
|
137 } |
|
138 |
|
139 OMX_ERRORTYPE COmxPCMCodec::SendCommand( |
|
140 OMX_COMMANDTYPE Cmd, |
|
141 TUint32 nParam1, |
|
142 TAny* /*pCmdData*/) |
|
143 { |
|
144 OMX_ERRORTYPE error = OMX_ErrorNone; |
|
145 switch (Cmd) |
|
146 { |
|
147 case OMX_CommandStateSet: |
|
148 OMX_STATETYPE state = (OMX_STATETYPE)nParam1; |
|
149 if (state == iState) |
|
150 { |
|
151 error = OMX_ErrorSameState; |
|
152 } |
|
153 else |
|
154 { |
|
155 // notify client of the state change |
|
156 switch (state) |
|
157 { |
|
158 case OMX_StateIdle: |
|
159 { |
|
160 if (iState == OMX_StateExecuting) |
|
161 { |
|
162 iCodecProcessor->Stop(); |
|
163 } |
|
164 break; |
|
165 } |
|
166 case OMX_StateExecuting: |
|
167 StartExecution(); |
|
168 break; |
|
169 }; |
|
170 |
|
171 iState = state; |
|
172 |
|
173 EventHandlerCallback( |
|
174 OMX_EventCmdComplete, |
|
175 OMX_CommandStateSet, |
|
176 iState, |
|
177 NULL); |
|
178 break; |
|
179 } |
|
180 }; |
|
181 return error; |
|
182 } |
|
183 |
|
184 OMX_ERRORTYPE COmxPCMCodec::GetParameter( |
|
185 OMX_INDEXTYPE nParamIndex, |
|
186 TAny* ComponentParameterStructure) |
|
187 { |
|
188 switch (nParamIndex) |
|
189 { |
|
190 case OMX_IndexParamAudioInit : |
|
191 { |
|
192 OMX_PORT_PARAM_TYPE* param = static_cast<OMX_PORT_PARAM_TYPE*>(ComponentParameterStructure); |
|
193 param->nPorts = 2; |
|
194 } |
|
195 break; |
|
196 case OMX_IndexParamPortDefinition: |
|
197 { |
|
198 OMX_PARAM_PORTDEFINITIONTYPE* portDef = static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(ComponentParameterStructure); |
|
199 if (portDef->nPortIndex==0) |
|
200 { |
|
201 portDef->eDir = OMX_DirInput; |
|
202 portDef->nBufferSize = KPCMBufferSize; |
|
203 } |
|
204 else |
|
205 { |
|
206 portDef->eDir = OMX_DirOutput; |
|
207 portDef->nBufferSize = KPCMBufferSize; |
|
208 } |
|
209 } |
|
210 break; |
|
211 default: |
|
212 return OMX_ErrorUnsupportedIndex; |
|
213 } |
|
214 return OMX_ErrorNone; |
|
215 } |
|
216 |
|
217 OMX_ERRORTYPE COmxPCMCodec::SetParameter( |
|
218 OMX_INDEXTYPE nIndex, |
|
219 TAny* ComponentParameterStructure) |
|
220 { |
|
221 ASSERT(iState == OMX_StateLoaded); |
|
222 switch (nIndex) |
|
223 { |
|
224 case OMX_IndexParamAudioPcm: |
|
225 { |
|
226 OMX_AUDIO_PARAM_PCMMODETYPE* param = static_cast<OMX_AUDIO_PARAM_PCMMODETYPE*>(ComponentParameterStructure); |
|
227 switch(param->nPortIndex) |
|
228 { |
|
229 case 0: // Input port |
|
230 { |
|
231 iCodecProcessor->SetInputBitsPerSample(param->nBitPerSample); |
|
232 iCodecProcessor->SetInputDataType(param->eNumData); |
|
233 //break; |
|
234 return OMX_ErrorNone; |
|
235 } |
|
236 case 1: // Output port |
|
237 { |
|
238 iCodecProcessor->SetOutputBitsPerSample(param->nBitPerSample); |
|
239 iCodecProcessor->SetOutputDataType(param->eNumData); |
|
240 //break; |
|
241 return OMX_ErrorNone; |
|
242 } |
|
243 default: |
|
244 { |
|
245 return OMX_ErrorUnsupportedIndex; |
|
246 } |
|
247 }; |
|
248 } |
|
249 default: |
|
250 { |
|
251 return OMX_ErrorUnsupportedIndex; |
|
252 } |
|
253 }; |
|
254 //return OMX_ErrorNone; |
|
255 } |
|
256 |
|
257 OMX_ERRORTYPE COmxPCMCodec::GetConfig( |
|
258 OMX_INDEXTYPE /*nIndex*/, |
|
259 TAny* /*value*/) |
|
260 { |
|
261 return OMX_ErrorUnsupportedIndex; |
|
262 } |
|
263 |
|
264 OMX_ERRORTYPE COmxPCMCodec::SetConfig( |
|
265 OMX_INDEXTYPE /*nIndex*/, |
|
266 TAny* /*value*/) |
|
267 { |
|
268 return OMX_ErrorUnsupportedIndex; |
|
269 } |
|
270 |
|
271 OMX_ERRORTYPE COmxPCMCodec::GetExtensionIndex( |
|
272 OMX_STRING /*ParameterName*/, |
|
273 OMX_INDEXTYPE* /*pIndexType*/) |
|
274 { |
|
275 return OMX_ErrorNotImplemented; |
|
276 } |
|
277 |
|
278 OMX_ERRORTYPE COmxPCMCodec::GetState( |
|
279 OMX_STATETYPE* pState) |
|
280 { |
|
281 *pState = iState; |
|
282 return OMX_ErrorNone; |
|
283 } |
|
284 |
|
285 OMX_ERRORTYPE COmxPCMCodec::ComponentTunnelRequest( |
|
286 OMX_HANDLETYPE /*hInput*/, |
|
287 TUint32 /*nInputPort*/, |
|
288 OMX_HANDLETYPE /*hOutput*/, |
|
289 TUint32 /*nOutputPort*/, |
|
290 OMX_TUNNELSETUPTYPE* /*pTunnelSetup*/) |
|
291 { |
|
292 return OMX_ErrorNotImplemented; |
|
293 } |
|
294 |
|
295 OMX_ERRORTYPE COmxPCMCodec::UseBuffer( |
|
296 OMX_BUFFERHEADERTYPE** ppBufferHeader, |
|
297 TUint32 /*nPortIndex*/, |
|
298 TAny* pAppPrivate, |
|
299 TUint32 nSizeBytes, |
|
300 TUint8* pBuffer) |
|
301 { |
|
302 ASSERT(iState == OMX_StateLoaded); |
|
303 *ppBufferHeader = new OMX_BUFFERHEADERTYPE; |
|
304 if (*ppBufferHeader != NULL) |
|
305 { |
|
306 (*ppBufferHeader)->pBuffer = pBuffer; |
|
307 (*ppBufferHeader)->pAppPrivate = pAppPrivate; |
|
308 (*ppBufferHeader)->nAllocLen = nSizeBytes; |
|
309 (*ppBufferHeader)->nFilledLen = 0; |
|
310 (*ppBufferHeader)->nFlags = 0; |
|
311 (*ppBufferHeader)->pInputPortPrivate = NULL; |
|
312 (*ppBufferHeader)->pOutputPortPrivate = NULL; |
|
313 } |
|
314 |
|
315 if (*ppBufferHeader) |
|
316 { |
|
317 return OMX_ErrorNone; |
|
318 } |
|
319 else |
|
320 { |
|
321 return OMX_ErrorInsufficientResources; |
|
322 } |
|
323 } |
|
324 |
|
325 OMX_ERRORTYPE COmxPCMCodec::AllocateBuffer( |
|
326 OMX_BUFFERHEADERTYPE** pBuffer, |
|
327 TUint32 nPortIndex, |
|
328 TAny* pAppData, |
|
329 TUint32 nSizeBytes) |
|
330 { |
|
331 ASSERT(iState == OMX_StateLoaded); |
|
332 |
|
333 *pBuffer = new OMX_BUFFERHEADERTYPE; |
|
334 if (*pBuffer != NULL) |
|
335 { |
|
336 (*pBuffer)->pBuffer = new unsigned char[nSizeBytes]; |
|
337 // store our allocated memory in component's private store |
|
338 switch (nPortIndex) |
|
339 { |
|
340 case 0: |
|
341 (*pBuffer)->pInputPortPrivate = (*pBuffer)->pBuffer; |
|
342 (*pBuffer)->pOutputPortPrivate = NULL; |
|
343 break; |
|
344 case 1: |
|
345 (*pBuffer)->pOutputPortPrivate = (*pBuffer)->pBuffer; |
|
346 (*pBuffer)->pInputPortPrivate = NULL; |
|
347 break; |
|
348 }; |
|
349 |
|
350 |
|
351 (*pBuffer)->nAllocLen = nSizeBytes; |
|
352 (*pBuffer)->nFilledLen = 0; |
|
353 (*pBuffer)->pAppPrivate = pAppData; |
|
354 } |
|
355 |
|
356 if (*pBuffer && (*pBuffer)->pBuffer) |
|
357 { |
|
358 return OMX_ErrorNone; |
|
359 } |
|
360 else |
|
361 { |
|
362 return OMX_ErrorInsufficientResources; |
|
363 } |
|
364 } |
|
365 |
|
366 OMX_ERRORTYPE COmxPCMCodec::FreeBuffer( |
|
367 TUint32 /*nPortIndex*/, |
|
368 OMX_BUFFERHEADERTYPE* pBuffer) |
|
369 { |
|
370 if (pBuffer->pInputPortPrivate || |
|
371 pBuffer->pOutputPortPrivate) |
|
372 delete[] pBuffer->pBuffer; |
|
373 delete pBuffer; |
|
374 return OMX_ErrorNone; |
|
375 } |
|
376 OMX_ERRORTYPE COmxPCMCodec::EmptyThisBuffer( |
|
377 OMX_BUFFERHEADERTYPE* pBuffer) |
|
378 { |
|
379 ASSERT(iState == OMX_StateExecuting || |
|
380 iState == OMX_StateIdle || |
|
381 iState == OMX_StatePause); |
|
382 return iCodecProcessor->EmptyThisBuffer(pBuffer); |
|
383 } |
|
384 OMX_ERRORTYPE COmxPCMCodec::FillThisBuffer( |
|
385 OMX_BUFFERHEADERTYPE* pBuffer) |
|
386 { |
|
387 ASSERT(iState == OMX_StateExecuting || |
|
388 iState == OMX_StateIdle || |
|
389 iState == OMX_StatePause); |
|
390 return iCodecProcessor->FillThisBuffer(pBuffer); |
|
391 } |
|
392 |
|
393 OMX_ERRORTYPE COmxPCMCodec::SetCallbacks( |
|
394 OMX_CALLBACKTYPE* pCallbacks, |
|
395 TAny* pAppData) |
|
396 { |
|
397 iCallback = pCallbacks; |
|
398 iAppData = pAppData; |
|
399 return OMX_ErrorNone; |
|
400 } |
|
401 |
|
402 |
|
403 CCodecProcessor::CCodecProcessor(COmxPCMCodec& aParent) |
|
404 : iParent(&aParent) |
|
405 { |
|
406 } |
|
407 |
|
408 void CCodecProcessor::RunThreadL() |
|
409 { |
|
410 iQueueStatus = KRequestPending; |
|
411 iMessageQueue.NotifyDataAvailable(iQueueStatus); |
|
412 |
|
413 for (;;) |
|
414 { |
|
415 User::WaitForRequest(iQueueStatus); |
|
416 TCodecMessage msg; |
|
417 |
|
418 TBool exit = EFalse; |
|
419 |
|
420 while (iMessageQueue.Receive(msg)==KErrNone) |
|
421 { |
|
422 switch (msg.iType) |
|
423 { |
|
424 case EStopProcessing: |
|
425 iStarted = EFalse; |
|
426 break; |
|
427 case EExit: |
|
428 exit = ETrue; |
|
429 break; |
|
430 case EInputBuffer: |
|
431 iBuffersToEmpty.Append(msg.iBuffer); |
|
432 break; |
|
433 case EOutputBuffer: |
|
434 iBuffersToFill.Append(msg.iBuffer); |
|
435 break; |
|
436 } |
|
437 } |
|
438 |
|
439 if (exit) |
|
440 { |
|
441 break; |
|
442 } |
|
443 else |
|
444 { |
|
445 // process all available buffers |
|
446 ProcessAvailableBuffers(); |
|
447 |
|
448 // request notification of further queue events |
|
449 iQueueStatus = KRequestPending; |
|
450 iMessageQueue.NotifyDataAvailable(iQueueStatus); |
|
451 //TBool lastBuffer=EFalse; TODO UNUSED! |
|
452 } |
|
453 } |
|
454 |
|
455 } |
|
456 |
|
457 |
|
458 CCodecProcessor* CCodecProcessor::NewL(COmxPCMCodec& aParent) |
|
459 { |
|
460 CCodecProcessor* self = new (ELeave) CCodecProcessor(aParent); |
|
461 CleanupStack::PushL(self); |
|
462 self->ConstructL(); |
|
463 CleanupStack::Pop(self); |
|
464 return self; |
|
465 } |
|
466 |
|
467 |
|
468 void CCodecProcessor::ConstructL() |
|
469 { |
|
470 User::LeaveIfError(iMessageQueue.CreateLocal(10)); |
|
471 // set the default case |
|
472 iInputBitsPerSample = 8; |
|
473 iInputDataType = OMX_NumericalDataUnsigned; |
|
474 iOutputBitsPerSample = 16; |
|
475 iOutputDataType = OMX_NumericalDataSigned; |
|
476 } |
|
477 |
|
478 OMX_ERRORTYPE CCodecProcessor::EmptyThisBuffer( |
|
479 OMX_BUFFERHEADERTYPE* pBuffer) |
|
480 { |
|
481 TCodecMessage message; |
|
482 message.iType = EInputBuffer; |
|
483 message.iBuffer = pBuffer; |
|
484 if (iMessageQueue.Send(message) == KErrNone) |
|
485 { |
|
486 return OMX_ErrorNone; |
|
487 } |
|
488 else |
|
489 { |
|
490 return OMX_ErrorUndefined; |
|
491 } |
|
492 } |
|
493 |
|
494 void CCodecProcessor::Stop() |
|
495 { |
|
496 TCodecMessage message; |
|
497 message.iType = EStopProcessing; |
|
498 message.iBuffer = NULL; |
|
499 iMessageQueue.Send(message); |
|
500 } |
|
501 |
|
502 void CCodecProcessor::Exit() |
|
503 { |
|
504 TCodecMessage message; |
|
505 message.iType = EExit; |
|
506 message.iBuffer = NULL; |
|
507 iMessageQueue.SendBlocking(message); |
|
508 } |
|
509 |
|
510 OMX_ERRORTYPE CCodecProcessor::FillThisBuffer( |
|
511 OMX_BUFFERHEADERTYPE* pBuffer) |
|
512 { |
|
513 TCodecMessage message; |
|
514 message.iType = EOutputBuffer; |
|
515 message.iBuffer = pBuffer; |
|
516 if (iMessageQueue.Send(message)== KErrNone) |
|
517 { |
|
518 return OMX_ErrorNone; |
|
519 } |
|
520 else |
|
521 { |
|
522 return OMX_ErrorUndefined; |
|
523 } |
|
524 } |
|
525 |
|
526 void CCodecProcessor::SetInputBitsPerSample(TInt aInputBitsPerSample) |
|
527 { |
|
528 iInputBitsPerSample = aInputBitsPerSample; |
|
529 } |
|
530 |
|
531 void CCodecProcessor::SetInputDataType(OMX_NUMERICALDATATYPE aType) |
|
532 { |
|
533 iInputDataType = aType; |
|
534 } |
|
535 |
|
536 void CCodecProcessor::SetOutputBitsPerSample(TInt aInputBitsPerSample) |
|
537 { |
|
538 iOutputBitsPerSample = aInputBitsPerSample; |
|
539 } |
|
540 |
|
541 void CCodecProcessor::SetOutputDataType(OMX_NUMERICALDATATYPE aType) |
|
542 { |
|
543 iOutputDataType = aType; |
|
544 } |
|
545 |
|
546 void CCodecProcessor::ChooseCodec() |
|
547 { |
|
548 // choose correct conversion codec |
|
549 if (iInputBitsPerSample == 8 && iOutputBitsPerSample == 16) |
|
550 { |
|
551 iOutputSamplesPerInputSample = 2; |
|
552 if (iInputDataType == OMX_NumericalDataSigned && |
|
553 iOutputDataType == OMX_NumericalDataSigned) |
|
554 { |
|
555 iCurrentCodec = &iAudioS8ToS16PcmCodec; |
|
556 } |
|
557 else if (iInputDataType == OMX_NumericalDataUnsigned && |
|
558 iOutputDataType == OMX_NumericalDataSigned) |
|
559 { |
|
560 iCurrentCodec = &iAudioU8ToS16PcmCodec; |
|
561 } |
|
562 } |
|
563 else if (iInputBitsPerSample == 16 && iOutputBitsPerSample == 8) |
|
564 { |
|
565 iOutputSamplesPerInputSample = .5; |
|
566 if (iInputDataType == OMX_NumericalDataSigned && |
|
567 iOutputDataType == OMX_NumericalDataSigned) |
|
568 { |
|
569 iCurrentCodec = &iAudioS16ToS8PcmCodec; |
|
570 } |
|
571 else if (iInputDataType == OMX_NumericalDataSigned && |
|
572 iOutputDataType == OMX_NumericalDataUnsigned) |
|
573 { |
|
574 iCurrentCodec = &iAudioS16ToU8PcmCodec; |
|
575 } |
|
576 } |
|
577 |
|
578 } |
|
579 |
|
580 void CCodecProcessor::ProcessAvailableBuffers() |
|
581 { |
|
582 // Setup wait for data in queue |
|
583 while (iBuffersToFill.Count()>0 && iBuffersToEmpty.Count() > 0) |
|
584 { |
|
585 TBool lastBuffer = EFalse; |
|
586 if (!iStarted) |
|
587 { |
|
588 ChooseCodec(); |
|
589 iStarted = ETrue; |
|
590 } |
|
591 |
|
592 OMX_BUFFERHEADERTYPE* srcBuffer = iBuffersToEmpty[0]; |
|
593 OMX_BUFFERHEADERTYPE* destBuffer = iBuffersToFill[0]; |
|
594 if (srcBuffer->nFlags & OMX_BUFFERFLAG_EOS) |
|
595 { |
|
596 lastBuffer = ETrue; |
|
597 } |
|
598 TInt destBufferPos = destBuffer->nFilledLen; |
|
599 |
|
600 TInt destBufferSize = destBuffer->nAllocLen - destBufferPos; |
|
601 TInt inputSamplesRequired = (TInt)((TReal)destBufferSize / iOutputSamplesPerInputSample); |
|
602 |
|
603 TInt availableSamples = srcBuffer->nFilledLen - iInputBufferPos; |
|
604 |
|
605 if (availableSamples <= inputSamplesRequired) |
|
606 { |
|
607 TInt samplesToConvert = availableSamples; |
|
608 if (iOutputSamplesPerInputSample == .5) |
|
609 { |
|
610 samplesToConvert >>= 1; |
|
611 } |
|
612 iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert); |
|
613 iInputBufferPos = 0; // finished buffer - so reset |
|
614 inputSamplesRequired -= availableSamples; |
|
615 // TInt filled = availableSamples; TODO UNUSED |
|
616 destBuffer->nFilledLen = (TInt)((TReal)availableSamples * iOutputSamplesPerInputSample); |
|
617 srcBuffer->nFilledLen = 0; |
|
618 iBuffersToEmpty.Remove(0); |
|
619 iParent->EmptyBufferDoneCallback(srcBuffer); |
|
620 |
|
621 if (inputSamplesRequired == 0 || lastBuffer) |
|
622 { |
|
623 iBuffersToFill.Remove(0); |
|
624 if (lastBuffer) |
|
625 { |
|
626 destBuffer->nFlags |= OMX_BUFFERFLAG_EOS; |
|
627 // propagate the EOS flag |
|
628 iParent->EventHandlerCallback( |
|
629 OMX_EventBufferFlag, |
|
630 0, |
|
631 destBuffer->nFlags, |
|
632 NULL); |
|
633 } |
|
634 iParent->FillBufferDoneCallback(destBuffer); |
|
635 } |
|
636 } |
|
637 else |
|
638 { |
|
639 TInt samplesToConvert = inputSamplesRequired; |
|
640 if (iOutputSamplesPerInputSample == .5) |
|
641 { |
|
642 samplesToConvert >>= 2; |
|
643 } |
|
644 |
|
645 iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert); |
|
646 iInputBufferPos += inputSamplesRequired; |
|
647 destBuffer->nFilledLen = destBuffer->nAllocLen; |
|
648 iBuffersToFill.Remove(0); |
|
649 iParent->FillBufferDoneCallback(destBuffer); |
|
650 } |
|
651 } |
|
652 } |
|
653 |
|
654 CCodecProcessor::~CCodecProcessor() |
|
655 { |
|
656 iBuffersToEmpty.Close(); |
|
657 iBuffersToFill.Close(); |
|
658 iMessageQueue.Close(); |
|
659 } |
|
660 |
|
661 |
|
662 TInt COmxPCMCodec::StartExecution() |
|
663 { |
|
664 // create thread with current thread's heap |
|
665 // we can thus allocate and free memory across threads |
|
666 if (!iCreatedThread) |
|
667 { |
|
668 TInt err = iProcessingThread.Create(_L("PCMCodec"), |
|
669 &ProcessingThread, |
|
670 KThreadStackSize, |
|
671 &User::Heap(), |
|
672 iCodecProcessor); |
|
673 |
|
674 if (err!=KErrNone) |
|
675 { |
|
676 return err; |
|
677 } |
|
678 iCreatedThread = ETrue; |
|
679 iThreadDeath = KRequestPending; |
|
680 iProcessingThread.Resume(); |
|
681 } |
|
682 |
|
683 return KErrNone; |
|
684 } |
|
685 |
|
686 // Callbacks for the PCM codec |
|
687 void COmxPCMCodec::EventHandlerCallback( |
|
688 OMX_OUT OMX_EVENTTYPE eEvent, |
|
689 OMX_OUT TUint32 nData1, |
|
690 OMX_OUT TUint32 nData2, |
|
691 OMX_OUT OMX_STRING cExtraInfo) |
|
692 { |
|
693 iCallback->EventHandler( |
|
694 this, |
|
695 iAppData, |
|
696 eEvent, |
|
697 nData1, |
|
698 nData2, |
|
699 cExtraInfo); |
|
700 } |
|
701 |
|
702 |
|
703 void COmxPCMCodec::FillBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer) |
|
704 { |
|
705 iCallback->FillBufferDone( |
|
706 *this, |
|
707 iAppData, |
|
708 aBuffer); |
|
709 } |
|
710 |
|
711 void COmxPCMCodec::EmptyBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer) |
|
712 { |
|
713 iCallback->EmptyBufferDone( |
|
714 *this, |
|
715 iAppData, |
|
716 aBuffer); |
|
717 } |
|
718 |
|
719 // Component Entry Point |
|
720 OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE hComponent) |
|
721 { |
|
722 TInt err = COmxPCMCodec::CreateComponent(hComponent); |
|
723 if (err == KErrNone) |
|
724 { |
|
725 return OMX_ErrorNone; |
|
726 } |
|
727 else |
|
728 { |
|
729 // return problem |
|
730 return OMX_ErrorInsufficientResources; |
|
731 } |
|
732 } |