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 }
00300 break;
00301 case KIndexOutputPort:
00302 {
00303 (*ppBufferHeader)->pOutputPortPrivate = buffer;
00304 }
00305 break;
00306
00307 }
00308 return OMX_ErrorNone;
00309 }
00310 else
00311 {
00312 return OMX_ErrorInsufficientResources;
00313 }
00314 }
00315
00316 OMX_ERRORTYPE COmxVorbisDecoder::AllocateBuffer(
00317 OMX_BUFFERHEADERTYPE** pBuffer,
00318 TUint32 nPortIndex,
00319 TAny* pAppData,
00320 TUint32 nSizeBytes)
00321 {
00322 ASSERT(iState == OMX_StateLoaded);
00323
00324 *pBuffer = new OMX_BUFFERHEADERTYPE;
00325 if (*pBuffer != NULL)
00326 {
00327 CMMFDescriptorBuffer* buffer = NULL;
00328 TRAPD(err, buffer = CMMFDescriptorBuffer::NewL(nSizeBytes));
00329 if (err != KErrNone)
00330 {
00331 return OMX_ErrorInsufficientResources;
00332 }
00333 (*pBuffer)->pBuffer = const_cast<TUint8*>(buffer->Data().Ptr());
00334
00335 switch (nPortIndex)
00336 {
00337 case KIndexInputPort:
00338 (*pBuffer)->pInputPortPrivate = buffer;
00339 (*pBuffer)->pOutputPortPrivate = NULL;
00340 break;
00341 case KIndexOutputPort:
00342 (*pBuffer)->pOutputPortPrivate = buffer;
00343 (*pBuffer)->pInputPortPrivate = NULL;
00344 break;
00345 };
00346
00347
00348 (*pBuffer)->nAllocLen = nSizeBytes;
00349 (*pBuffer)->nFilledLen = 0;
00350 (*pBuffer)->pAppPrivate = pAppData;
00351 }
00352
00353 if (*pBuffer && (*pBuffer)->pBuffer)
00354 {
00355 return OMX_ErrorNone;
00356 }
00357 else
00358 {
00359 return OMX_ErrorInsufficientResources;
00360 }
00361 }
00362
00363 OMX_ERRORTYPE COmxVorbisDecoder::FreeBuffer(
00364 TUint32 nPortIndex,
00365 OMX_BUFFERHEADERTYPE* pBuffer)
00366 {
00367 switch (nPortIndex)
00368 {
00369 case KIndexInputPort:
00370 {
00371 delete (static_cast<CMMFBuffer*>(pBuffer->pInputPortPrivate));
00372 pBuffer->pInputPortPrivate = NULL;
00373 break;
00374 }
00375 case KIndexOutputPort:
00376 delete (static_cast<CMMFBuffer*>(pBuffer->pOutputPortPrivate));
00377 pBuffer->pOutputPortPrivate = NULL;
00378 break;
00379
00380 }
00381 delete pBuffer;
00382 return OMX_ErrorNone;
00383 }
00384 OMX_ERRORTYPE COmxVorbisDecoder::EmptyThisBuffer(
00385 OMX_BUFFERHEADERTYPE* pBuffer)
00386 {
00387 ASSERT(iState == OMX_StateExecuting ||
00388 iState == OMX_StateIdle ||
00389 iState == OMX_StatePause);
00390 return iCodecProcessor->EmptyThisBuffer(pBuffer);
00391 }
00392 OMX_ERRORTYPE COmxVorbisDecoder::FillThisBuffer(
00393 OMX_BUFFERHEADERTYPE* pBuffer)
00394 {
00395 ASSERT(iState == OMX_StateExecuting ||
00396 iState == OMX_StateIdle ||
00397 iState == OMX_StatePause);
00398 return iCodecProcessor->FillThisBuffer(pBuffer);
00399 }
00400
00401 OMX_ERRORTYPE COmxVorbisDecoder::SetCallbacks(
00402 OMX_CALLBACKTYPE* pCallbacks,
00403 TAny* pAppData)
00404 {
00405 iCallback = pCallbacks;
00406 iAppData = pAppData;
00407 return OMX_ErrorNone;
00408 }
00409
00410 CCodecProcessor::CCodecProcessor(COmxVorbisDecoder& aParent)
00411 : iParent(&aParent)
00412 {
00413 }
00414
00415 void CCodecProcessor::RunThreadL()
00416 {
00417 iQueueStatus = KRequestPending;
00418 iMessageQueue.NotifyDataAvailable(iQueueStatus);
00419
00420 for (;;)
00421 {
00422 User::WaitForRequest(iQueueStatus);
00423 TCodecMessage msg;
00424
00425 TBool exit = EFalse;
00426
00427 while (iMessageQueue.Receive(msg)==KErrNone)
00428 {
00429 switch (msg.iType)
00430 {
00431 case EStopProcessing:
00432 iStarted = EFalse;
00433 iLastInputBuffer = EFalse;
00434 iBuffersToEmpty.Reset();
00435 iBuffersToFill.Reset();
00436 break;
00437 case EExit:
00438 exit = ETrue;
00439 break;
00440 case EInputBuffer:
00441 iBuffersToEmpty.Append(msg.iBuffer);
00442 break;
00443 case EOutputBuffer:
00444 iBuffersToFill.Append(msg.iBuffer);
00445 break;
00446 }
00447 }
00448
00449 if (exit)
00450 {
00451 break;
00452 }
00453 else
00454 {
00455
00456 ProcessAvailableBuffers();
00457
00458
00459 iQueueStatus = KRequestPending;
00460 iMessageQueue.NotifyDataAvailable(iQueueStatus);
00461 }
00462 }
00463 }
00464
00465 CCodecProcessor* CCodecProcessor::NewL(COmxVorbisDecoder& aParent)
00466 {
00467 CCodecProcessor* self = new (ELeave) CCodecProcessor(aParent);
00468 CleanupStack::PushL(self);
00469 self->ConstructL();
00470 CleanupStack::Pop(self);
00471 return self;
00472 }
00473
00474
00475 void CCodecProcessor::ConstructL()
00476 {
00477 User::LeaveIfError(iMessageQueue.CreateLocal(10));
00478
00479
00480
00481 iOutputBitsPerSample = KDefaultOutputBitsPerSample;
00482 iOutputDataType = KDefaultOutputDataType;
00483
00484
00485 iCodec = CVorbisDecoderProcessor::NewL();
00486
00487
00488 iDummyBuffer = (CMMFDataBuffer*)CMMFDescriptorBuffer::NewL();
00489 iDummyBuffer->SetStatus(EUnAvailable);
00490 }
00491
00492 OMX_ERRORTYPE CCodecProcessor::EmptyThisBuffer(
00493 OMX_BUFFERHEADERTYPE* pBuffer)
00494 {
00495 TCodecMessage message;
00496 message.iType = EInputBuffer;
00497 message.iBuffer = pBuffer;
00498 if (iMessageQueue.Send(message) == KErrNone)
00499 {
00500 return OMX_ErrorNone;
00501 }
00502 else
00503 {
00504 return OMX_ErrorUndefined;
00505 }
00506 }
00507
00508 void CCodecProcessor::Stop()
00509 {
00510 TCodecMessage message;
00511 message.iType = EStopProcessing;
00512 message.iBuffer = NULL;
00513 iMessageQueue.Send(message);
00514 }
00515
00516 void CCodecProcessor::Exit()
00517 {
00518 TCodecMessage message;
00519 message.iType = EExit;
00520 message.iBuffer = NULL;
00521 iMessageQueue.Send(message);
00522 }
00523
00524 OMX_ERRORTYPE CCodecProcessor::FillThisBuffer(
00525 OMX_BUFFERHEADERTYPE* pBuffer)
00526 {
00527 TCodecMessage message;
00528 message.iType = EOutputBuffer;
00529 message.iBuffer = pBuffer;
00530 if (iMessageQueue.Send(message)== KErrNone)
00531 {
00532 return OMX_ErrorNone;
00533 }
00534 else
00535 {
00536 return OMX_ErrorUndefined;
00537 }
00538 }
00539
00540 void CCodecProcessor::SetOutputBitsPerSample(TInt aOutputBitsPerSample)
00541 {
00542 iOutputBitsPerSample = aOutputBitsPerSample;
00543 }
00544
00545 void CCodecProcessor::SetOutputDataType(OMX_NUMERICALDATATYPE aType)
00546 {
00547 iOutputDataType = aType;
00548 }
00549
00550 void CCodecProcessor::ProcessAvailableBuffers()
00551 {
00552
00553 while (iBuffersToFill.Count()>0 && (iBuffersToEmpty.Count()>0 || iLastInputBuffer))
00554 {
00555 if (!iStarted)
00556 {
00557 iStarted = ETrue;
00558 }
00559
00560 OMX_BUFFERHEADERTYPE* srcBuffer = NULL;
00561 CMMFDataBuffer* mmfSrcBuffer = NULL;
00562
00563 TBool useSrcBuffer = iBuffersToEmpty.Count()>0;
00564 if (useSrcBuffer)
00565 {
00566 srcBuffer = iBuffersToEmpty[0];
00567 if (srcBuffer->nFlags & OMX_BUFFERFLAG_EOS)
00568 {
00569 iLastInputBuffer = ETrue;
00570 }
00571
00572
00573
00574
00575 mmfSrcBuffer = (CMMFDataBuffer*)(srcBuffer->pInputPortPrivate);
00576 mmfSrcBuffer->Data().SetLength(srcBuffer->nFilledLen);
00577 }
00578 else
00579 {
00580 if (!iLastInputBuffer)
00581 {
00582 return;
00583 }
00584
00585 mmfSrcBuffer = iDummyBuffer;
00586 }
00587
00588 OMX_BUFFERHEADERTYPE* destBuffer = iBuffersToFill[0];
00589 CMMFDataBuffer* mmfDestBuffer = (CMMFDataBuffer*)(destBuffer->pOutputPortPrivate);
00590 mmfDestBuffer->Data().SetLength(destBuffer->nFilledLen);
00591 const TDesC8& srcData = mmfSrcBuffer->Data();
00592 const TUint8* srcDataPtr = srcData.Ptr();
00593
00594 CVorbisDecoderProcessor::TProcessResult processResult;
00595 TUint bytesRead = 0;
00596 TUint bytesWritten = 0;
00597 TRAPD(err, iCodec->ProcessL(*mmfSrcBuffer,
00598 *mmfDestBuffer,
00599 processResult,
00600 bytesRead,
00601 bytesWritten) );
00602 if(err)
00603 {
00604
00605
00606 }
00607 if (useSrcBuffer)
00608 {
00609 srcBuffer->nFilledLen = 0;
00610 iBuffersToEmpty.Remove(0);
00611 iParent->EmptyBufferDoneCallback(srcBuffer);
00612 }
00613
00614 destBuffer->nFilledLen = bytesWritten;
00615 iBuffersToFill.Remove(0);
00616
00617 if (iLastInputBuffer && (bytesWritten == 0))
00618 {
00619
00620 iBuffersToFill.Reset();
00621 destBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
00622
00623 iParent->EventHandlerCallback(
00624 OMX_EventBufferFlag,
00625 0,
00626 destBuffer->nFlags,
00627 NULL);
00628 }
00629 iParent->FillBufferDoneCallback(destBuffer);
00630 }
00631 }
00632
00633 CCodecProcessor::~CCodecProcessor()
00634 {
00635 iBuffersToEmpty.Close();
00636 iBuffersToFill.Close();
00637 iMessageQueue.Close();
00638
00639
00640 delete iCodec;
00641 iCodec = NULL;
00642
00643 delete iDummyBuffer;
00644 iDummyBuffer = NULL;
00645 }
00646
00647 TInt COmxVorbisDecoder::StartExecution()
00648 {
00649
00650
00651 if (!iCreatedThread)
00652 {
00653
00654
00655 TTime threadTime;
00656 threadTime.HomeTime();
00657 TName threadName;
00658 threadName.Copy(KVorbisDecoder);
00659 threadName.AppendNum(threadTime.Int64(), EHex);
00660
00661 TInt err = iProcessingThread.Create(threadName,
00662 &ProcessingThread,
00663 KThreadStackSize,
00664 &User::Heap(),
00665 iCodecProcessor,
00666 EOwnerThread);
00667
00668 if (err!=KErrNone)
00669 {
00670 return err;
00671 }
00672 iCreatedThread = ETrue;
00673 iThreadDeath = KRequestPending;
00674 iProcessingThread.Resume();
00675 }
00676
00677 return KErrNone;
00678 }
00679
00680
00681 void COmxVorbisDecoder::EventHandlerCallback(
00682 OMX_OUT OMX_EVENTTYPE eEvent,
00683 OMX_OUT TUint32 nData1,
00684 OMX_OUT TUint32 nData2,
00685 OMX_OUT OMX_STRING cExtraInfo)
00686 {
00687 iCallback->EventHandler(
00688 this,
00689 iAppData,
00690 eEvent,
00691 nData1,
00692 nData2,
00693 cExtraInfo);
00694 }
00695
00696 void COmxVorbisDecoder::FillBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
00697 {
00698 iCallback->FillBufferDone(
00699 *this,
00700 iAppData,
00701 aBuffer);
00702 }
00703
00704 void COmxVorbisDecoder::EmptyBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
00705 {
00706 iCallback->EmptyBufferDone(
00707 *this,
00708 iAppData,
00709 aBuffer);
00710 }
00711
00712
00713 OMX_ERRORTYPE ComponentInit(OMX_HANDLETYPE hComponent)
00714 {
00715 TInt err = COmxVorbisDecoder::CreateComponent(hComponent);
00716 if (err == KErrNone)
00717 return OMX_ErrorNone;
00718 else
00719 {
00720
00721 return OMX_ErrorInsufficientResources;
00722
00723 }
00724 }