sl@0: // Copyright (c) 2006-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: // This is a re-implementation of CMdfHwDeviceCodecTestAdapter sl@0: // primarily intended for unit testing codec PUs in PREQ1024. sl@0: // It is NOT a subclass, as CMdfHwDeviceCodecTestAdapter itself has no sl@0: // virtual or protected methods to override. sl@0: // The only difference is that it encodes and decodes from codec sl@0: // to codec, unlike CMdfHwDeviceCodecTestAdapter which encodes from sounddev sl@0: // (mic) to codec and decodes from codec to sounddev (speaker) sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @internalComponent sl@0: */ sl@0: sl@0: #include "audiocodectestadapter.h" sl@0: #include sl@0: #include sl@0: // for the bitrate custom interface sl@0: #include sl@0: sl@0: #include sl@0: sl@0: // #define AUDIOCODECTESTADAPTER_DEBUG 1 sl@0: #if defined(AUDIOCODECTESTADAPTER_DEBUG) sl@0: #define DEBUG_PRINT RDebug::Print sl@0: #else sl@0: #define DEBUG_PRINT sl@0: #endif sl@0: sl@0: // Interface UID for the Processing Unit Loader sl@0: const TUid KUidPuLoader = {KUidPuLoaderImplementation}; sl@0: sl@0: sl@0: CMdfHwDeviceCodecTestAdapter::~CMdfHwDeviceCodecTestAdapter() sl@0: { sl@0: Stop(); sl@0: // Unload the PUs sl@0: if (iCodecPU) sl@0: { sl@0: iPuLoader->UnloadProcessingUnit(iCodecPU); sl@0: } sl@0: sl@0: // The I/O ports should have been deleted at this point sl@0: sl@0: delete iInputBuffer; sl@0: delete iOutputBuffer; sl@0: delete iActiveWait; sl@0: delete iPuLoader; sl@0: REComSession::DestroyedImplementation(iPuLoaderDtorKey); sl@0: } sl@0: sl@0: CMdfHwDeviceCodecTestAdapter* CMdfHwDeviceCodecTestAdapter::NewL() sl@0: { sl@0: CMdfHwDeviceCodecTestAdapter* self = new (ELeave) CMdfHwDeviceCodecTestAdapter; sl@0: CleanupStack::PushL (self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CMdfHwDeviceCodecTestAdapter::CMdfHwDeviceCodecTestAdapter() sl@0: { sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::ConstructL() sl@0: { sl@0: // Load the PU Loader plugin sl@0: iPuLoader = static_cast sl@0: (REComSession::CreateImplementationL(KUidPuLoader, iPuLoaderDtorKey)); sl@0: iActiveWait = new (ELeave) CActiveSchedulerWait; sl@0: iState = EProcessingUnitLoaderLoaded; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::Start(TDeviceFunc aFuncCmd, TDeviceFlow /*aFlowCmd*/) sl@0: { sl@0: if (!((aFuncCmd == EDevEncode)|(aFuncCmd == EDevDecode)|(aFuncCmd == EDevNullFunc))) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: iFuncCmd = aFuncCmd; sl@0: sl@0: // NB: aFlowCmd not used - this is codec-codec processing by default. sl@0: sl@0: TInt err = KErrNone; sl@0: switch(aFuncCmd) sl@0: { sl@0: case EDevEncode: sl@0: { sl@0: err = StartEncode(); sl@0: } sl@0: break; sl@0: case EDevDecode: sl@0: { sl@0: err = StartDecode(); sl@0: } sl@0: break; sl@0: case EDevNullFunc: sl@0: default: sl@0: { sl@0: err = KErrNotSupported; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: sl@0: return err; sl@0: } sl@0: sl@0: // encode and decode logic is identical for codec-codec processing sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::InitializeEncodeDecode() sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::InitializeEncodeDecode")); sl@0: sl@0: ASSERT(iOutputPort); sl@0: sl@0: iInputPortBufferSize = iInputPort->MipBufferSize(); sl@0: TRAPD(err, iInputBuffer = CMMFDescriptorBuffer::NewL(iInputPortBufferSize)); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: iInputBuffer->SetLastBuffer(EFalse); sl@0: iInputPort->MipUseBuffer(*iInputBuffer); sl@0: sl@0: iOutputPortBufferSize = iOutputPort->MopBufferSize(); sl@0: TRAP(err, iOutputBuffer = CMMFDescriptorBuffer::NewL(iOutputPortBufferSize)); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: iOutputBuffer->SetLastBuffer(EFalse); sl@0: iOutputPort->MopUseBuffer(*iOutputBuffer); sl@0: sl@0: // VD: should not move the set up of the state after sending the Initialize() calls??? sl@0: iState = EProcessingUnitInitializing; sl@0: sl@0: iCodecPU->Initialize(); sl@0: sl@0: iActiveWait->Start(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::StartEncode() sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::StartEncode")); sl@0: TInt err = KErrNone; sl@0: if (iState == EProcessingUnitLoaded) sl@0: { sl@0: err = InitializeEncodeDecode(); sl@0: } sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: return StartExecuting(); sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::StartDecode() sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::StartDecode")); sl@0: sl@0: TInt err = KErrNone; sl@0: if (iState == EProcessingUnitLoaded) sl@0: { sl@0: err = InitializeEncodeDecode(); sl@0: } sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: return StartExecuting(); sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::StartExecuting() sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::StartExecuting")); sl@0: TInt err = KErrNone; sl@0: sl@0: iOutputPort->MopReadData(*iOutputBuffer); sl@0: err = iHwDeviceObserver->FillThisHwBuffer(*iInputBuffer); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: iState = EProcessingUnitExecuting; sl@0: iCodecPU->Execute(); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::Stop() sl@0: { sl@0: if(iState == EProcessingUnitExecuting || iState == EProcessingUnitPaused) sl@0: { sl@0: iStopping = ETrue; // is used as a guard in ExecuteComplete sl@0: sl@0: if(iCodecPU) sl@0: { sl@0: iCodecPU->Stop(); sl@0: } sl@0: sl@0: iPCMPUCallbackComplete = EFalse; sl@0: sl@0: iState = EProcessingUnitIdle; sl@0: iStopping = EFalse; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::Pause() sl@0: { sl@0: return iCodecPU->Pause(); sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::Init(THwDeviceInitParams& aDevInfo) sl@0: { sl@0: if(!iCodecPU) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: // Not currently using any other members of aDevInfo, except the Observer sl@0: if(!aDevInfo.iHwDeviceObserver) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: iHwDeviceObserver = aDevInfo.iHwDeviceObserver; sl@0: sl@0: // Get ports and set observers sl@0: RPointerArray inputPorts; sl@0: TInt err = iCodecPU->GetInputPorts(inputPorts); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: if (inputPorts.Count()<1) sl@0: { sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: iInputPort = inputPorts[0]; sl@0: inputPorts.Close(); sl@0: sl@0: iInputPort->MipSetObserver(*this); sl@0: sl@0: RPointerArray outputPorts; sl@0: err = iCodecPU->GetOutputPorts(outputPorts); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: if (outputPorts.Count()<1) sl@0: { sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: iOutputPort = outputPorts[0]; sl@0: outputPorts.Close(); sl@0: iOutputPort->MopSetObserver(*this); sl@0: sl@0: iState = EProcessingUnitLoaded; sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TAny* CMdfHwDeviceCodecTestAdapter::CustomInterface(TUid aInterfaceId) sl@0: { sl@0: if (aInterfaceId == KUidHwDeviceSetupInterface) sl@0: { sl@0: return static_cast(this); sl@0: } sl@0: else if (aInterfaceId.iUid == KMmfPlaySettingsCustomInterface) sl@0: { sl@0: return reinterpret_cast(iInputPort); sl@0: } sl@0: else if (aInterfaceId.iUid == KMmfRecordSettingsCustomInterface) sl@0: { sl@0: return reinterpret_cast(iOutputPort); sl@0: } sl@0: // if the PU is an encoder it may have a BitRate custom interface sl@0: else if (aInterfaceId == KUidCustomInterfaceDevSoundBitRate) sl@0: { sl@0: return static_cast(iCodecPU->CustomInterface(aInterfaceId)); sl@0: } sl@0: else sl@0: { sl@0: return NULL; sl@0: } sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::ThisHwBufferFilled(CMMFBuffer& aFillBufferPtr) sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::ThisHwBufferFilled")); sl@0: sl@0: aFillBufferPtr.SetStatus(EFull); sl@0: sl@0: // if the buffer is empty or the last buffer, write it anyway - sl@0: // the stop / error will be generated elsewhere sl@0: sl@0: iInputPort->MipWriteData(aFillBufferPtr); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::ThisHwBufferEmptied(CMMFBuffer& /*aEmptyBufferPtr*/) sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::ThisHwBufferEmptied")); sl@0: sl@0: iOutputPort->MopReadData(*iOutputBuffer); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::SetConfig(TTaskConfig& aConfig) sl@0: { sl@0: TInt err = KErrNone; sl@0: // Call to Configure the Codec PU sl@0: TPuTaskConfig config(aConfig); sl@0: err = iInputPort->MipConfigure(config); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: err = iOutputPort->MopConfigure(config); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: // iState = EProcessingUnitConfigured; sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::StopAndDeleteCodec() sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CMdfHwDeviceCodecTestAdapter::DeleteCodec() sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::MipoWriteDataComplete(const MMdfInputPort* aInputPort, sl@0: CMMFBuffer* aBuffer, TInt aErrorCode) sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::MipoWriteDataComplete")); sl@0: sl@0: if (aErrorCode == KErrNone && aInputPort == iInputPort) sl@0: { sl@0: if(aBuffer->LastBuffer()) sl@0: { sl@0: if(iFuncCmd == EDevEncode) sl@0: { sl@0: // we must cancel the PU here if it's an encoder - the decoder sl@0: // will be done elsewhere sl@0: iCodecPU->Stop(); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: iHwDeviceObserver->FillThisHwBuffer(*aBuffer); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: StopHwDevice(aErrorCode); sl@0: } sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::MipoDisconnectTunnelComplete(const MMdfInputPort* aInputPort, sl@0: TInt aErrorCode) sl@0: { sl@0: // The Inputport of the PcmCodecPu will no longer receive data. sl@0: // Set flag to indicate that the sink outputport has been stopped? sl@0: if(aErrorCode == KErrNone) sl@0: { sl@0: if(aInputPort == iInputPort) sl@0: { sl@0: iPCMPuMipoStopCompleted = ETrue; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: iHwDeviceObserver->Error(aErrorCode); sl@0: } sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::MipoRestartTunnelComplete(const MMdfInputPort* /*aInputPort*/, sl@0: TInt /*aErrorCode*/) sl@0: { sl@0: sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::MopoReadDataComplete(const MMdfOutputPort* aOutputPort, sl@0: CMMFBuffer* aBuffer, TInt aErrorCode) sl@0: { sl@0: DEBUG_PRINT(_L("CMdfHwDeviceCodecTestAdapter::MopoReadDataComplete")); sl@0: sl@0: if(aErrorCode == KErrNone && aOutputPort == iOutputPort) sl@0: { sl@0: iHwDeviceObserver->EmptyThisHwBuffer(*aBuffer); sl@0: } sl@0: else sl@0: { sl@0: StopHwDevice(aErrorCode); sl@0: } sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::MopoDisconnectTunnelComplete(const MMdfOutputPort* aOutputPort, sl@0: TInt aErrorCode) sl@0: { sl@0: if(aErrorCode == KErrNone) sl@0: { sl@0: if(aOutputPort == iOutputPort) sl@0: { sl@0: iPCMPuMopoStopCompleted = ETrue; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: iHwDeviceObserver->Error(aErrorCode); sl@0: } sl@0: if(iPCMPuMipoStopCompleted && iPCMPuMopoStopCompleted) sl@0: { sl@0: iState = EProcessingUnitIdle; sl@0: } sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::MopoRestartTunnelComplete(const MMdfOutputPort* /* aOutputPort */, sl@0: TInt /*aErrorCode*/) sl@0: { sl@0: sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::InitializeComplete(const CMdfProcessingUnit* aPu, TInt aErrorCode) sl@0: { sl@0: if(aErrorCode != KErrNone) sl@0: { sl@0: iHwDeviceObserver->Error(aErrorCode); sl@0: return; sl@0: } sl@0: sl@0: if(aPu == iCodecPU) sl@0: { sl@0: iPCMPUCallbackComplete = ETrue; sl@0: } sl@0: sl@0: if(iPCMPUCallbackComplete) sl@0: { sl@0: sl@0: // reset the flags sl@0: iPCMPUCallbackComplete = EFalse; sl@0: sl@0: // PUs initialised OK sl@0: iActiveWait->AsyncStop(); sl@0: sl@0: } sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::ExecuteComplete(const CMdfProcessingUnit* aPu, TInt aErrorCode) sl@0: { sl@0: if(iStopping) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: if (iExecuteError == KErrNone) sl@0: { sl@0: iExecuteError = aErrorCode; sl@0: } sl@0: sl@0: if(aPu == iCodecPU) sl@0: { sl@0: iPCMPUCallbackComplete = ETrue; sl@0: } sl@0: sl@0: if(iExecuteError != KErrNone || (iPCMPUCallbackComplete) ) sl@0: { sl@0: if (iState == EProcessingUnitExecuting) sl@0: { sl@0: // stop the hardware device if we are still executing sl@0: StopHwDevice(iExecuteError); sl@0: iState = EProcessingUnitIdle; sl@0: } sl@0: // reset the flags sl@0: iPCMPUCallbackComplete = EFalse; sl@0: } sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::SetDataTypesL(TFourCC aSrcType, TFourCC aDestType) sl@0: { sl@0: // Find and load an appropriate Codec sl@0: iCodecPU = iPuLoader->LoadProcessingUnitL(*this, aSrcType, aDestType); sl@0: } sl@0: sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::StopHwDevice(TInt error) sl@0: { sl@0: iHwDeviceObserver->Stopped(); sl@0: iHwDeviceObserver->Error(error); sl@0: } sl@0: sl@0: void CMdfHwDeviceCodecTestAdapter::GetState(THwDevAdapterState& aState) const sl@0: { sl@0: aState = iState; sl@0: }