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