00001
00002
00003
00004
00005
00011 #include <e32debug.h>
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <stdlib.h>
00015 #include <OMX_Core.h>
00016 #include <OMX_Audio.h>
00017
00018 #include "OmxImpl.h"
00019 #include "OmxVorbisDecoder.h"
00020 #include "VorbisDecoder.h"
00021
00022 const TInt KIndexInputPort = 0;
00023 const TInt KIndexOutputPort = 1;
00024
00025
00026 const TInt KVorbisDecoderInputBufferSize = 0x2000;
00027 const TInt KVorbisDecoderOutputBufferSize = 0x4000;
00028
00029 const TInt KThreadStackSize = 16384;
00030
00031 const TInt KDefaultOutputBitsPerSample = 16;
00032 const OMX_NUMERICALDATATYPE KDefaultOutputDataType = OMX_NumericalDataSigned;
00033
00034 _LIT(KVorbisDecoder, "VorbisDecoder");
00035
00036 TInt ProcessingThread(TAny* aComponent)
00037 {
00038
00039 CCodecProcessor* codecprocessor = static_cast<CCodecProcessor*>(aComponent);
00040
00041 TRAPD(err, codecprocessor->RunThreadL());
00042
00043 return err;
00044 }
00045
00046
00047 TInt COmxVorbisDecoder::CreateComponent(OMX_HANDLETYPE hComponent)
00048 {
00049 COmxVorbisDecoder* self = new COmxVorbisDecoder(hComponent);
00050 if (self==NULL)
00051 return KErrNoMemory;
00052 TRAPD(err, self->ConstructL());
00053
00054 return err;
00055 }
00056
00057 OMX_ERRORTYPE COmxVorbisDecoder::GetComponentVersion(
00058 OMX_STRING ,
00059 OMX_VERSIONTYPE* ,
00060 OMX_VERSIONTYPE* ,
00061 OMX_UUIDTYPE* )
00062 {
00063
00064 return OMX_ErrorNone;
00065 }
00066
00067 void COmxVorbisDecoder::ConstructL()
00068 {
00069 iCodecProcessor = CCodecProcessor::NewL(*this);
00070 iState = OMX_StateLoaded;
00071 }
00072
00073 COmxVorbisDecoder::COmxVorbisDecoder(OMX_HANDLETYPE hComponent)
00074 :COmxComponentImpl(hComponent)
00075 {
00076 }
00077
00078 COmxVorbisDecoder::~COmxVorbisDecoder()
00079 {
00080 if (iState == OMX_StateExecuting)
00081 {
00082 iCodecProcessor->Stop();
00083 iState = OMX_StateIdle;
00084 }
00085
00086 if (iCreatedThread)
00087 {
00088 iCodecProcessor->Exit();
00089 TRequestStatus status;
00090 iProcessingThread.Logon(status);
00091 User::WaitForRequest(status);
00092 iProcessingThread.Close();
00093 }
00094 delete iCodecProcessor;
00095 }
00096
00097 OMX_ERRORTYPE COmxVorbisDecoder::SendCommand(
00098 OMX_COMMANDTYPE Cmd,
00099 TUint32 nParam1,
00100 TAny* )
00101 {
00102 OMX_ERRORTYPE error = OMX_ErrorNone;
00103 switch (Cmd)
00104 {
00105 case OMX_CommandStateSet:
00106 OMX_STATETYPE state = (OMX_STATETYPE)nParam1;
00107 if (state == iState)
00108 {
00109 error = OMX_ErrorSameState;
00110 }
00111 else
00112 {
00113
00114 switch (state)
00115 {
00116 case OMX_StateIdle:
00117 {
00118 if (iState == OMX_StateExecuting)
00119 {
00120 iCodecProcessor->Stop();
00121 }
00122 break;
00123 }
00124 case OMX_StateExecuting:
00125 StartExecution();
00126 break;
00127 };
00128
00129 iState = state;
00130
00131 EventHandlerCallback(
00132 OMX_EventCmdComplete,
00133 OMX_CommandStateSet,
00134 iState,
00135 NULL);
00136 break;
00137 }
00138 };
00139 return error;
00140 }
00141
00142 OMX_ERRORTYPE COmxVorbisDecoder::GetParameter(
00143 OMX_INDEXTYPE nParamIndex,
00144 TAny* ComponentParameterStructure)
00145 {
00146 switch (nParamIndex)
00147 {
00148 case OMX_IndexParamAudioInit :
00149 {
00150 OMX_PORT_PARAM_TYPE* param = static_cast<OMX_PORT_PARAM_TYPE*>(ComponentParameterStructure);
00151 param->nPorts = 2;
00152 }
00153 break;
00154 case OMX_IndexParamPortDefinition:
00155 {
00156 OMX_PARAM_PORTDEFINITIONTYPE* portDef = static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(ComponentParameterStructure);
00157 if (portDef->nPortIndex==0)
00158 {
00159 portDef->eDir = OMX_DirInput;
00160 portDef->nBufferSize = KVorbisDecoderInputBufferSize;
00161 }
00162 else
00163 {
00164 portDef->eDir = OMX_DirOutput;
00165 portDef->nBufferSize = KVorbisDecoderOutputBufferSize;
00166 }
00167 }
00168 break;
00169 default:
00170 return OMX_ErrorUnsupportedIndex;
00171 }
00172 return OMX_ErrorNone;
00173 }
00174
00175 OMX_ERRORTYPE COmxVorbisDecoder::SetParameter(
00176 OMX_INDEXTYPE nIndex,
00177 TAny* ComponentParameterStructure)
00178 {
00179 ASSERT(iState == OMX_StateLoaded);
00180 switch (nIndex)
00181 {
00182 case OMX_IndexParamAudioVorbis:
00183 {
00184 OMX_AUDIO_PARAM_VORBISTYPE* param = static_cast<OMX_AUDIO_PARAM_VORBISTYPE*>(ComponentParameterStructure);
00185 switch(param->nPortIndex)
00186 {
00187 case 0:
00188 {
00189
00190 return OMX_ErrorNone;
00191 }
00192 case 1:
00193 default:
00194 {
00195 return OMX_ErrorUnsupportedIndex;
00196 }
00197 };
00198 }
00199 case OMX_IndexParamAudioPcm:
00200 {
00201 OMX_AUDIO_PARAM_PCMMODETYPE* param = static_cast<OMX_AUDIO_PARAM_PCMMODETYPE*>(ComponentParameterStructure);
00202 switch(param->nPortIndex)
00203 {
00204 case 1:
00205 {
00206 iCodecProcessor->SetOutputBitsPerSample(param->nBitPerSample);
00207 iCodecProcessor->SetOutputDataType(param->eNumData);
00208 return OMX_ErrorNone;
00209 }
00210 case 0:
00211 default:
00212 {
00213 return OMX_ErrorUnsupportedIndex;
00214 }
00215 };
00216 }
00217 default:
00218 {
00219 return OMX_ErrorUnsupportedIndex;
00220 }
00221 };
00222 }
00223
00224 OMX_ERRORTYPE COmxVorbisDecoder::GetConfig(
00225 OMX_INDEXTYPE ,
00226 TAny* )
00227 {
00228 return OMX_ErrorUnsupportedIndex;
00229 }
00230
00231 OMX_ERRORTYPE COmxVorbisDecoder::SetConfig(
00232 OMX_INDEXTYPE ,
00233 TAny* )
00234 {
00235 return OMX_ErrorUnsupportedIndex;
00236 }
00237
00238 OMX_ERRORTYPE COmxVorbisDecoder::GetExtensionIndex(
00239 OMX_STRING ,
00240 OMX_INDEXTYPE* )
00241 {
00242 return OMX_ErrorNotImplemented;
00243 }
00244
00245 OMX_ERRORTYPE COmxVorbisDecoder::GetState(
00246 OMX_STATETYPE* pState)
00247 {
00248 *pState = iState;
00249 return OMX_ErrorNone;
00250 }
00251
00252
00253 OMX_ERRORTYPE COmxVorbisDecoder::ComponentTunnelRequest(
00254 OMX_HANDLETYPE ,
00255 TUint32 ,
00256 OMX_HANDLETYPE ,
00257 TUint32 ,
00258 OMX_TUNNELSETUPTYPE* )
00259 {
00260 return OMX_ErrorNotImplemented;
00261 }
00262
00263 OMX_ERRORTYPE COmxVorbisDecoder::UseBuffer(
00264 OMX_BUFFERHEADERTYPE** ppBufferHeader,
00265 TUint32 nPortIndex,
00266 TAny* pAppPrivate,
00267 TUint32 nSizeBytes,
00268 TUint8* pBuffer)
00269 {
00270 ASSERT(iState == OMX_StateLoaded);
00271 *ppBufferHeader = new OMX_BUFFERHEADERTYPE;
00272 if (*ppBufferHeader != NULL)
00273 {
00274 (*ppBufferHeader)->pBuffer = pBuffer;
00275 (*ppBufferHeader)->pAppPrivate = pAppPrivate;
00276 (*ppBufferHeader)->nAllocLen = nSizeBytes;
00277 (*ppBufferHeader)->nFilledLen = 0;
00278 (*ppBufferHeader)->nFlags = 0;
00279 (*ppBufferHeader)->pInputPortPrivate = NULL;
00280 (*ppBufferHeader)->pOutputPortPrivate = NULL;
00281 }
00282
00283
00284
00285 if (*ppBufferHeader)
00286 {
00287 TPtr8 ptr(pBuffer,nSizeBytes,nSizeBytes);
00288 CMMFBuffer* buffer = NULL;
00289 TRAPD(err, buffer = CMMFPtrBuffer::NewL(ptr));
00290 if (err != KErrNone)
00291 {
00292 return OMX_ErrorInsufficientResources;
00293 }
00294 switch (nPortIndex)
00295 {
00296 case KIndexInputPort:
00297 {
00298 (*ppBufferHeader)->pInputPortPrivate = buffer;
00299 (*ppBufferHeader)->nInputPortIndex = nPortIndex;
00300 }
00301 break;
00302 case KIndexOutputPort:
00303 {
00304 (*ppBufferHeader)->pOutputPortPrivate = buffer;
00305 (*ppBufferHeader)->nOutputPortIndex = nPortIndex;
00306 }
00307 break;
00308
00309 }
00310 return OMX_ErrorNone;
00311 }
00312 else
00313 {
00314 return OMX_ErrorInsufficientResources;
00315 }
00316 }
00317
00318 OMX_ERRORTYPE COmxVorbisDecoder::AllocateBuffer(
00319 OMX_BUFFERHEADERTYPE** pBuffer,
00320 TUint32 nPortIndex,
00321 TAny* pAppData,
00322 TUint32 nSizeBytes)
00323 {
00324 ASSERT(iState == OMX_StateLoaded);
00325
00326 *pBuffer = new OMX_BUFFERHEADERTYPE;
00327 if (*pBuffer != NULL)
00328 {
00329 CMMFDescriptorBuffer* buffer = NULL;
00330 TRAPD(err, buffer = CMMFDescriptorBuffer::NewL(nSizeBytes));
00331 if (err != KErrNone)
00332 {
00333 return OMX_ErrorInsufficientResources;
00334 }
00335 (*pBuffer)->pBuffer = const_cast<TUint8*>(buffer->Data().Ptr());
00336
00337 switch (nPortIndex)
00338 {
00339 case KIndexInputPort:
00340 (*pBuffer)->pInputPortPrivate = buffer;
00341 (*pBuffer)->pOutputPortPrivate = NULL;
00342 break;
00343 case KIndexOutputPort:
00344 (*pBuffer)->pOutputPortPrivate = buffer;
00345 (*pBuffer)->pInputPortPrivate = NULL;
00346 break;
00347 };
00348
00349
00350 (*pBuffer)->nAllocLen = nSizeBytes;
00351 (*pBuffer)->nFilledLen = 0;
00352 (*pBuffer)->pAppPrivate = pAppData;
00353 }
00354
00355 if (*pBuffer && (*pBuffer)->pBuffer)
00356 {
00357 return OMX_ErrorNone;
00358 }
00359 else
00360 {
00361 return OMX_ErrorInsufficientResources;
00362 }
00363 }
00364
00365 OMX_ERRORTYPE COmxVorbisDecoder::FreeBuffer(
00366 TUint32 nPortIndex,
00367 OMX_BUFFERHEADERTYPE* pBuffer)
00368 {
00369 switch (nPortIndex)
00370 {
00371 case KIndexInputPort:
00372 {
00373 delete (static_cast<CMMFBuffer*>(pBuffer->pInputPortPrivate));
00374 pBuffer->pInputPortPrivate = NULL;
00375 break;
00376 }
00377 case KIndexOutputPort:
00378 delete (static_cast<CMMFBuffer*>(pBuffer->pOutputPortPrivate));
00379 pBuffer->pOutputPortPrivate = NULL;
00380 break;
00381
00382 }
00383 delete pBuffer;
00384 return OMX_ErrorNone;
00385 }
00386 OMX_ERRORTYPE COmxVorbisDecoder::EmptyThisBuffer(
00387 OMX_BUFFERHEADERTYPE* pBuffer)
00388 {
00389 ASSERT(iState == OMX_StateExecuting ||
00390 iState == OMX_StateIdle ||
00391 iState == OMX_StatePause);
00392 return iCodecProcessor->EmptyThisBuffer(pBuffer);
00393 }
00394 OMX_ERRORTYPE COmxVorbisDecoder::FillThisBuffer(
00395 OMX_BUFFERHEADERTYPE* pBuffer)
00396 {
00397 ASSERT(iState == OMX_StateExecuting ||
00398 iState == OMX_StateIdle ||
00399 iState == OMX_StatePause);
00400 return iCodecProcessor->FillThisBuffer(pBuffer);
00401 }
00402
00403 OMX_ERRORTYPE COmxVorbisDecoder::SetCallbacks(
00404 OMX_CALLBACKTYPE* pCallbacks,
00405 TAny* pAppData)
00406 {
00407 iCallback = pCallbacks;
00408 iAppData = pAppData;
00409 return OMX_ErrorNone;
00410 }
00411
00412 CCodecProcessor::CCodecProcessor(COmxVorbisDecoder& aParent)
00413 : iParent(&aParent)
00414 {
00415 }
00416
00417 void CCodecProcessor::RunThreadL()
00418 {
00419 iQueueStatus = KRequestPending;
00420 iMessageQueue.NotifyDataAvailable(iQueueStatus);
00421
00422 for (;;)
00423 {
00424 User::WaitForRequest(iQueueStatus);
00425 TCodecMessage msg;
00426
00427 TBool exit = EFalse;
00428
00429 while (iMessageQueue.Receive(msg)==KErrNone)
00430 {
00431 switch (msg.iType)
00432 {
00433 case EStopProcessing:
00434 iStarted = EFalse;
00435 iLastInputBuffer = EFalse;
00436 iBuffersToEmpty.Reset();
00437 iBuffersToFill.Reset();
00438 break;
00439 case EExit:
00440 exit = ETrue;
00441 break;
00442 case EInputBuffer:
00443 iBuffersToEmpty.Append(msg.iBuffer);
00444 break;
00445 case EOutputBuffer:
00446 iBuffersToFill.Append(msg.iBuffer);
00447 break;
00448 }
00449 }
00450
00451 if (exit)
00452 {
00453 break;
00454 }
00455 else
00456 {
00457
00458 ProcessAvailableBuffers();
00459
00460
00461 iQueueStatus = KRequestPending;
00462 iMessageQueue.NotifyDataAvailable(iQueueStatus);
00463 }
00464 }
00465 }
00466
00467 CCodecProcessor* CCodecProcessor::NewL(COmxVorbisDecoder& aParent)
00468 {
00469 CCodecProcessor* self = new (ELeave) CCodecProcessor(aParent);
00470 CleanupStack::PushL(self);
00471 self->ConstructL();
00472 CleanupStack::Pop(self);
00473 return self;
00474 }
00475
00476
00477 void CCodecProcessor::ConstructL()
00478 {
00479 User::LeaveIfError(iMessageQueue.CreateLocal(10));
00480
00481
00482
00483 iOutputBitsPerSample = KDefaultOutputBitsPerSample;
00484 iOutputDataType = KDefaultOutputDataType;
00485
00486
00487 iCodec = CVorbisDecoderProcessor::NewL();
00488
00489
00490 iDummyBuffer = (CMMFDataBuffer*)CMMFDescriptorBuffer::NewL();
00491 iDummyBuffer->SetStatus(EUnAvailable);
00492 }
00493
00494 OMX_ERRORTYPE CCodecProcessor::EmptyThisBuffer(
00495 OMX_BUFFERHEADERTYPE* pBuffer)
00496 {
00497 TCodecMessage message;
00498 message.iType = EInputBuffer;
00499 message.iBuffer = pBuffer;
00500 if (iMessageQueue.Send(message) == KErrNone)
00501 {
00502 return OMX_ErrorNone;
00503 }
00504 else
00505 {
00506 return OMX_ErrorUndefined;
00507 }
00508 }
00509
00510 void CCodecProcessor::Stop()
00511 {
00512 TCodecMessage message;
00513 message.iType = EStopProcessing;
00514 message.iBuffer = NULL;
00515 iMessageQueue.Send(message);
00516 }
00517
00518 void CCodecProcessor::Exit()
00519 {
00520 TCodecMessage message;
00521 message.iType = EExit;
00522 message.iBuffer = NULL;
00523 iMessageQueue.Send(message);
00524 }
00525
00526 OMX_ERRORTYPE CCodecProcessor::FillThisBuffer(
00527 OMX_BUFFERHEADERTYPE* pBuffer)
00528 {
00529 TCodecMessage message;
00530 message.iType = EOutputBuffer;
00531 message.iBuffer = pBuffer;
00532 if (iMessageQueue.Send(message)== KErrNone)
00533 {
00534 return OMX_ErrorNone;
00535 }
00536 else
00537 {
00538 return OMX_ErrorUndefined;
00539 }
00540 }
00541
00542 void CCodecProcessor::SetOutputBitsPerSample(TInt aOutputBitsPerSample)
00543 {
00544 iOutputBitsPerSample = aOutputBitsPerSample;
00545 }
00546
00547 void CCodecProcessor::SetOutputDataType(OMX_NUMERICALDATATYPE aType)
00548 {
00549 iOutputDataType = aType;
00550 }
00551
00552 void CCodecProcessor::ProcessAvailableBuffers()
00553 {
00554
00555 while (iBuffersToFill.Count()>0 && (iBuffersToEmpty.Count()>0 || iLastInputBuffer))
00556 {
00557 if (!iStarted)
00558 {
00559 iStarted = ETrue;
00560 }
00561
00562 OMX_BUFFERHEADERTYPE* srcBuffer = NULL;
00563 CMMFDataBuffer* mmfSrcBuffer = NULL;
00564
00565 TBool useSrcBuffer = iBuffersToEmpty.Count()>0;
00566 if (useSrcBuffer)
00567 {
00568 srcBuffer = iBuffersToEmpty[0];
00569 if (srcBuffer->nFlags & OMX_BUFFERFLAG_EOS)
00570 {
00571 iLastInputBuffer = ETrue;
00572 }
00573
00574
00575
00576
00577 mmfSrcBuffer = (CMMFDataBuffer*)(srcBuffer->pInputPortPrivate);
00578 mmfSrcBuffer->Data().SetLength(srcBuffer->nFilledLen);
00579 }
00580 else
00581 {
00582 if (!iLastInputBuffer)
00583 {
00584 return;
00585 }
00586
00587 mmfSrcBuffer = iDummyBuffer;
00588 }
00589
00590 OMX_BUFFERHEADERTYPE* destBuffer = iBuffersToFill[0];
00591 CMMFDataBuffer* mmfDestBuffer = (CMMFDataBuffer*)(destBuffer->pOutputPortPrivate);
00592 mmfDestBuffer->Data().SetLength(destBuffer->nFilledLen);
00593 const TDesC8& srcData = mmfSrcBuffer->Data();
00594 const TUint8* srcDataPtr = srcData.Ptr();
00595
00596 CVorbisDecoderProcessor::TProcessResult processResult;
00597 TUint bytesRead = 0;
00598 TUint bytesWritten = 0;
00599 TRAPD(err, iCodec->ProcessL(*mmfSrcBuffer,
00600 *mmfDestBuffer,
00601 processResult,
00602 bytesRead,
00603 bytesWritten) );
00604 if(err)
00605 {
00606
00607
00608 }
00609 if (useSrcBuffer)
00610 {
00611 srcBuffer->nFilledLen = 0;
00612 iBuffersToEmpty.Remove(0);
00613 iParent->EmptyBufferDoneCallback(srcBuffer);
00614 }
00615
00616 destBuffer->nFilledLen = bytesWritten;
00617 iBuffersToFill.Remove(0);
00618
00619 if (iLastInputBuffer && (bytesWritten == 0))
00620 {
00621
00622 iBuffersToFill.Reset();
00623 destBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
00624
00625 iParent->EventHandlerCallback(
00626 OMX_EventBufferFlag,
00627 0,
00628 destBuffer->nFlags,
00629 NULL);
00630 }
00631 iParent->FillBufferDoneCallback(destBuffer);
00632 }
00633 }
00634
00635 CCodecProcessor::~CCodecProcessor()
00636 {
00637 iBuffersToEmpty.Close();
00638 iBuffersToFill.Close();
00639 iMessageQueue.Close();
00640
00641
00642 delete iCodec;
00643 iCodec = NULL;
00644
00645 delete iDummyBuffer;
00646 iDummyBuffer = NULL;
00647 }
00648
00649 TInt COmxVorbisDecoder::StartExecution()
00650 {
00651
00652
00653 if (!iCreatedThread)
00654 {
00655
00656
00657 TTime threadTime;
00658 threadTime.HomeTime();
00659 TName threadName;
00660 threadName.Copy(KVorbisDecoder);
00661 threadName.AppendNum(threadTime.Int64(), EHex);
00662
00663 TInt err = iProcessingThread.Create(threadName,
00664 &ProcessingThread,
00665 KThreadStackSize,
00666 &User::Heap(),
00667 iCodecProcessor);
00668
00669 if (err!=KErrNone)
00670 {
00671 return err;
00672 }
00673 iCreatedThread = ETrue;
00674 iThreadDeath = KRequestPending;
00675 iProcessingThread.Resume();
00676 }
00677
00678 return KErrNone;
00679 }
00680
00681
00682 void COmxVorbisDecoder::EventHandlerCallback(
00683 OMX_OUT OMX_EVENTTYPE eEvent,
00684 OMX_OUT TUint32 nData1,
00685 OMX_OUT TUint32 nData2,
00686 OMX_OUT OMX_STRING cExtraInfo)
00687 {
00688 iCallback->EventHandler(
00689 this,
00690 iAppData,
00691 eEvent,
00692 nData1,
00693 nData2,
00694 cExtraInfo);
00695 }
00696
00697 void COmxVorbisDecoder::FillBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
00698 {
00699 iCallback->FillBufferDone(
00700 *this,
00701 iAppData,
00702 aBuffer);
00703 }
00704
00705 void COmxVorbisDecoder::EmptyBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
00706 {
00707 iCallback->EmptyBufferDone(
00708 *this,
00709 iAppData,
00710 aBuffer);
00711 }
00712
00713
00714 OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE hComponent)
00715 {
00716 TInt err = COmxVorbisDecoder::CreateComponent(hComponent);
00717 if (err == KErrNone)
00718 return OMX_ErrorNone;
00719 else
00720 {
00721
00722 return OMX_ErrorInsufficientResources;
00723
00724 }
00725 }