--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmdevicefw/mdf/src/video/decoderadapter/mdfvideodecodehwdeviceadapter.cpp Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,1402 @@
+// 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:
+//
+
+#include <mmf/devvideo/devvideopuconfig.h>
+#include "mdfvideodecodehwdeviceadapter.h"
+#include "displaymodeutils.h"
+
+#if defined (SYMBIAN_MDFVIDEODECODERHWDEVICE_DEBUG)
+#define DEBUG_PRINT RDebug::Print
+#else
+#define DEBUG_PRINT
+#endif // defined (SYMBIAN_MDFVIDEODECODERHWDEVICE_DEBUG)
+
+const TInt KOutputFormatsArraySize = 3;
+const TInt KTenFPS = 10;
+const TInt KOneSecond = 1000000;
+const TInt KInputBufferSize = 8192;
+
+_LIT(KDevVideoHwDeviceDecoderPanicCategory, "DevVideoHwDeviceDecoder");
+void DevVideoHwDeviceDecoderPanic(TInt aReason)
+ {
+ User::Panic(KDevVideoHwDeviceDecoderPanicCategory, aReason);
+ }
+
+/*
+ Constructs a new instance of CMdfVideoDecodeHwDeviceAdapter.
+ @return "CMdfVideoDecodeHwDeviceAdapter*"
+ A pointer to the newly constructed HwDevice
+ */
+CMdfVideoDecodeHwDeviceAdapter* CMdfVideoDecodeHwDeviceAdapter::NewL()
+ {
+ CMdfVideoDecodeHwDeviceAdapter* self = new (ELeave) CMdfVideoDecodeHwDeviceAdapter;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/*
+ Default constructor
+*/
+CMdfVideoDecodeHwDeviceAdapter::CMdfVideoDecodeHwDeviceAdapter()
+ {
+ }
+
+void CMdfVideoDecodeHwDeviceAdapter::ConstructL()
+ {
+ // system clock without HAL
+ TInt64 tt64;
+ TTime ttime;
+ ttime.HomeTime();
+ tt64 = ttime.Int64();
+ iSystemClock = tt64;
+
+ // reset picture format
+ iFormat.iDataFormat = (TImageDataFormat)0;
+
+ // Load the PU Loader plugin
+ iPuLoader = static_cast<CMdfPuLoader*>
+ (REComSession::CreateImplementationL(TUid::Uid(KUidPuLoaderImplementation), iPuLoaderDtorKey));
+ iState = EProcessingUnitLoaderLoaded;
+ }
+
+/*
+ Default destructor
+*/
+CMdfVideoDecodeHwDeviceAdapter::~CMdfVideoDecodeHwDeviceAdapter()
+ {
+ DEBUG_PRINT(_L("HwDevice: Destroying"));
+ // stop playing if necessary
+ Stop();
+
+ delete iPlayerEngine;
+ delete iScreenDeviceGc;
+
+ // destroy the buffer manager
+ delete iBufferManager;
+ // destroy the picture header
+ delete iPictureHeader;
+
+ // Unload the DecoderPU
+ if (iDecoderPU)
+ {
+ iPuLoader->UnloadProcessingUnit(iDecoderPU);
+ }
+
+ delete iPuLoader;
+ delete iPuData;
+ delete iManufacturer;
+ REComSession::DestroyedImplementation(iPuLoaderDtorKey);
+
+ iInputVidFormats.ResetAndDestroy(); // will destroy contents as well
+ iOutputVidFormats.Close();
+ iPictureRates.Close();
+
+ DEBUG_PRINT(_L("HwDevice: Destroyed"));
+ }
+
+/*
+ @see CMMFVideoHwDevice::CustomInterface()
+ */
+TAny* CMdfVideoDecodeHwDeviceAdapter::CustomInterface(TUid aInterface)
+ {
+ if (aInterface.iUid == KUidDevVideoHwDeviceAdapterSetup)
+ {
+ return static_cast<MDevVideoHwDeviceAdapterSetup*>(this);
+ }
+ return NULL;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::PostProcessorInfoLC()
+ */
+CPostProcessorInfo* CMdfVideoDecodeHwDeviceAdapter::PostProcessorInfoLC()
+ {
+ // post processor info will be obtained from the post processor plugin, if any
+ return NULL;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::GetOutputFormatListL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetOutputFormatListL(RArray<TUncompressedVideoFormat>& aFormats)
+ {
+ // TUncompressedVideoFormats is a union - therefore using hard initialisation
+ iOutputVidFormats.Reset();
+ TUncompressedVideoFormat outputFormats[KOutputFormatsArraySize];
+
+ outputFormats[0].iDataFormat = ERgbRawData;
+ outputFormats[0].iRgbFormat = ERgb16bit565;
+ iOutputVidFormats.AppendL(outputFormats[0]);
+ aFormats.AppendL(outputFormats[0]);
+
+ outputFormats[1].iDataFormat = ERgbFbsBitmap;
+ outputFormats[1].iRgbFormat = EFbsBitmapColor16M;
+ iOutputVidFormats.AppendL(outputFormats[1]);
+ aFormats.AppendL(outputFormats[1]);
+
+ outputFormats[2].iDataFormat = EYuvRawData;
+ iOutputVidFormats.AppendL(outputFormats[2]);
+ aFormats.AppendL(outputFormats[2]);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetOutputFormatL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetOutputFormatL(const TUncompressedVideoFormat& aFormat)
+ {
+ // check size and format are supported
+ if(iOutputVidFormats.Count() == 0)
+ {
+ User::Leave(KErrNotReady);
+ }
+ if(!iOutputVidFormats.Find(aFormat))
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ iFormat = aFormat;
+ TDevVideoPlayPuConfig decodeConfig;
+ decodeConfig.iImageFormat = iFormat;
+ decodeConfig.iInputBufferSize = KInputBufferSize;
+ TPuConfigVideoPlayback puConfig(decodeConfig);
+
+ User::LeaveIfError(iDecoderPU->Configure(puConfig));
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetClockSource()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetClockSource(MMMFClockSource* aClock)
+ {
+ iClockSource = aClock;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetVideoDestScreenL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetVideoDestScreenL(TBool aScreen)
+ {
+ if(aScreen)
+ {
+ // NB we expect the output format to have been set before this is called
+ if(!iFormat.iDataFormat)
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ // we support only bitmaps for DSA, not raw data
+ if(iFormat.iDataFormat != ERgbFbsBitmap)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ // ETrue = use DSA
+ iDSAEnabled = aScreen;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetPostProcessTypesL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetPostProcessTypesL(TUint32 /* aPostProcCombination */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetInputCropOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetInputCropOptionsL(const TRect& /* aRect */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetYuvToRgbOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetYuvToRgbOptionsL(const TYuvToRgbOptions& /* aOptions */, const TYuvFormat& /* aYuvFormat */, TRgbFormat /* aRgbFormat */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetYuvToRgbOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetYuvToRgbOptionsL(const TYuvToRgbOptions& /* aOptions */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetRotateOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetRotateOptionsL(TRotationType /* aRotationType */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetScaleOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetScaleOptionsL(const TSize& /* aTargetSize */, TBool /* aAntiAliasFiltering */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetOutputCropOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetOutputCropOptionsL(const TRect& /* aRect */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetPostProcSpecificOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetPostProcSpecificOptionsL(const TDesC8& /* aOptions */)
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::Initialize()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::Initialize()
+ {
+ __ASSERT_ALWAYS(iProxy, DevVideoHwDeviceDecoderPanic(0));
+
+ TRAPD(err, InitializeL());
+ if(err == KErrNone && !iPUInitialized)
+ {
+ err = KErrNotSupported;
+ }
+ iProxy->MdvppInitializeComplete(this, err);
+ }
+
+// private method : body of Initialize()
+void CMdfVideoDecodeHwDeviceAdapter::InitializeL()
+ {
+ // pre-check format
+ switch(iFormat.iDataFormat)
+ {
+ case 0:
+ User::Leave(KErrNotReady);
+ break;
+ case ERgbRawData:
+ case ERgbFbsBitmap:
+ case EYuvRawData:
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ // create and initialise the buffer manager
+ iBufferManager = CMdfVideoDecoderBufferManager::NewL();
+
+ iBufferManager->Init(iFormat);
+ iBufferManager->SetFrameSize(iFrameSize);
+
+ DEBUG_PRINT(_L("HwDevice: Buffer Manager initialized"));
+
+ // The actual frame rate will come from the VOL headers.
+ iFrameRate = KTenFPS;
+
+ // reset the player flags
+ iPrimed = EFalse;
+ iInputBufferWaiting = EFalse;
+ iInputEnd = EFalse;
+
+ // create the player engine
+ iPlayerEngine = CMdfVideoPlayerEngine::NewL(*this);
+
+ RPointerArray<MMdfInputPort> inputPorts;
+ // Get ports and set observers
+ User::LeaveIfError(iDecoderPU->GetInputPorts(inputPorts));
+ if (inputPorts.Count()==0)
+ {
+ inputPorts.Close();
+ User::Leave(KErrNotFound);
+ }
+ iDecoderPUInputPort = inputPorts[0];
+ iDecoderPUInputPort->MipSetObserver(*this);
+ inputPorts.Close();
+
+ RPointerArray<MMdfOutputPort> outputPorts;
+ User::LeaveIfError(iDecoderPU->GetOutputPorts(outputPorts));
+ if (outputPorts.Count()==0)
+ {
+ outputPorts.Close();
+ User::Leave(KErrNotFound);
+ }
+ iDecoderPUOutputPort = outputPorts[0];
+ iDecoderPUOutputPort->MopSetObserver(*this);
+ outputPorts.Close();
+
+ iState = EProcessingUnitLoaded;
+
+ DEBUG_PRINT(_L("HwDevice: Decoder Processing Unit Loaded"));
+
+ // Create the buffers that are associated with the input and output ports
+ iInputBuffer = &iBufferManager->CreateDataBufferL(iDecoderPUInputPort->MipBufferSize());
+ iPUInputBuffer = *iInputBuffer;
+ User::LeaveIfError(iDecoderPUInputPort->MipUseBuffer(*iPUInputBuffer));
+
+ CVideoFrameBuffer& frameBuffer = iBufferManager->CreateFrameBufferL(TMMFDisplayModeUtils::DisplayMode(iFormat.iRgbFormat));
+ User::LeaveIfError(iDecoderPUOutputPort->MopUseBuffer(frameBuffer));
+
+ // VD: should not move the set up of the state after sending the Initialize() calls???
+ iState = EProcessingUnitInitializing;
+
+ // async call, that calls back to InitializeComplete()
+ iDecoderPU->Initialize();
+
+ DEBUG_PRINT(_L("HwDevice: Initialized OK"));
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::StartDirectScreenAccessL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::StartDirectScreenAccessL(const TRect& aVideoRect, CFbsScreenDevice& aScreenDevice, const TRegion& aClipRegion)
+ {
+ // ensure SetVideoDestScreenL() has been called
+ if(!iDSAEnabled)
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ DEBUG_PRINT(_L("HwDevice: Starting DSA"));
+
+ iDSAStarted = ETrue;
+
+ // the CDirectScreenAccess must be created by the client app.
+ // the CFbsScreenDevice (only) is passed across...
+ // we need to blit the bitmap into it, i.e. we need to create our own GC
+ if(!iScreenDevice)
+ {
+ User::LeaveIfError(aScreenDevice.CreateContext(iScreenDeviceGc));
+ iScreenDevice = &aScreenDevice;
+ iScreenDeviceRect = aVideoRect;
+ iScreenDeviceGc->SetClippingRegion(aClipRegion);
+ }
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetScreenClipRegion()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetScreenClipRegion(const TRegion& aRegion)
+ {
+ __ASSERT_ALWAYS(iScreenDeviceGc, DevVideoHwDeviceDecoderPanic(0));
+
+ iScreenDeviceGc->SetClippingRegion(aRegion);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetPauseOnClipFail()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetPauseOnClipFail(TBool /* aPause */)
+ {
+ // not implemented - will pause by default
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::AbortDirectScreenAccess()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::AbortDirectScreenAccess()
+ {
+ DEBUG_PRINT(_L("HwDevice: Stopping DSA"));
+ iDSAStarted = EFalse;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::IsPlaying()
+ */
+TBool CMdfVideoDecodeHwDeviceAdapter::IsPlaying()
+ {
+ return (iState == EProcessingUnitExecuting ? ETrue : EFalse);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::Redraw()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::Redraw()
+ {
+ if(iDSAStarted)
+ {
+ DisplayLastFrameDirect();
+ }
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::Start()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::Start()
+ {
+ __ASSERT_ALWAYS(iPlayerEngine, DevVideoHwDeviceDecoderPanic(0));
+ __ASSERT_ALWAYS(iDecoderPU, DevVideoHwDeviceDecoderPanic(0));
+
+ if(iState != EProcessingUnitExecuting)
+ {
+ CVideoFrameBuffer* frameBuffer = NULL;
+ TRAPD(err, frameBuffer = &iBufferManager->GetEmptyFrameBufferL(ETrue));
+ if (err != KErrNone)
+ {
+ iProxy->MdvppFatalError(this, err);
+ return;
+ }
+
+ iDecoderPUOutputPort->MopReadData(*frameBuffer);
+
+ iDecoderPU->Execute();
+ TProcessingUnitState puState = iDecoderPU->State();
+ if(puState == EProcessingUnitInvalid)
+ {
+ return;
+ }
+ iState = EProcessingUnitExecuting;
+
+ // if we are using raw decoding, then play as fast as we can,
+ // otherwise use the actual frame rate
+ TInt playerFrameRate;
+ if(iSynchronize)
+ {
+ playerFrameRate = TInt(iFrameRate);
+ }
+ else
+ {
+ playerFrameRate = CMdfVideoPlayerEngine::KUnsynchronized;
+ }
+ TRAP(err, iPlayerEngine->StartL(playerFrameRate));
+ if(err != KErrNone)
+ {
+ // the player failed to start. this is a fatal error
+ iProxy->MdvppFatalError(this, err);
+ }
+ else
+ {
+ iProxy->MdvppNewBuffers();
+ }
+ }
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::Stop()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::Stop()
+ {
+ if(iState == EProcessingUnitExecuting)
+ {
+ iPlayerEngine->Stop();
+ iDecoderPU->Stop();
+ iState = EProcessingUnitIdle;
+ }
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::Pause()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::Pause()
+ {
+ Stop();
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::Resume()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::Resume()
+ {
+ Start();
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetPosition()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetPosition(const TTimeIntervalMicroSeconds& aPlaybackPosition)
+ {
+ TPuConfigTimestamp timeStamp(aPlaybackPosition);
+ // we have no way report a failure here, and it is not a fatal error so any error is ignored
+ iDecoderPU->Configure(timeStamp);
+ }
+/*
+ @see CMMFVideoPlayHwDevice::FreezePicture()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::FreezePicture(const TTimeIntervalMicroSeconds& /* aTimestamp */)
+ {
+ // not supported; we have no presentation timestamps
+ // however should not cause a fatal error
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::ReleaseFreeze()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::ReleaseFreeze(const TTimeIntervalMicroSeconds& /* aTimestamp */)
+ {
+ // not supported; we have no presentation timestamps
+ // however should not cause a fatal error
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::PlaybackPosition()
+ */
+TTimeIntervalMicroSeconds CMdfVideoDecodeHwDeviceAdapter::PlaybackPosition()
+ {
+ if(iFrameRate == 0.0)
+ {
+ return 0;
+ }
+ // this is the total number of pictures displayed or discarded
+ // NB it is NOT equivalent to the number of pictures decoded, as the
+ // player may be running a few frames behind the decoder
+ return ((iPictureCounters.iPicturesDisplayed + iPictureCounters.iPicturesSkipped) * (KOneSecond / (TInt)iFrameRate));
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::PictureBufferBytes()
+ */
+TUint CMdfVideoDecodeHwDeviceAdapter::PictureBufferBytes()
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ return (iBufferManager->FrameBufferSize() * iBufferManager->MaxFrameBuffers());
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::GetPictureCounters()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetPictureCounters(CMMFDevVideoPlay::TPictureCounters& aCounters)
+ {
+ aCounters = iPictureCounters;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::SetComplexityLevel()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetComplexityLevel(TUint /* aLevel */)
+ {
+ // separate complexity levels are not available; ignored
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::NumComplexityLevels()
+ */
+TUint CMdfVideoDecodeHwDeviceAdapter::NumComplexityLevels()
+ {
+ // separate complexity levels are not available; return 1
+ return 1;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::GetComplexityLevelInfo()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetComplexityLevelInfo(TUint aLevel, CMMFDevVideoPlay::TComplexityLevelInfo& aInfo)
+ {
+ // ignore call if aLevel is not 0
+ if(aLevel == 0)
+ {
+ aInfo = iComplexityLevelInfo;
+ }
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::ReturnPicture()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::ReturnPicture(TVideoPicture* aPicture)
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ // return the frame buffer that has been emptied
+ TRAPD(err, iBufferManager->ReturnFrameBufferL(*aPicture, CVideoFrameBuffer::EEmptied));
+ if (err == KErrNone)
+ {
+ if (!iLastFrameBufferReceived)
+ {
+
+ // request the next empty frame buffer
+ CVideoFrameBuffer* frameBuffer = NULL;
+ TRAP(err, frameBuffer = &iBufferManager->GetEmptyFrameBufferL(ETrue));
+ if (err == KErrNone)
+ {
+ CMMFBuffer* buffer = *frameBuffer;
+ iDecoderPUOutputPort->MopReadData(*buffer);
+ }
+ }
+ // DoPostPictureNotify() will handle MdvppStreamEnd()
+ }
+ else
+ {
+ iProxy->MdvppFatalError(this, err);
+ }
+ ASSERT(err == KErrNone);
+ DoPostPictureNotify();
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::GetSnapshotL()
+ */
+TBool CMdfVideoDecodeHwDeviceAdapter::GetSnapshotL(TPictureData& /*aPictureData*/, const TUncompressedVideoFormat& /*aFormat*/)
+ {
+ // not supported - no presentation timestamps
+ User::Leave(KErrNotSupported);
+ return EFalse;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::GetTimedSnapshotL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetTimedSnapshotL(TPictureData* /*aPictureData*/, const TUncompressedVideoFormat& /*aFormat*/, const TTimeIntervalMicroSeconds& /*aPresentationTimestamp*/)
+ {
+ // this method should be called on the post processor not on the decoder
+ // ending up here is a programming error and hence a PANIC condition
+ DevVideoHwDeviceDecoderPanic(0);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::GetTimedSnapshotL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetTimedSnapshotL(TPictureData* /*aPictureData*/, const TUncompressedVideoFormat& /*aFormat*/, const TPictureId& /*aPictureId*/)
+ {
+ // this method should be called on the post processor not on the decoder
+ // ending up here is a programming error and hence a PANIC condition
+ DevVideoHwDeviceDecoderPanic(0);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::CancelTimedSnapshot()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::CancelTimedSnapshot()
+ {
+ // this method should be called on the post processor not on the decoder
+ // ending up here is a programming error and hence a PANIC condition
+ DevVideoHwDeviceDecoderPanic(0);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::GetSupportedSnapshotFormatsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetSupportedSnapshotFormatsL(RArray<TUncompressedVideoFormat>& /*aFormats*/)
+ {
+ // this method should be called on the post processor not on the decoder
+ // ending up here is a programming error and hence a PANIC condition
+ DevVideoHwDeviceDecoderPanic(0);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::InputEnd()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::InputEnd()
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ DEBUG_PRINT(_L("HwDevice: Input end"));
+
+ iInputEnd = ETrue;
+
+ // if there isn't an outstanding write to the PU, write
+ // an empty buffer
+ if(!iWriteRequestOutstanding)
+ {
+ SendLastBuffer();
+ }
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::VideoDecoderInfoLC()
+ */
+CVideoDecoderInfo* CMdfVideoDecodeHwDeviceAdapter::VideoDecoderInfoLC()
+ {
+ // this is a complicated structure, ensure all fields are
+ // filled with some valid value
+
+ //if PU is not loaded panic
+ if(iPuData == NULL)
+ {
+ DevVideoHwDeviceDecoderPanic(KErrNotReady);
+ }
+ // supported formats array
+ iInputVidFormats.Reset();
+ CCompressedVideoFormat* vidCV = NULL;
+ vidCV = CCompressedVideoFormat::NewL(iPuData->InputDataType() , KNullDesC8);
+ CleanupStack::PushL(vidCV);
+ iInputVidFormats.AppendL(vidCV);
+ CleanupStack::Pop(vidCV); // CCompressedVideo object is destroyed in destructor
+
+
+ // construct the video decoder info object
+ CVideoDecoderInfo* vInfo = CVideoDecoderInfo::NewL(
+ iPuUid,
+ *iManufacturer,
+ KNullDesC,
+ TVersion(KVideoDecoderInfoVersionMaj, KVideoDecoderInfoVersionMin, KVideoDecoderInfoVersionBuild),
+ iInputVidFormats.Array(),
+ EFalse, // not accelerated
+ ETrue, // supports direct screen access
+ iMaxPictureSize,
+ KMaxTUint32, // max bitrate supported
+ iPuData->MaxPictureRates().Array(),
+ EFalse, // picture loss not supported,
+ EFalse, // slice loss not supported,
+ KVideoDecoderInfoCSInfo,
+ KVideoDecoderInfoISInfo );
+
+ CleanupStack::PushL(vInfo);
+ return vInfo;
+ }
+
+
+/*
+ @see CMMFVideoDecodeHwDevice::GetHeaderInformationL()
+ */
+
+TVideoPictureHeader* CMdfVideoDecodeHwDeviceAdapter::GetHeaderInformationL(TVideoDataUnitType aDataUnitType, TVideoDataUnitEncapsulation aEncapsulation, TVideoInputBuffer* aDataUnit)
+ {
+ // NB this may be called EITHER before OR after the decoder is initialized.
+ // ensure at least that SetOutputFormatL() has been called before this,
+ // as the decoder requires it to be able to initialize.
+
+ __ASSERT_ALWAYS(iFormat.iDataFormat, DevVideoHwDeviceDecoderPanic(0));
+
+ TDevVideoHeaderPuConfig header;
+ header.iDataUnitType = aDataUnitType;
+ header.iDataUnitEncapsulation = aEncapsulation;
+ header.iHeaderData.Set(aDataUnit->iData.Ptr(),aDataUnit->iData.Size());
+
+ TPuConfigVideoHeader headerConfig(header);
+
+ // Configure the decoder with the Header Information
+ User::LeaveIfError(iDecoderPU->Configure(headerConfig));
+
+ // retrieve the picture information from the config structure
+
+ TPuConfigVideoPictureHeader pict;
+ User::LeaveIfError(iDecoderPU->GetConfig(pict));
+
+ delete iPictureHeader;
+ iPictureHeader = NULL;
+ // Create a new header from the returned data
+ iPictureHeader = new (ELeave)TVideoPictureHeader(
+ *TPuConfigVideoPictureHeader::GetStructure(pict));
+ iFrameSize = iPictureHeader->iSizeInMemory;
+ return iPictureHeader;
+
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::ConfigureDecoderL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::ConfigureDecoderL(const TVideoPictureHeader& /* aVideoPictureHeader */)
+ {
+ // there is nothing configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::ReturnHeader()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::ReturnHeader(TVideoPictureHeader* aHeader)
+ {
+ if(aHeader == iPictureHeader) // only free our created header
+ {
+ delete iPictureHeader;
+ iPictureHeader = NULL;
+ }
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::SetInputFormatL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetInputFormatL(const CCompressedVideoFormat& aFormat, TVideoDataUnitType aDataUnitType, TVideoDataUnitEncapsulation aEncapsulation, TBool aDataInOrder)
+ {
+ // EDuCodedPicture, EDuElementaryStream, aDataInOrder == ETrue
+ if(aFormat.MimeType() != iPuData->InputDataType())
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(aDataUnitType != EDuCodedPicture)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(aEncapsulation != EDuElementaryStream)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(!aDataInOrder)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::SynchronizeDecoding()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SynchronizeDecoding(TBool aSynchronize)
+ {
+ iSynchronize = aSynchronize;
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::SetBufferOptionsL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetBufferOptionsL(const CMMFDevVideoPlay::TBufferOptions& aOptions)
+ {
+ // check values are within the constraints of this device
+ if(aOptions.iPreDecoderBufferPeriod != 0)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(aOptions.iMaxPostDecodeBufferSize != 0)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(aOptions.iPreDecoderBufferPeriod != 0)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(aOptions.iPostDecoderBufferPeriod != 0)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(aOptions.iMaxInputBufferSize > KVideoDecoderMaxDataBufferSize)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ if(aOptions.iMinNumInputBuffers > 1)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ // input is OK; write it
+ iBufferOptions = aOptions;
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::GetBufferOptions()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetBufferOptions(CMMFDevVideoPlay::TBufferOptions& aOptions)
+ {
+ aOptions = iBufferOptions;
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::SetHrdVbvSpec()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetHrdVbvSpec(THrdVbvSpecification /* aHrdVbvSpec */, const TDesC8& /* aHrdVbvParams */)
+ {
+ // the decoder is not configurable
+ // however this should not cause a fatal error
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::SetOutputDevice()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::SetOutputDevice(CMMFVideoPostProcHwDevice* aDevice)
+ {
+ // we allow output to be sent to a post-processor,
+ // even though this plugin doesn not itself provide one
+ iPostProcOutputDevice = aDevice;
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::DecodingPosition()
+ */
+TTimeIntervalMicroSeconds CMdfVideoDecodeHwDeviceAdapter::DecodingPosition()
+ {
+ if(iFrameRate == 0.0)
+ {
+ return 0;
+ }
+ // this is the total number of pictures decoded
+ return (iPictureCounters.iPicturesDecoded * (KOneSecond / (TInt)iFrameRate));
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::PreDecoderBufferBytes()
+ */
+TUint CMdfVideoDecodeHwDeviceAdapter::PreDecoderBufferBytes()
+ {
+ return 0;
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::GetBitstreamCounters()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::GetBitstreamCounters(CMMFDevVideoPlay::TBitstreamCounters& aCounters)
+ {
+ aCounters = iBitstreamCounters;
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::NumFreeBuffers()
+ */
+TUint CMdfVideoDecodeHwDeviceAdapter::NumFreeBuffers()
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ if(!FrameBufferAvailable())
+ {
+ // if there are too many output buffers waiting, we refuse an input buffer
+ // until some output buffers have been processed.
+ return 0;
+ }
+ else
+ {
+ return (iBufferManager->DataBuffersAvailable());
+ }
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::GetBufferL()
+
+ This will return a buffer of the requested size, within min/max constraints
+ */
+TVideoInputBuffer* CMdfVideoDecodeHwDeviceAdapter::GetBufferL(TUint /* aBufferSize */)
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ TVideoInputBuffer& buf = iBufferManager->GetDataBufferL();
+ return &buf;
+ }
+
+/*
+ @see CMMFVideoDecodeHwDevice::WriteCodedDataL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::WriteCodedDataL(TVideoInputBuffer* aInputBuffer)
+ {
+ // Leave on null input buffer
+ if(!aInputBuffer)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // increment received buffer count
+ iBitstreamCounters.iTotalPackets++;
+
+ CMMFDataBuffer* dataBuffer = static_cast<CMMFDataBuffer*>(iPUInputBuffer);
+ dataBuffer->Data().SetLength(aInputBuffer->iData.Length());
+ dataBuffer->SetPosition(0);
+ iDecoderPUInputPort->MipWriteData(*iPUInputBuffer);
+ iWriteRequestOutstanding = ETrue;
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::CommitL()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::CommitL()
+ {
+ // the decoder is not configurable
+ User::Leave(KErrNotSupported);
+ }
+
+/*
+ @see CMMFVideoPlayHwDevice::Revert()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::Revert()
+ {
+ // the decoder is not configurable
+ // however this should not cause a fatal error
+ }
+
+void CMdfVideoDecodeHwDeviceAdapter::SetProxy(MMMFDevVideoPlayProxy& aProxy)
+ {
+ ASSERT(!iProxy);
+ iProxy = &aProxy;
+ }
+
+
+/*
+ @see MMdfDecoderHwDeviceObserver::FrameBufferAvailable()
+ */
+TBool CMdfVideoDecodeHwDeviceAdapter::FrameBufferAvailable() const
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ return (iBufferManager->EmptyFrameBuffersAvailable() > 0);
+ }
+
+/*
+ @see MMdfVideoPlayerHwDeviceObserver::Time()
+ */
+TUint CMdfVideoDecodeHwDeviceAdapter::Time() const
+ {
+
+ if(iClockSource)
+ {
+ return iClockSource->Time().Int64();
+ }
+ else
+ {
+ // system clock without HAL
+ TInt64 tt64;
+ TTime ttime;
+ ttime.HomeTime();
+ tt64 = ttime.Int64();
+ return (tt64 - iSystemClock);
+ }
+ }
+
+/*
+ @see MMdfVideoPlayerHwDeviceObserver::DisplayFrame()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::DisplayFrame()
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ CVideoFrameBuffer* frameBuffer = NULL;
+ TRAPD(err, frameBuffer = &iBufferManager->GetFilledFrameBufferL(EFalse));
+ if(err != KErrNone)
+ {
+ // the buffer manager has failed
+ DEBUG_PRINT(_L("HwDevice: Buffer Manager failed"));
+ iProxy->MdvppFatalError(this, err);
+ }
+ else
+ {
+ // is this the last buffer?
+ iLastFrameBufferReceived = frameBuffer->LastBuffer();
+
+ TVideoPicture& thePicture = *frameBuffer;
+
+ // increment picture counter
+ CMMFBuffer& theBuffer = *frameBuffer;
+ if(theBuffer.BufferSize())
+ {
+ iPictureCounters.iPicturesDisplayed++;
+ }
+
+ iDisplayPictureAvailable = EFalse;
+
+ // send it to post-processor output, DSA, or the client
+ if(iPostProcOutputDevice)
+ {
+ TRAP(err, iPostProcOutputDevice->WritePictureL(&thePicture));
+ }
+ else if(iDSAStarted)
+ {
+ DisplayFrameDirect(&thePicture);
+ TRAP(err, iBufferManager->ReturnFrameBufferL(thePicture, CVideoFrameBuffer::EEmptied));
+
+ if (!iLastFrameBufferReceived)
+ {
+ CVideoFrameBuffer* frameBuffer = NULL;
+ TRAP(err, frameBuffer = &iBufferManager->GetEmptyFrameBufferL(ETrue));
+ if (err == KErrNone)
+ {
+ iDecoderPUOutputPort->MopReadData(*frameBuffer);
+ }
+ else
+ {
+ iProxy->MdvppFatalError(this, err);
+ return;
+ }
+ }
+ // DoPostPictureNotify() will handle MdvppStreamEnd()
+ // NB we need to notify the client here as there will be no callback
+ DoPostPictureNotify();
+ }
+ else
+ {
+ iProxy->MdvppNewPicture(&thePicture);
+ }
+ }
+ }
+
+/*
+ @see MMdfVideoPlayerHwDeviceObserver::DiscardFrame()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::DiscardFrame()
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ CVideoFrameBuffer* frameBuffer = NULL;
+ TVideoPicture* thePicture = NULL;
+ TRAPD(err, frameBuffer = &iBufferManager->GetFilledFrameBufferL(EFalse));
+ if(err != KErrNone)
+ {
+ // the buffer manager has failed
+ DEBUG_PRINT(_L("HwDevice: Buffer Manager failed"));
+ iProxy->MdvppFatalError(this, err);
+ }
+ else
+ {
+ thePicture = *frameBuffer;
+
+ // increment picture counter
+ CMMFBuffer& theBuffer = *frameBuffer;
+ if(theBuffer.BufferSize())
+ {
+ iPictureCounters.iPicturesSkipped++;
+ }
+
+ iDisplayPictureAvailable = EFalse;
+
+ // this should never leave, as thePicture has been given to us by
+ // iBufferManager to start with.
+ TRAP(err, iBufferManager->ReturnFrameBufferL(*thePicture, CVideoFrameBuffer::EEmptied));
+ if (err != KErrNone)
+ {
+ DEBUG_PRINT(_L("HwDevice: ReturnFrameBufferL failed"));
+ iProxy->MdvppFatalError(this, err);
+ }
+
+ TRAP(err, frameBuffer = &iBufferManager->GetEmptyFrameBufferL(ETrue));
+ if (err == KErrNone)
+ {
+ iDecoderPUOutputPort->MopReadData(*frameBuffer);
+ }
+
+ // NB we need to notify the client here as there will be no callback
+ DoPostPictureNotify();
+ }
+ }
+
+/*
+ @see MMdfVideoPlayerHwDeviceObserver::FrameAvailable()
+ */
+TBool CMdfVideoDecodeHwDeviceAdapter::FrameAvailable() const
+ {
+ return iDisplayPictureAvailable;
+ }
+
+/*
+ @see MMdfInputPortObserver::MipoWriteDataComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::MipoWriteDataComplete(const MMdfInputPort* aInputPort,
+ CMMFBuffer* /* aBuffer */, TInt aErrorCode)
+ {
+ iWriteRequestOutstanding = EFalse;
+ __ASSERT_ALWAYS(aInputPort == iDecoderPUInputPort, DevVideoHwDeviceDecoderPanic(0));
+ if (aErrorCode != KErrNone)
+ {
+ iProxy->MdvppFatalError(this, aErrorCode);
+ return;
+ }
+ // Return the data buffer, the position tells us how much data
+ // was used
+ if (!iInputEnd)
+ {
+ TRAPD(err, iBufferManager->ReturnDataBufferL(*iInputBuffer));
+ if(err == KErrNone)
+ {
+ iProxy->MdvppNewBuffers();
+ }
+ else
+ {
+ iProxy->MdvppFatalError(this, err);
+ }
+ }
+ else
+ {
+ // Send an empty buffer to the decoder to signal the
+ // end of the stream
+ SendLastBuffer();
+ }
+ }
+
+/*
+ @see MMdfInputPortObserver::MipoStopComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::MipoDisconnectTunnelComplete(const MMdfInputPort* /* aInputPort */,
+ TInt /* aErrorCode */)
+ {
+ }
+
+/*
+ @see MMdfInputPortObserver::MipoRestartComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::MipoRestartTunnelComplete(const MMdfInputPort* /* aInputPort */,
+ TInt /* aErrorCode */)
+ {
+ }
+
+/*
+ @see MMdfOutputPortObserver::MopoReadDataComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::MopoReadDataComplete(const MMdfOutputPort* aOutputPort,
+ CMMFBuffer* aBuffer, TInt aErrorCode)
+ {
+ if(aErrorCode != KErrNone)
+ {
+ iProxy->MdvppFatalError(this, aErrorCode);
+ return;
+ }
+
+ if(aOutputPort != iDecoderPUOutputPort)
+ {
+ iProxy->MdvppFatalError(this, KErrArgument);
+ return;
+ }
+
+ // increment iPicturesDecoded
+ if(aBuffer->BufferSize())
+ {
+ iPictureCounters.iPicturesDecoded++;
+ }
+
+ iDisplayPictureAvailable = ETrue;
+
+ TRAPD(err, iBufferManager->ReturnFrameBufferL(aBuffer, CVideoFrameBuffer::EFilled, aBuffer->LastBuffer()));
+ if(err != KErrNone)
+ {
+ iProxy->MdvppFatalError(this, err);
+ }
+ }
+
+/*
+ @see MMdfOutputPortObserver::MopoStopComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::MopoDisconnectTunnelComplete(const MMdfOutputPort* /* aOutputPort */,
+ TInt /* aErrorCode */)
+ {
+ }
+
+/*
+ @see MMdfOutputPortObserver::MopoRestartComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::MopoRestartTunnelComplete(const MMdfOutputPort* /* aOutputPort */,
+ TInt /* aErrorCode */)
+ {
+ }
+
+/*
+ @see MMdfProcessingUnitObserver::InitializeComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::InitializeComplete(const CMdfProcessingUnit* aPu, TInt aErrorCode)
+ {
+ __ASSERT_ALWAYS(aPu == iDecoderPU, DevVideoHwDeviceDecoderPanic(0));
+
+ if(aErrorCode != KErrNone)
+ {
+ iProxy->MdvppFatalError(this, aErrorCode);
+ return;
+ }
+
+ iPUInitialized = ETrue;
+ }
+
+/*
+ @see MMdfProcessingUnitObserver::ExecuteComplete()
+ */
+void CMdfVideoDecodeHwDeviceAdapter::ExecuteComplete(const CMdfProcessingUnit* aPu, TInt aErrorCode)
+ {
+ __ASSERT_ALWAYS(aPu == iDecoderPU, DevVideoHwDeviceDecoderPanic(0));
+
+ if(aErrorCode != KErrNone)
+ {
+ iProxy->MdvppFatalError(this, aErrorCode);
+ return;
+ }
+
+ if (iState == EProcessingUnitExecuting)
+ {
+ DEBUG_PRINT(_L("HwDevice: 3() - Stream end"));
+ iProxy->MdvppStreamEnd();
+ iState = EProcessingUnitIdle;
+ }
+ }
+
+// private method - DoPostPictureNotify
+void CMdfVideoDecodeHwDeviceAdapter::DoPostPictureNotify()
+ {
+ __ASSERT_ALWAYS(iBufferManager, DevVideoHwDeviceDecoderPanic(0));
+
+ DEBUG_PRINT(_L("HwDevice: PostPictureNotify"));
+ // notify the client that an input buffer is available if we weren't able to
+ // do it before
+ if(iInputBufferWaiting && iBufferManager->DataBuffersAvailable())
+ {
+ iInputBufferWaiting = EFalse;
+ iProxy->MdvppNewBuffers();
+ }
+
+ // at this point, if there are no frames left, the input buffer is free
+ // and InputEnd() has been called, then we have finished.
+ if(iInputEnd && !iBufferManager->FilledFrameBuffersAvailable() && iBufferManager->DataBuffersAvailable())
+ {
+ iLastFrameBufferReceived = ETrue;
+ }
+
+ // NB iLastFrameBufferReceived may have been set beforehand
+ if(iLastFrameBufferReceived)
+ {
+ DEBUG_PRINT(_L("HwDevice: Stream end"));
+ iProxy->MdvppStreamEnd();
+ }
+ }
+
+// private method - display the frame using direct screen access
+void CMdfVideoDecodeHwDeviceAdapter::DisplayFrameDirect(TVideoPicture* aPicture)
+ {
+ __ASSERT_ALWAYS(iScreenDevice, DevVideoHwDeviceDecoderPanic(0));
+
+ DEBUG_PRINT(_L("HwDevice: Displaying frame using DSA"));
+ // draw into our GC
+ // NB this will only work if the picture is a CFbsBitmap
+ CFbsBitmap* theBitmap = aPicture->iData.iRgbBitmap;
+ iScreenDeviceGc->DrawBitmap(iScreenDeviceRect, theBitmap);
+ iScreenDevice->Update();
+ }
+
+// private method - display the last frame using direct screen access
+void CMdfVideoDecodeHwDeviceAdapter::DisplayLastFrameDirect()
+ {
+ __ASSERT_ALWAYS(iScreenDevice, DevVideoHwDeviceDecoderPanic(0));
+
+ DEBUG_PRINT(_L("HwDevice: Redrawing last frame using DSA"));
+ // redraw
+ // NB this will only work if the picture is a CFbsBitmap
+ const TPictureData* lastFrame = NULL;
+ TRAPD(err, lastFrame = &iBufferManager->LastPictureL());
+ if(!err)
+ {
+ CFbsBitmap* theBitmap = lastFrame->iRgbBitmap;
+ iScreenDeviceGc->DrawBitmap(iScreenDeviceRect, theBitmap);
+ iScreenDevice->Update();
+ }
+ }
+
+void CMdfVideoDecodeHwDeviceAdapter::LoadProcessingUnitL(const CImplementationInformation& aImplInfo)
+ {
+ __ASSERT_ALWAYS(iPuLoader, DevVideoHwDeviceDecoderPanic(0));
+ iPuUid = aImplInfo.ImplementationUid();
+ iDecoderPU = iPuLoader->LoadProcessingUnitL(*this, iPuUid);
+ // store the opaque data associated with this PU so we can extract information about
+ // the PU later
+ iPuData = CCodecApiVideoOpaqueData::NewL(aImplInfo.OpaqueData());
+ iManufacturer = HBufC::NewL(iPuData->Manufacturer().Length());
+ iManufacturer->Des().Copy(iPuData->Manufacturer());
+ iMaxPictureSize = iPuData->MaxPictureSize();
+ }
+
+void CMdfVideoDecodeHwDeviceAdapter::SendLastBuffer()
+ {
+ __ASSERT_ALWAYS(iPUInputBuffer, DevVideoHwDeviceDecoderPanic(0));
+ __ASSERT_ALWAYS(iDecoderPUInputPort, DevVideoHwDeviceDecoderPanic(0));
+ // Send an empty buffer to the decoder to signal the
+ // end of the stream
+ iPUInputBuffer->SetLastBuffer(ETrue);
+ CMMFDataBuffer* dataBuffer = static_cast<CMMFDataBuffer*>(iPUInputBuffer);
+ dataBuffer->Data().SetLength(0);
+ dataBuffer->SetPosition(0);
+ iDecoderPUInputPort->MipWriteData(*iPUInputBuffer);
+ }