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