First public contribution.
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "HwDeviceAdapter/mdfhwdeviceadapter.h"
17 #include <mdf/codecapiuids.hrh>
18 #include <mdf/mdfpuconfig.h>
19 #include <mmf/server/devsoundstandardcustominterfaces.h>
21 // Interface UID for the Sink Processing Unit
22 const TUid KUidSourceSinkPu = {0x102730BB};
23 const TInt KZerothPort = 0;
26 The destructor. Unloads the Processing Units, deletes the
27 Processing Unit Loader and frees any owned buffers.
28 @see CMMFHwDevice::~CMMFHwDevice()
30 CMdfHwDeviceAdapter::~CMdfHwDeviceAdapter()
36 iPuLoader->UnloadProcessingUnit(iCodecPU);
40 iPuLoader->UnloadProcessingUnit(iAudioDevicePU);
47 REComSession::DestroyedImplementation(iPuLoaderDtorKey);
51 Creates a new CMdfHwDeviceAdapter object. The Processing Unit Loader plugin
52 is also loaded, and so the CMdfHwDeviceAdapter state is set to EProcessingUnitLoaderLoaded.
53 Will leave with KErrNotFound if it, or the Processing Unit Loader plugin is not found.
54 @see THwDevAdapterState
56 CMdfHwDeviceAdapter* CMdfHwDeviceAdapter::NewL()
58 CMdfHwDeviceAdapter* self = new (ELeave) CMdfHwDeviceAdapter;
59 CleanupStack::PushL (self);
61 CleanupStack::Pop(self);
68 CMdfHwDeviceAdapter::CMdfHwDeviceAdapter()
73 Loads the Processing Unit Loader plugin.
75 void CMdfHwDeviceAdapter::ConstructL()
77 // Load the PU Loader plugin
78 iPuLoader = static_cast<CMdfPuLoader*>
79 (REComSession::CreateImplementationL(TUid::Uid(KUidPuLoaderImplementation), iPuLoaderDtorKey));
80 iActiveWait = new (ELeave) CActiveSchedulerWait;
81 iState = EProcessingUnitLoaderLoaded;
85 @see CMMFHwDevice::Start()
88 TInt CMdfHwDeviceAdapter::Start(TDeviceFunc aFuncCmd, TDeviceFlow /*aFlowCmd*/)
90 if (!((aFuncCmd == EDevEncode)|(aFuncCmd == EDevDecode)|(aFuncCmd == EDevNullFunc)))
112 // nothing at the moment, so fall through
117 err = KErrNotSupported;
127 Initialises the encode operation, and set the state of the CMdfHwDeviceAdapter
128 to EProcessingUnitInitializing.
129 @return An error code indicating if the function call was successful.
130 KErrNone on success, otherwise another of the system-wide error codes.
132 TInt CMdfHwDeviceAdapter::InitializeEncode()
134 ASSERT(iCodecOutputPort && iSourceOutputPort);
135 // Create input buffer that passes data from Source -> Codec PU
136 TRAPD(err, iInputBuffer = CMMFDescriptorBuffer::NewL(iSourceOutputPort->MopBufferSize()));
142 // Create output buffer that passes decoded data from Codec PU -> Out to file
143 TRAP(err, iOutputBuffer = CMMFDescriptorBuffer::NewL(iCodecOutputPort->MopBufferSize()));
149 err = iSourceOutputPort->MopUseBuffer(*iInputBuffer);
154 err = iCodecInputPort->MipUseBuffer(*iInputBuffer);
159 err = iCodecOutputPort->MopUseBuffer(*iOutputBuffer);
165 // async calls, that callback to InitializeComplete()
166 iCodecPU->Initialize();
167 iAudioDevicePU->Initialize();
168 if (iState == EProcessingUnitLoaded)
170 // only wait for the callbacks if we haven't already received them
171 iState = EProcessingUnitInitializing;
172 iActiveWait->Start();
178 Starts the encode operation, providing that the intial state of the
179 CMdfHwDeviceAdapter is EProcessingUnitLoaded.
180 @return An error code indicating if the function call was successful.
181 KErrNone on success, otherwise another of the system-wide error codes.
183 TInt CMdfHwDeviceAdapter::StartEncode()
186 if (iState == EProcessingUnitLoaded)
188 err = InitializeEncode();
194 if (iState == EProcessingUnitPaused)
196 // Ensure that the LastBuffer flags are reset.
197 iInputBuffer->SetLastBuffer(EFalse);
198 iOutputBuffer->SetLastBuffer(EFalse);
201 return StartExecuting();
205 Starts the execution of the encode or decode operation, and sets the state
206 of the CMdfHwDeviceAdapter to EProcessingUnitExecuting.
207 @return An error code indicating if the function call was successful.
208 KErrNone on success, otherwise another of the system-wide error codes.
210 TInt CMdfHwDeviceAdapter::StartExecuting()
213 if(iFuncCmd == EDevDecode)
215 iCodecOutputPort->MopReadData(*iOutputBuffer);
216 err = iHwDeviceObserver->FillThisHwBuffer(*iInputBuffer);
224 iSourceOutputPort->MopReadData(*iInputBuffer);
225 iCodecOutputPort->MopReadData(*iOutputBuffer);
228 iState = EProcessingUnitExecuting;
231 iAudioDevicePU->Execute();
237 Initialises the decode operation, and set the state of the CMdfHwDeviceAdapter
238 to EProcessingUnitInitializing.
239 @return An error code indicating if the function call was successful.
240 KErrNone on success, otherwise another of the system-wide error codes.
242 TInt CMdfHwDeviceAdapter::InitializeDecode()
244 ASSERT(iCodecOutputPort && iSinkInputPort);
246 TRAPD(err, iInputBuffer = CMMFDescriptorBuffer::NewL(iCodecInputPort->MipBufferSize()));
252 iCodecInputPort->MipUseBuffer(*iInputBuffer);
253 TRAP(err, iOutputBuffer = CMMFDescriptorBuffer::NewL(iCodecOutputPort->MopBufferSize()));
259 // Try to set up a tunnelbetween the output port of the PCM Pu
260 // and the input port of the Sink Pu
261 if (iPuLoader->TunnelSetup(*iCodecOutputPort, *iSinkInputPort) != KErrNone)
263 iSinkInputPort->MipUseBuffer(*iOutputBuffer);
265 iCodecOutputPort->MopUseBuffer(*iOutputBuffer);
267 // async calls, that callback to InitializeComplete()
268 iCodecPU->Initialize();
269 iAudioDevicePU->Initialize();
270 iState = EProcessingUnitInitializing;
271 iActiveWait->Start();
276 Starts the decode operation, providing that the intial state of the
277 CMdfHwDeviceAdapter is EProcessingUnitLoaded.
278 @return An error code indicating if the function call was successful.
279 KErrNone on success, otherwise another of the system-wide error codes.
281 TInt CMdfHwDeviceAdapter::StartDecode()
284 if (iState == EProcessingUnitLoaded)
286 err = InitializeDecode();
292 if (iState == EProcessingUnitIdle)
294 // Ensure that the LastBuffer flags are reset.
295 iInputBuffer->SetLastBuffer(EFalse);
296 iOutputBuffer->SetLastBuffer(EFalse);
298 return StartExecuting();
302 @see CMMFHwDevice::Stop()
304 TInt CMdfHwDeviceAdapter::Stop()
306 if(iState == EProcessingUnitExecuting || iState == EProcessingUnitPaused)
308 iStopping = ETrue; // is used as a guard in ExecuteComplete
311 iAudioDevicePU->Stop();
318 iPCMPUCallbackComplete = EFalse;
319 iSourceSinkPUCallbackComplete = EFalse;
321 iState = EProcessingUnitIdle;
328 @see CMMFHwDevice::Pause()
330 TInt CMdfHwDeviceAdapter::Pause()
333 if(iState != EProcessingUnitPaused)
337 err = iAudioDevicePU->Pause();
339 iState = EProcessingUnitPaused;
345 @see CMMFHwDevice::Init()
347 TInt CMdfHwDeviceAdapter::Init(THwDeviceInitParams& aDevInfo)
351 return KErrNotSupported;
354 // Not currently using any other members of aDevInfo, except the Observer
356 if(!aDevInfo.iHwDeviceObserver)
360 iHwDeviceObserver = aDevInfo.iHwDeviceObserver;
362 RPointerArray<MMdfInputPort> inputPorts;
363 // Get ports and set observers
364 TInt err = iCodecPU->GetInputPorts(inputPorts);
365 if (err == KErrNone && inputPorts.Count() > 0)
367 iCodecInputPort = inputPorts[KZerothPort];
368 iCodecInputPort->MipSetObserver(*this);
375 if (!iCodecInputPort)
380 RPointerArray<MMdfOutputPort> outputPorts;
381 // Get ports and set observers
382 err = iCodecPU->GetOutputPorts(outputPorts);
383 if (err == KErrNone && outputPorts.Count() > 0)
385 iCodecOutputPort = outputPorts[KZerothPort];
386 iCodecOutputPort->MopSetObserver(*this);
393 if (!iCodecOutputPort)
398 // Load SourceSink Pu
399 TRAP(err, iAudioDevicePU = iPuLoader->LoadProcessingUnitL(*this, KUidSourceSinkPu));
405 err = iAudioDevicePU->GetInputPorts(inputPorts);
406 if (err == KErrNone && inputPorts.Count() > 0)
408 iSinkInputPort = inputPorts[KZerothPort];
409 iSinkInputPort->MipSetObserver(*this);
422 err = iAudioDevicePU->GetOutputPorts(outputPorts);
423 if (err == KErrNone && outputPorts.Count() > 0)
425 iSourceOutputPort = outputPorts[KZerothPort];
426 iSourceOutputPort->MopSetObserver(*this);
433 if (!iCodecOutputPort)
438 iState = EProcessingUnitLoaded;
443 @see CMMFHwDevice::CustomInterface()
445 TAny* CMdfHwDeviceAdapter::CustomInterface(TUid aInterfaceId)
447 if (aInterfaceId == KUidHwDeviceSetupInterface)
449 MMdfHwDeviceSetup* hwDeviceSetup = this;
450 return hwDeviceSetup;
452 else if (aInterfaceId.iUid == KMmfPlaySettingsCustomInterface)
454 return iSinkInputPort->MipCustomInterface(aInterfaceId);
456 else if (aInterfaceId.iUid == KMmfRecordSettingsCustomInterface)
458 return iSourceOutputPort->MopCustomInterface(aInterfaceId);
460 else if (aInterfaceId == KUidCustomInterfaceDevSoundBitRate)
462 return iCodecPU->CustomInterface(aInterfaceId);
471 @see CMMFHwDevice::ThisHwBufferFilled()
473 TInt CMdfHwDeviceAdapter::ThisHwBufferFilled(CMMFBuffer& aFillBufferPtr)
475 aFillBufferPtr.SetStatus(EFull);
476 iCodecInputPort->MipWriteData(aFillBufferPtr);
481 @see CMMFHwDevice::ThisHwBufferEmptied()
483 TInt CMdfHwDeviceAdapter::ThisHwBufferEmptied(CMMFBuffer& /*aEmptyBufferPtr*/)
485 if (iOutputBuffer->LastBuffer())
487 CMMFDataBuffer* buffer = static_cast <CMMFDataBuffer*> (iOutputBuffer);
488 buffer->Data().SetLength(0);
489 iHwDeviceObserver->EmptyThisHwBuffer(*iOutputBuffer);
493 iCodecOutputPort->MopReadData(*iOutputBuffer);
499 @see CMMFHwDevice::SetConfig()
501 TInt CMdfHwDeviceAdapter::SetConfig(TTaskConfig& aConfig)
504 // Call to Configure the Codec PU
505 TPuTaskConfig config(aConfig);
506 err = iCodecInputPort->MipConfigure(config);
511 err = iCodecOutputPort->MopConfigure(config);
517 // configure the audio device
518 err = iSinkInputPort->MipConfigure(config);
523 err = iSourceOutputPort->MopConfigure(config);
533 @see CMMFHwDevice::StopAndDeleteCodec()
535 TInt CMdfHwDeviceAdapter::StopAndDeleteCodec()
537 TInt stopError = Stop();
538 TInt deleteError = DeleteCodec();
540 if (stopError != KErrNone)
551 Unloads all Processing Units, and deletes any locally owned buffers.
552 State is set to EProcessingUnitLoaderLoaded.
554 @see CMMFHwDevice::DeleteCodec()
556 TInt CMdfHwDeviceAdapter::DeleteCodec()
561 iPuLoader->UnloadProcessingUnit(iCodecPU);
565 iPuLoader->UnloadProcessingUnit(iAudioDevicePU);
568 // CMdfHwDeviceAdapter does not own the I/O ports, which
569 // have been deleted at this point by UnloadProcessingUnit()
570 iCodecInputPort = NULL;
571 iCodecOutputPort = NULL;
572 iSinkInputPort = NULL;
573 iSourceOutputPort = NULL;
577 delete iOutputBuffer;
578 iOutputBuffer = NULL;
580 iState = EProcessingUnitLoaderLoaded;
586 @see MMdfInputPortObserver::MipoWriteDataComplete()
588 void CMdfHwDeviceAdapter::MipoWriteDataComplete(const MMdfInputPort* aInputPort,
589 CMMFBuffer* aBuffer, TInt aErrorCode)
591 if(aErrorCode != KErrNone)
593 StopHwDevice(aErrorCode);
601 if(aInputPort == iCodecInputPort)
603 if(aBuffer->LastBuffer())
609 // if not the last buffer, then pass buffer back to source to get more data
610 iSourceOutputPort->MopReadData(*iInputBuffer);
617 if(aInputPort == iCodecInputPort)
619 if (!aBuffer->LastBuffer())
622 // if the PU is idle (having been Stopped) then
623 // FillThisHwBuffer will cause a kern-exec,
624 // as the DevSoundSession no longer has a buffer
625 if(iState == EProcessingUnitExecuting)
627 TInt err = iHwDeviceObserver->FillThisHwBuffer(*aBuffer);
635 else // aInputPort == iSinkInputPort
637 if (!aBuffer->LastBuffer())
639 if(iSinkInputPort->MipIsTunnelled())
641 // This callback shouldn't occur since it should be tunnelled with the sink input port
642 StopHwDevice(KErrArgument);
646 iCodecOutputPort->MopReadData(*iOutputBuffer);
653 // nothing at the moment, so fall through
655 StopHwDevice(KErrNotSupported);
661 @see MMdfInputPortObserver::MipoDisconnectTunnelComplete()
663 void CMdfHwDeviceAdapter::MipoDisconnectTunnelComplete(const MMdfInputPort* aInputPort,
666 // The Inputport of the PcmCodecPu will no longer receive data.
667 if(aErrorCode == KErrNone)
669 if(aInputPort == iCodecInputPort)
671 iPCMPuMipoStopCompleted = ETrue;
673 else if(aInputPort == iSinkInputPort)
675 // This shouldn't be called!
676 iHwDeviceObserver->Error(KErrNotFound);
681 iHwDeviceObserver->Error(aErrorCode);
686 @see MMdfInputPortObserver::MipoRestartTunnelComplete()
688 void CMdfHwDeviceAdapter::MipoRestartTunnelComplete(const MMdfInputPort* /*aInputPort*/,
695 @see MMdfOutputPortObserver::MopoReadDataComplete()
697 void CMdfHwDeviceAdapter::MopoReadDataComplete(const MMdfOutputPort* aOutputPort,
698 CMMFBuffer* aBuffer, TInt aErrorCode)
700 if(aErrorCode != KErrNone)
702 StopHwDevice(aErrorCode);
710 if(aOutputPort == iSourceOutputPort)
712 iCodecInputPort->MipWriteData(*aBuffer);
714 else // aPu == iCodecPU
716 TInt err = iHwDeviceObserver->EmptyThisHwBuffer(*aBuffer);
726 if(aOutputPort == iCodecOutputPort)
728 if(iCodecOutputPort->MopIsTunnelled())
730 // This callback shouldn't occur since it should be tunnelled with the sink input port
731 StopHwDevice(KErrArgument);
735 iSinkInputPort->MipWriteData(*aBuffer);
741 // nothing at the moment, so fall through
743 StopHwDevice(KErrNotSupported);
749 @see MMdfOutputPortObserver::MopoDisconnectTunnelComplete()
751 void CMdfHwDeviceAdapter::MopoDisconnectTunnelComplete(const MMdfOutputPort* aOutputPort,
756 iHwDeviceObserver->Error(KErrArgument);
760 // The last buffer has been set, and called back to MopoReadDataComplete
761 if(aErrorCode != KErrNone)
763 iHwDeviceObserver->Error(aErrorCode);
767 if(aOutputPort == iCodecOutputPort)
769 iPCMPuMopoStopCompleted = ETrue;
771 else if(aOutputPort == iSourceOutputPort)
773 iSourceSinkPuMopoStopCompleted = ETrue;
777 iHwDeviceObserver->Error(KErrArgument);
781 if(iPCMPuMipoStopCompleted && iPCMPuMopoStopCompleted && iSourceSinkPuMopoStopCompleted)
783 iHwDeviceObserver->Error(KErrNone);
784 iState = EProcessingUnitIdle;
789 @see MMdfOutputPortObserver::MopoRestartTunnelComplete()
791 void CMdfHwDeviceAdapter::MopoRestartTunnelComplete(const MMdfOutputPort* /*aOutputPort*/,
798 @see MMdfProcessingUnitObserver::InitializeComplete()
800 void CMdfHwDeviceAdapter::InitializeComplete(const CMdfProcessingUnit* aPu, TInt aErrorCode)
802 iInitError = aErrorCode;
803 if(aErrorCode != KErrNone)
805 // stop waiting on the active scheduler if we were doing so
806 if (iState == EProcessingUnitInitializing)
808 // change state back to processing unit loaded
809 iState = EProcessingUnitLoaded;
810 iActiveWait->AsyncStop();
817 iPCMPUCallbackComplete = ETrue;
819 else if(aPu == iAudioDevicePU)
821 iSourceSinkPUCallbackComplete = ETrue;
824 if(iPCMPUCallbackComplete && iSourceSinkPUCallbackComplete)
827 iPCMPUCallbackComplete = EFalse;
828 iSourceSinkPUCallbackComplete = EFalse;
830 // Both PUs initialised OK
831 if (iState == EProcessingUnitInitializing)
833 iActiveWait->AsyncStop();
835 iState = EProcessingUnitIdle;
840 @see MMdfProcessingUnitObserver::ExecuteComplete()
842 void CMdfHwDeviceAdapter::ExecuteComplete(const CMdfProcessingUnit* aPu, TInt aErrorCode)
849 if (iExecuteError == KErrNone)
851 iExecuteError = aErrorCode;
856 iPCMPUCallbackComplete = ETrue;
858 else if(aPu == iAudioDevicePU)
860 iSourceSinkPUCallbackComplete = ETrue;
863 if(iExecuteError != KErrNone || (iPCMPUCallbackComplete && iSourceSinkPUCallbackComplete))
865 if (iState == EProcessingUnitExecuting)
867 // stop the hardware device if we are still executing
868 StopHwDevice(iExecuteError);
869 iState = EProcessingUnitIdle;
872 iPCMPUCallbackComplete = EFalse;
873 iSourceSinkPUCallbackComplete = EFalse;
878 @see MMdfHwDeviceSetup::::SetDataTypesL()
880 void CMdfHwDeviceAdapter::SetDataTypesL(TFourCC aSrcType, TFourCC aDestType)
882 // Find and load an appropriate Codec
883 iCodecPU = iPuLoader->LoadProcessingUnitL(*this, aSrcType, aDestType);
887 Called to indicate that the Hardware Device has been stopped, leading
888 to callbacks to the observer.
889 @see MMMFHwDeviceObserver::Stopped()
890 @see MMMFHwDeviceObserver::Error()
892 void CMdfHwDeviceAdapter::StopHwDevice(TInt error)
894 iHwDeviceObserver->Stopped();
895 iHwDeviceObserver->Error(error);
899 Returns the state of the Hardware Device Adapter object.
901 void CMdfHwDeviceAdapter::GetState(THwDevAdapterState& aState) const