sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include "OmxImpl.h" sl@0: #include "OmxPCMCodec.h" sl@0: sl@0: const TInt KPCMBufferSize = 4096; sl@0: sl@0: const TInt KThreadStackSize = 16384; sl@0: sl@0: const TInt KShutDownTime = 5000000; sl@0: sl@0: sl@0: TInt ProcessingThread(TAny* aComponent) sl@0: { sl@0: // get our class sl@0: CCodecProcessor* codecprocessor = static_cast(aComponent); sl@0: sl@0: // run the thread sl@0: TRAPD(err, codecprocessor->RunThreadL()); sl@0: // thread has exited or failed to start so return error to the client. sl@0: return err; sl@0: } sl@0: sl@0: sl@0: TInt COmxPCMCodec::CreateComponent(OMX_HANDLETYPE hComponent) sl@0: { sl@0: COmxPCMCodec* self = new COmxPCMCodec(hComponent); sl@0: if (self==NULL) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: TRAPD(err, self->ConstructL()); sl@0: // self is stored in the handle, so we won't return it sl@0: return err; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::GetComponentVersion( sl@0: OMX_STRING /*pComponentName*/, sl@0: OMX_VERSIONTYPE* /*pComponentVersion*/, sl@0: OMX_VERSIONTYPE* /*pSpecVersion*/, sl@0: OMX_UUIDTYPE* /*pComponentUUID*/) sl@0: { sl@0: // to be implemented sl@0: return OMX_ErrorNone; sl@0: } sl@0: sl@0: sl@0: void COmxPCMCodec::ConstructL() sl@0: { sl@0: iCodecProcessor = CCodecProcessor::NewL(*this); sl@0: iState = OMX_StateLoaded; sl@0: } sl@0: sl@0: COmxPCMCodec::COmxPCMCodec(OMX_HANDLETYPE hComponent) sl@0: :COmxComponentImpl(hComponent) sl@0: { sl@0: } sl@0: sl@0: COmxPCMCodec::~COmxPCMCodec() sl@0: { sl@0: if (iState == OMX_StateExecuting) sl@0: { sl@0: iCodecProcessor->Stop(); sl@0: iState = OMX_StateIdle; sl@0: } sl@0: sl@0: if (iCreatedThread &&(iProcessingThread.Handle() != KNullHandle) && (iProcessingThread.ExitType() == EExitPending)) sl@0: { sl@0: TRequestStatus logonStatus; sl@0: TBool logonFailed = EFalse; sl@0: iProcessingThread.Logon(logonStatus); sl@0: if(logonStatus != KRequestPending) sl@0: {//logon failed. Mostly due to no memory sl@0: logonFailed = ETrue; sl@0: } sl@0: iCodecProcessor->Exit(); sl@0: RTimer timer; sl@0: TInt err = timer.CreateLocal(); sl@0: if(err==KErrNone && !logonFailed) //both timer and logon successful sl@0: { sl@0: TRequestStatus timeout; sl@0: timer.After(timeout, KShutDownTime); sl@0: User::WaitForRequest(logonStatus, timeout); sl@0: if(logonStatus==KRequestPending) sl@0: {//Thread has not exited after the timeout. Kill it! sl@0: iProcessingThread.LogonCancel(logonStatus); sl@0: User::WaitForRequest(logonStatus); sl@0: iProcessingThread.Kill(KErrDied); sl@0: } sl@0: else sl@0: {//Thread exited. Cancel the timer sl@0: timer.Cancel(); sl@0: User::WaitForRequest(timeout); sl@0: } sl@0: } sl@0: else sl@0: {//either timer or Logon method has failed.Poll the thread status a maximum sl@0: // of 10 times and kill the thread if it hasn't exited after the polling sl@0: for (TInt i=0; i<10 && iProcessingThread.ExitType() == EExitPending; ++i) sl@0: { sl@0: User::After(KShutDownTime/10); // wait for a while sl@0: } sl@0: sl@0: if (iProcessingThread.ExitType() == EExitPending) sl@0: { sl@0: // The polling hasn't been succesful so we kill the thread sl@0: iProcessingThread.Kill(KErrDied); sl@0: } sl@0: if(!logonFailed) sl@0: { sl@0: User::WaitForRequest(logonStatus); sl@0: } sl@0: } sl@0: iProcessingThread.Close(); sl@0: } sl@0: delete iCodecProcessor; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::SendCommand( sl@0: OMX_COMMANDTYPE Cmd, sl@0: TUint32 nParam1, sl@0: TAny* /*pCmdData*/) sl@0: { sl@0: OMX_ERRORTYPE error = OMX_ErrorNone; sl@0: switch (Cmd) sl@0: { sl@0: case OMX_CommandStateSet: sl@0: OMX_STATETYPE state = (OMX_STATETYPE)nParam1; sl@0: if (state == iState) sl@0: { sl@0: error = OMX_ErrorSameState; sl@0: } sl@0: else sl@0: { sl@0: // notify client of the state change sl@0: switch (state) sl@0: { sl@0: case OMX_StateIdle: sl@0: { sl@0: if (iState == OMX_StateExecuting) sl@0: { sl@0: iCodecProcessor->Stop(); sl@0: } sl@0: break; sl@0: } sl@0: case OMX_StateExecuting: sl@0: StartExecution(); sl@0: break; sl@0: }; sl@0: sl@0: iState = state; sl@0: sl@0: EventHandlerCallback( sl@0: OMX_EventCmdComplete, sl@0: OMX_CommandStateSet, sl@0: iState, sl@0: NULL); sl@0: break; sl@0: } sl@0: }; sl@0: return error; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::GetParameter( sl@0: OMX_INDEXTYPE nParamIndex, sl@0: TAny* ComponentParameterStructure) sl@0: { sl@0: switch (nParamIndex) sl@0: { sl@0: case OMX_IndexParamAudioInit : sl@0: { sl@0: OMX_PORT_PARAM_TYPE* param = static_cast(ComponentParameterStructure); sl@0: param->nPorts = 2; sl@0: } sl@0: break; sl@0: case OMX_IndexParamPortDefinition: sl@0: { sl@0: OMX_PARAM_PORTDEFINITIONTYPE* portDef = static_cast(ComponentParameterStructure); sl@0: if (portDef->nPortIndex==0) sl@0: { sl@0: portDef->eDir = OMX_DirInput; sl@0: portDef->nBufferSize = KPCMBufferSize; sl@0: } sl@0: else sl@0: { sl@0: portDef->eDir = OMX_DirOutput; sl@0: portDef->nBufferSize = KPCMBufferSize; sl@0: } sl@0: } sl@0: break; sl@0: default: sl@0: return OMX_ErrorUnsupportedIndex; sl@0: } sl@0: return OMX_ErrorNone; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::SetParameter( sl@0: OMX_INDEXTYPE nIndex, sl@0: TAny* ComponentParameterStructure) sl@0: { sl@0: ASSERT(iState == OMX_StateLoaded); sl@0: switch (nIndex) sl@0: { sl@0: case OMX_IndexParamAudioPcm: sl@0: { sl@0: OMX_AUDIO_PARAM_PCMMODETYPE* param = static_cast(ComponentParameterStructure); sl@0: switch(param->nPortIndex) sl@0: { sl@0: case 0: // Input port sl@0: { sl@0: iCodecProcessor->SetInputBitsPerSample(param->nBitPerSample); sl@0: iCodecProcessor->SetInputDataType(param->eNumData); sl@0: //break; sl@0: return OMX_ErrorNone; sl@0: } sl@0: case 1: // Output port sl@0: { sl@0: iCodecProcessor->SetOutputBitsPerSample(param->nBitPerSample); sl@0: iCodecProcessor->SetOutputDataType(param->eNumData); sl@0: //break; sl@0: return OMX_ErrorNone; sl@0: } sl@0: default: sl@0: { sl@0: return OMX_ErrorUnsupportedIndex; sl@0: } sl@0: }; sl@0: } sl@0: default: sl@0: { sl@0: return OMX_ErrorUnsupportedIndex; sl@0: } sl@0: }; sl@0: //return OMX_ErrorNone; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::GetConfig( sl@0: OMX_INDEXTYPE /*nIndex*/, sl@0: TAny* /*value*/) sl@0: { sl@0: return OMX_ErrorUnsupportedIndex; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::SetConfig( sl@0: OMX_INDEXTYPE /*nIndex*/, sl@0: TAny* /*value*/) sl@0: { sl@0: return OMX_ErrorUnsupportedIndex; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::GetExtensionIndex( sl@0: OMX_STRING /*ParameterName*/, sl@0: OMX_INDEXTYPE* /*pIndexType*/) sl@0: { sl@0: return OMX_ErrorNotImplemented; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::GetState( sl@0: OMX_STATETYPE* pState) sl@0: { sl@0: *pState = iState; sl@0: return OMX_ErrorNone; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::ComponentTunnelRequest( sl@0: OMX_HANDLETYPE /*hInput*/, sl@0: TUint32 /*nInputPort*/, sl@0: OMX_HANDLETYPE /*hOutput*/, sl@0: TUint32 /*nOutputPort*/, sl@0: OMX_TUNNELSETUPTYPE* /*pTunnelSetup*/) sl@0: { sl@0: return OMX_ErrorNotImplemented; sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::UseBuffer( sl@0: OMX_BUFFERHEADERTYPE** ppBufferHeader, sl@0: TUint32 /*nPortIndex*/, sl@0: TAny* pAppPrivate, sl@0: TUint32 nSizeBytes, sl@0: TUint8* pBuffer) sl@0: { sl@0: ASSERT(iState == OMX_StateLoaded); sl@0: *ppBufferHeader = new OMX_BUFFERHEADERTYPE; sl@0: if (*ppBufferHeader != NULL) sl@0: { sl@0: (*ppBufferHeader)->pBuffer = pBuffer; sl@0: (*ppBufferHeader)->pAppPrivate = pAppPrivate; sl@0: (*ppBufferHeader)->nAllocLen = nSizeBytes; sl@0: (*ppBufferHeader)->nFilledLen = 0; sl@0: (*ppBufferHeader)->nFlags = 0; sl@0: (*ppBufferHeader)->pInputPortPrivate = NULL; sl@0: (*ppBufferHeader)->pOutputPortPrivate = NULL; sl@0: } sl@0: sl@0: if (*ppBufferHeader) sl@0: { sl@0: return OMX_ErrorNone; sl@0: } sl@0: else sl@0: { sl@0: return OMX_ErrorInsufficientResources; sl@0: } sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::AllocateBuffer( sl@0: OMX_BUFFERHEADERTYPE** pBuffer, sl@0: TUint32 nPortIndex, sl@0: TAny* pAppData, sl@0: TUint32 nSizeBytes) sl@0: { sl@0: ASSERT(iState == OMX_StateLoaded); sl@0: sl@0: *pBuffer = new OMX_BUFFERHEADERTYPE; sl@0: if (*pBuffer != NULL) sl@0: { sl@0: (*pBuffer)->pBuffer = new unsigned char[nSizeBytes]; sl@0: // store our allocated memory in component's private store sl@0: switch (nPortIndex) sl@0: { sl@0: case 0: sl@0: (*pBuffer)->pInputPortPrivate = (*pBuffer)->pBuffer; sl@0: (*pBuffer)->pOutputPortPrivate = NULL; sl@0: break; sl@0: case 1: sl@0: (*pBuffer)->pOutputPortPrivate = (*pBuffer)->pBuffer; sl@0: (*pBuffer)->pInputPortPrivate = NULL; sl@0: break; sl@0: }; sl@0: sl@0: sl@0: (*pBuffer)->nAllocLen = nSizeBytes; sl@0: (*pBuffer)->nFilledLen = 0; sl@0: (*pBuffer)->pAppPrivate = pAppData; sl@0: } sl@0: sl@0: if (*pBuffer && (*pBuffer)->pBuffer) sl@0: { sl@0: return OMX_ErrorNone; sl@0: } sl@0: else sl@0: { sl@0: return OMX_ErrorInsufficientResources; sl@0: } sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::FreeBuffer( sl@0: TUint32 /*nPortIndex*/, sl@0: OMX_BUFFERHEADERTYPE* pBuffer) sl@0: { sl@0: if (pBuffer->pInputPortPrivate || sl@0: pBuffer->pOutputPortPrivate) sl@0: delete[] pBuffer->pBuffer; sl@0: delete pBuffer; sl@0: return OMX_ErrorNone; sl@0: } sl@0: OMX_ERRORTYPE COmxPCMCodec::EmptyThisBuffer( sl@0: OMX_BUFFERHEADERTYPE* pBuffer) sl@0: { sl@0: ASSERT(iState == OMX_StateExecuting || sl@0: iState == OMX_StateIdle || sl@0: iState == OMX_StatePause); sl@0: return iCodecProcessor->EmptyThisBuffer(pBuffer); sl@0: } sl@0: OMX_ERRORTYPE COmxPCMCodec::FillThisBuffer( sl@0: OMX_BUFFERHEADERTYPE* pBuffer) sl@0: { sl@0: ASSERT(iState == OMX_StateExecuting || sl@0: iState == OMX_StateIdle || sl@0: iState == OMX_StatePause); sl@0: return iCodecProcessor->FillThisBuffer(pBuffer); sl@0: } sl@0: sl@0: OMX_ERRORTYPE COmxPCMCodec::SetCallbacks( sl@0: OMX_CALLBACKTYPE* pCallbacks, sl@0: TAny* pAppData) sl@0: { sl@0: iCallback = pCallbacks; sl@0: iAppData = pAppData; sl@0: return OMX_ErrorNone; sl@0: } sl@0: sl@0: sl@0: CCodecProcessor::CCodecProcessor(COmxPCMCodec& aParent) sl@0: : iParent(&aParent) sl@0: { sl@0: } sl@0: sl@0: void CCodecProcessor::RunThreadL() sl@0: { sl@0: iQueueStatus = KRequestPending; sl@0: iMessageQueue.NotifyDataAvailable(iQueueStatus); sl@0: sl@0: for (;;) sl@0: { sl@0: User::WaitForRequest(iQueueStatus); sl@0: TCodecMessage msg; sl@0: sl@0: TBool exit = EFalse; sl@0: sl@0: while (iMessageQueue.Receive(msg)==KErrNone) sl@0: { sl@0: switch (msg.iType) sl@0: { sl@0: case EStopProcessing: sl@0: iStarted = EFalse; sl@0: break; sl@0: case EExit: sl@0: exit = ETrue; sl@0: break; sl@0: case EInputBuffer: sl@0: iBuffersToEmpty.Append(msg.iBuffer); sl@0: break; sl@0: case EOutputBuffer: sl@0: iBuffersToFill.Append(msg.iBuffer); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if (exit) sl@0: { sl@0: break; sl@0: } sl@0: else sl@0: { sl@0: // process all available buffers sl@0: ProcessAvailableBuffers(); sl@0: sl@0: // request notification of further queue events sl@0: iQueueStatus = KRequestPending; sl@0: iMessageQueue.NotifyDataAvailable(iQueueStatus); sl@0: } sl@0: } sl@0: sl@0: } sl@0: sl@0: sl@0: CCodecProcessor* CCodecProcessor::NewL(COmxPCMCodec& aParent) sl@0: { sl@0: CCodecProcessor* self = new (ELeave) CCodecProcessor(aParent); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: void CCodecProcessor::ConstructL() sl@0: { sl@0: User::LeaveIfError(iMessageQueue.CreateLocal(10)); sl@0: // set the default case sl@0: iInputBitsPerSample = 8; sl@0: iInputDataType = OMX_NumericalDataUnsigned; sl@0: iOutputBitsPerSample = 16; sl@0: iOutputDataType = OMX_NumericalDataSigned; sl@0: } sl@0: sl@0: OMX_ERRORTYPE CCodecProcessor::EmptyThisBuffer( sl@0: OMX_BUFFERHEADERTYPE* pBuffer) sl@0: { sl@0: TCodecMessage message; sl@0: message.iType = EInputBuffer; sl@0: message.iBuffer = pBuffer; sl@0: if (iMessageQueue.Send(message) == KErrNone) sl@0: { sl@0: return OMX_ErrorNone; sl@0: } sl@0: else sl@0: { sl@0: return OMX_ErrorUndefined; sl@0: } sl@0: } sl@0: sl@0: void CCodecProcessor::Stop() sl@0: { sl@0: TCodecMessage message; sl@0: message.iType = EStopProcessing; sl@0: message.iBuffer = NULL; sl@0: iMessageQueue.Send(message); sl@0: } sl@0: sl@0: void CCodecProcessor::Exit() sl@0: { sl@0: TCodecMessage message; sl@0: message.iType = EExit; sl@0: message.iBuffer = NULL; sl@0: iMessageQueue.SendBlocking(message); sl@0: } sl@0: sl@0: OMX_ERRORTYPE CCodecProcessor::FillThisBuffer( sl@0: OMX_BUFFERHEADERTYPE* pBuffer) sl@0: { sl@0: TCodecMessage message; sl@0: message.iType = EOutputBuffer; sl@0: message.iBuffer = pBuffer; sl@0: if (iMessageQueue.Send(message)== KErrNone) sl@0: { sl@0: return OMX_ErrorNone; sl@0: } sl@0: else sl@0: { sl@0: return OMX_ErrorUndefined; sl@0: } sl@0: } sl@0: sl@0: void CCodecProcessor::SetInputBitsPerSample(TInt aInputBitsPerSample) sl@0: { sl@0: iInputBitsPerSample = aInputBitsPerSample; sl@0: } sl@0: sl@0: void CCodecProcessor::SetInputDataType(OMX_NUMERICALDATATYPE aType) sl@0: { sl@0: iInputDataType = aType; sl@0: } sl@0: sl@0: void CCodecProcessor::SetOutputBitsPerSample(TInt aInputBitsPerSample) sl@0: { sl@0: iOutputBitsPerSample = aInputBitsPerSample; sl@0: } sl@0: sl@0: void CCodecProcessor::SetOutputDataType(OMX_NUMERICALDATATYPE aType) sl@0: { sl@0: iOutputDataType = aType; sl@0: } sl@0: sl@0: void CCodecProcessor::ChooseCodec() sl@0: { sl@0: // choose correct conversion codec sl@0: if (iInputBitsPerSample == 8 && iOutputBitsPerSample == 16) sl@0: { sl@0: iOutputSamplesPerInputSample = 2; sl@0: if (iInputDataType == OMX_NumericalDataSigned && sl@0: iOutputDataType == OMX_NumericalDataSigned) sl@0: { sl@0: iCurrentCodec = &iAudioS8ToS16PcmCodec; sl@0: } sl@0: else if (iInputDataType == OMX_NumericalDataUnsigned && sl@0: iOutputDataType == OMX_NumericalDataSigned) sl@0: { sl@0: iCurrentCodec = &iAudioU8ToS16PcmCodec; sl@0: } sl@0: } sl@0: else if (iInputBitsPerSample == 16 && iOutputBitsPerSample == 8) sl@0: { sl@0: iOutputSamplesPerInputSample = .5; sl@0: if (iInputDataType == OMX_NumericalDataSigned && sl@0: iOutputDataType == OMX_NumericalDataSigned) sl@0: { sl@0: iCurrentCodec = &iAudioS16ToS8PcmCodec; sl@0: } sl@0: else if (iInputDataType == OMX_NumericalDataSigned && sl@0: iOutputDataType == OMX_NumericalDataUnsigned) sl@0: { sl@0: iCurrentCodec = &iAudioS16ToU8PcmCodec; sl@0: } sl@0: } sl@0: sl@0: } sl@0: sl@0: void CCodecProcessor::ProcessAvailableBuffers() sl@0: { sl@0: // Setup wait for data in queue sl@0: while (iBuffersToFill.Count()>0 && iBuffersToEmpty.Count() > 0) sl@0: { sl@0: TBool lastBuffer = EFalse; sl@0: if (!iStarted) sl@0: { sl@0: ChooseCodec(); sl@0: iStarted = ETrue; sl@0: } sl@0: sl@0: OMX_BUFFERHEADERTYPE* srcBuffer = iBuffersToEmpty[0]; sl@0: OMX_BUFFERHEADERTYPE* destBuffer = iBuffersToFill[0]; sl@0: if (srcBuffer->nFlags & OMX_BUFFERFLAG_EOS) sl@0: { sl@0: lastBuffer = ETrue; sl@0: } sl@0: TInt destBufferPos = destBuffer->nFilledLen; sl@0: sl@0: TInt destBufferSize = destBuffer->nAllocLen - destBufferPos; sl@0: TInt inputSamplesRequired = (TInt)((TReal)destBufferSize / iOutputSamplesPerInputSample); sl@0: sl@0: TInt availableSamples = srcBuffer->nFilledLen - iInputBufferPos; sl@0: sl@0: if (availableSamples <= inputSamplesRequired) sl@0: { sl@0: TInt samplesToConvert = availableSamples; sl@0: if (iOutputSamplesPerInputSample == .5) sl@0: { sl@0: samplesToConvert >>= 1; sl@0: } sl@0: iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert); sl@0: iInputBufferPos = 0; // finished buffer - so reset sl@0: inputSamplesRequired -= availableSamples; sl@0: destBuffer->nFilledLen = (TInt)((TReal)availableSamples * iOutputSamplesPerInputSample); sl@0: srcBuffer->nFilledLen = 0; sl@0: iBuffersToEmpty.Remove(0); sl@0: iParent->EmptyBufferDoneCallback(srcBuffer); sl@0: sl@0: if (inputSamplesRequired == 0 || lastBuffer) sl@0: { sl@0: iBuffersToFill.Remove(0); sl@0: if (lastBuffer) sl@0: { sl@0: destBuffer->nFlags |= OMX_BUFFERFLAG_EOS; sl@0: // propagate the EOS flag sl@0: iParent->EventHandlerCallback( sl@0: OMX_EventBufferFlag, sl@0: 0, sl@0: destBuffer->nFlags, sl@0: NULL); sl@0: } sl@0: iParent->FillBufferDoneCallback(destBuffer); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: TInt samplesToConvert = inputSamplesRequired; sl@0: if (iOutputSamplesPerInputSample == .5) sl@0: { sl@0: samplesToConvert >>= 2; sl@0: } sl@0: sl@0: iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert); sl@0: iInputBufferPos += inputSamplesRequired; sl@0: destBuffer->nFilledLen = destBuffer->nAllocLen; sl@0: iBuffersToFill.Remove(0); sl@0: iParent->FillBufferDoneCallback(destBuffer); sl@0: } sl@0: } sl@0: } sl@0: sl@0: CCodecProcessor::~CCodecProcessor() sl@0: { sl@0: iBuffersToEmpty.Close(); sl@0: iBuffersToFill.Close(); sl@0: iMessageQueue.Close(); sl@0: } sl@0: sl@0: sl@0: TInt COmxPCMCodec::StartExecution() sl@0: { sl@0: // create thread with current thread's heap sl@0: // we can thus allocate and free memory across threads sl@0: if (!iCreatedThread) sl@0: { sl@0: TInt err = iProcessingThread.Create(_L("PCMCodec"), sl@0: &ProcessingThread, sl@0: KThreadStackSize, sl@0: &User::Heap(), sl@0: iCodecProcessor); sl@0: sl@0: if (err!=KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: iCreatedThread = ETrue; sl@0: iThreadDeath = KRequestPending; sl@0: iProcessingThread.Resume(); sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: // Callbacks for the PCM codec sl@0: void COmxPCMCodec::EventHandlerCallback( sl@0: OMX_OUT OMX_EVENTTYPE eEvent, sl@0: OMX_OUT TUint32 nData1, sl@0: OMX_OUT TUint32 nData2, sl@0: OMX_OUT OMX_STRING cExtraInfo) sl@0: { sl@0: iCallback->EventHandler( sl@0: this, sl@0: iAppData, sl@0: eEvent, sl@0: nData1, sl@0: nData2, sl@0: cExtraInfo); sl@0: } sl@0: sl@0: sl@0: void COmxPCMCodec::FillBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer) sl@0: { sl@0: iCallback->FillBufferDone( sl@0: *this, sl@0: iAppData, sl@0: aBuffer); sl@0: } sl@0: sl@0: void COmxPCMCodec::EmptyBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer) sl@0: { sl@0: iCallback->EmptyBufferDone( sl@0: *this, sl@0: iAppData, sl@0: aBuffer); sl@0: } sl@0: sl@0: // Component Entry Point sl@0: OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE hComponent) sl@0: { sl@0: TInt err = COmxPCMCodec::CreateComponent(hComponent); sl@0: if (err == KErrNone) sl@0: { sl@0: return OMX_ErrorNone; sl@0: } sl@0: else sl@0: { sl@0: // return problem sl@0: return OMX_ErrorInsufficientResources; sl@0: } sl@0: }