mdfdevvideoextensions/nga_mdf_postprocessor_shai/src/NGAPostProcHwDevice.cpp
changeset 58 b6dbf97aba93
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdfdevvideoextensions/nga_mdf_postprocessor_shai/src/NGAPostProcHwDevice.cpp	Thu Sep 16 18:57:38 2010 +0100
@@ -0,0 +1,2689 @@
+/*
+* Copyright (c) 2006 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 "NGAPostProcHwDevice.h"
+#include "NGAPostProcSessionManager.h"
+#include "NGAPostProcSurfaceHandler.h"
+
+//currently this uid only used if not under WINSCW environment since the only hw to use is bridge
+#define EStUidPixelFormatYUV_420MB  0x2001FBC1
+// post-processor info
+const TUid KUidVideoPostProcHwDevice = {KUidNGAPostProcHwDeviceImplUid};
+_LIT(KManufacturer, "Nokia Inc.");
+_LIT(KIdentifier, "Nokia S60 Video Post Processor Hardware Device Plugin");
+
+// --- Constants ---
+const TInt KMaxVBMBuffers      			= 4;
+const TInt KMinVBMInputWidth   			= 32; 
+const TInt KMinVBMInputHeight  			= 32;
+const TInt KMaxVBMInputWidth   			= 1280; 
+const TInt KMaxVBMInputHeight  			= 720;
+const TInt KRenderAhead 	     		= 50000;     
+const TInt KMaxRenderDelay     			= 50000;
+const TInt KPostingOfset       			= 0;    
+const TInt KColorConversionBuffers  	= 3;
+const TInt KMaxBuffersGceCanHold    	= 3;
+const TInt KDefPlayRate					= 100;
+const TInt KMaxAllowedSkipInNFrames 	= 40;
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int32 gColorConvYUVtoYUV422Int (tBaseVideoFrame *yuv420Frame, tBaseVideoFrame* yuv422Frame,
+							   uint8 outClrFmt, int16 stride); 
+
+int32 Emz_VDec_gColorConv_YUVtoRGB ( 
+	  tBaseVideoFrame *srcImage, uint8 *dstImage, tWndParam *srcWindow, 
+	  tWndParam *dstWindow, uint8 srcImageFormat, uint8 dstImageFormat,
+	  uint8 colorConvScheme);
+		 	  
+#ifdef __cplusplus
+}
+#endif
+
+//**************************************************
+
+CMMFVideoPostProcHwDevice* CNGAPostProcHwDevice::NewL() 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice::NewL() ++"));
+
+    CNGAPostProcHwDevice* self = new (ELeave) CNGAPostProcHwDevice; 
+    CleanupStack::PushL(self);
+    self->ConstructL(); 
+    CleanupStack::Pop();
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice::NewL() --"));
+    return (CMMFVideoPostProcHwDevice*)self; 
+}
+
+void CNGAPostProcHwDevice::ConstructL() 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::ConstructL() ++"), this);
+    
+    // support for VBM buffer interface
+    iVBMBufferOptions.iNumInputBuffers  = KMaxVBMBuffers; 
+    iVBMBufferOptions.iBufferSize = TSize(KMaxVBMInputWidth, KMaxVBMInputHeight);
+    iPostingTimer = CNGAPostProcTimer::NewL(*this);
+    User::LeaveIfError(iWsSession.Connect());
+    
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::ConstructL() --"), this);
+}
+
+CNGAPostProcHwDevice::CNGAPostProcHwDevice() 
+        :   iProxy(NULL), 
+            iInputDecoderDevice(NULL),
+            iCurrentPlaybackPosition(TTimeIntervalMicroSeconds(0)),
+            iPPState(EInitializing),
+            iSurfaceHandler(NULL),
+            iSessionManager(NULL),
+            iIsInputEnded(EFalse),
+            iPostingTimer(NULL),
+            iFirstPictureUpdated(EFalse),
+            iUsingExternalSurface(EFalse),
+            iIsColorConversionNeeded(EFalse),
+            iSurfaceCreatedEventPublished(EFalse),
+            iOverflowPictureCounter(0),
+            iVideoFrameBufSize(0),
+            iResourceLost(EFalse),
+            iRedrawDone(EFalse),
+			iRedrawSurfaceInUse(EFalse),
+            iVBMObserver(NULL),
+            iVBMEnabled(EFalse),        
+            count(0),
+            iSurfaceMask(surfaceHints::EAllowAllExternals),
+            iSurfaceKey(TUid::Uid(surfaceHints::KSurfaceProtection)),
+            iVideoSurfaceObserver(NULL),
+            iVPObserver(NULL),
+            iPicSize(0,0),
+			iAspectRatioNum(1),
+			iAspectRatioDenom(1),
+            iStepFrameCount(0),
+            iPlayRate(KDefPlayRate),
+            iKeyFrameMode(EFalse),
+            iFPObserver(NULL),
+            iIsExternalChunk(EFalse)
+{
+	iSurfaceId 		 = TSurfaceId::CreateNullId();
+
+#if defined __WINSCW__ 
+	iAttributes().iPixelFormat    = EUidPixelFormatYUV_422Interleaved;
+#else    
+	iAttributes().iPixelFormat    = (TUidPixelFormat) EStUidPixelFormatYUV_420MB;
+#endif
+}
+
+CNGAPostProcHwDevice::~CNGAPostProcHwDevice()
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::~CNGAPostProcHwDevice() ++"), this);
+   	if (iSessionManager)
+    {
+        iSessionManager->CancelNotifiers();
+        delete iSessionManager;
+        iSessionManager = NULL;
+    }
+   	
+   	while (iSupportedInputFormats.Count()>0)
+    {
+		iSupportedInputFormats.Remove(0);
+    }
+    
+   	while (iProcessQ.Count()>0)
+    {
+		iProcessQ.Remove(0);
+    }
+
+   	if(iPostingTimer)
+    {
+    	iPostingTimer->Cancel();
+        delete iPostingTimer;
+        iPostingTimer = NULL;
+    }
+    
+    while (iVBMBufferReferenceQ.Count()>0)
+    {
+        TVideoPicture* pic = iVBMBufferReferenceQ[0];
+        iVBMBufferReferenceQ.Remove(0);
+        if (iColorConversionQ.Count()>0)
+    	{
+	        iColorConversionQ.Remove(0);
+	    }
+
+        if (pic->iHeader) delete pic->iHeader;
+        delete pic->iData.iRawData;
+        delete pic;
+    }
+    
+    iSupportedInputFormats.Reset();
+    iSupportedInputFormats.Close();
+    
+    iVBMBufferReferenceQ.Reset();
+    iVBMBufferReferenceQ.Close();
+    
+    iColorConversionQ.Reset();
+    iColorConversionQ.Close();
+    
+    iVBMBufferQ.Reset();
+    iVBMBufferQ.Close();
+    
+    iProcessQ.Reset();
+    iProcessQ.Close();
+        
+    iInputQ.Reset();
+    iInputQ.Close();
+    
+    if (iSurfaceHandler)
+    {
+    	if(!iSurfaceId.IsNull())
+    	{
+    		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::UnregisterSurface"), this);
+			TInt numScreens = iWsSession.NumberOfScreens();
+    		for(TInt i=0;i < numScreens;i++)
+    		{
+    			iWsSession.UnregisterSurface(i, iSurfaceId);
+    		}
+    		iWsSession.Flush();
+        	TInt err = iSurfaceHandler->DestroySurface(iSurfaceId);
+    	}
+        delete iSurfaceHandler;
+        iSurfaceHandler = NULL;
+    }
+    
+    iWsSession.Close();
+    if(!iIsExternalChunk)
+    {
+        iChunk.Close();
+    }
+    
+    RDebug::Printf("------ Statistics of Post Processor ------");
+    RDebug::Printf("    Pictures Received : %d", iPictureCounters.iTotalPictures);
+    RDebug::Printf("    Pictures Displayed: %d", iPictureCounters.iPicturesDisplayed);
+    RDebug::Printf("    Pictures Skipped  : %d", iPictureCounters.iPicturesSkipped);
+    RDebug::Printf("    Pictures overflow : %d", iOverflowPictureCounter);
+    RDebug::Printf("------------------------------------------");
+    
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:~() --"), this);
+}
+
+void CNGAPostProcHwDevice::SetInputFormatL(const TUncompressedVideoFormat&  aFormat) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputFormatL() Pattern= %x ++"), this, aFormat.iYuvFormat.iPattern);
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputFormatL() FAILED: Unexpected state"), this);
+        User::Leave(KErrNotReady);
+    }
+
+		iVideoFormat = aFormat; 
+		if( ((iVideoFormat.iYuvFormat.iPattern == EYuv420Chroma1) ||
+			(iVideoFormat.iYuvFormat.iPattern == EYuv420Chroma2) ||
+    		(iVideoFormat.iYuvFormat.iPattern == EYuv420Chroma3) ))
+		{
+			iVideoFormat.iYuvFormat.iCoefficients  	     = EYuvBt709Range1;
+    		iVideoFormat.iYuvFormat.iPattern       	     = EYuv422Chroma1;
+    		iVideoFormat.iYuvFormat.iDataLayout          = EYuvDataInterleavedBE;
+			
+#if defined __WINSCW__				
+				iIsColorConversionNeeded = ETrue; 
+#else
+				iAttributes().iPixelFormat = (TUidPixelFormat) EStUidPixelFormatYUV_420MB;
+#endif
+		}	
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputFormatL() WARNING: -- Not Found!"), this);
+}
+
+
+void CNGAPostProcHwDevice::SetInputDevice(CMMFVideoDecodeHwDevice* aDevice) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputDevice() ++"), this);
+
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputDevice() FAILED: unexpected state"), this);
+        return;
+	}
+
+    iInputDecoderDevice = aDevice;
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputDevice() --"), this);
+}
+
+void CNGAPostProcHwDevice::GetOutputFormatListL(RArray<TUncompressedVideoFormat>& ) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetOutputFormatListL() ++"), this);
+
+
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetOutputFormatListL() --"), this);
+}
+
+void CNGAPostProcHwDevice::SetOutputFormatL(const TUncompressedVideoFormat&  ) 
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetOutputFormatL() ++"), this);
+
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetOutputFormatL() --"), this);
+}
+
+void CNGAPostProcHwDevice::SetClockSource(MMMFClockSource* aClock) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetClockSource() ++"), this);
+    
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetClockSource() FAILED: Unexpected state"), this);
+        return;
+	}
+    iClockSource = aClock;
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetClockSource() --"), this);
+}
+
+void CNGAPostProcHwDevice::SetVideoDestScreenL(TBool /*aScreen*/) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetVideoDestScreenL() ++"), this);
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetVideoDestScreenL() --"), this);
+}
+
+void CNGAPostProcHwDevice::SetProxy(MMMFDevVideoPlayProxy& aProxy) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetProxy() ++"), this);
+
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetProxy() FAILED: Unexpected state"), this);
+        return;
+	}
+
+    iProxy = &aProxy;
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetProxy() --"), this);
+}
+
+void CNGAPostProcHwDevice::Initialize() 
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize ++"));
+	TInt err = KErrNone;
+
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize() FAILED: Unexpected state"), this);
+        if (iProxy)
+		{
+			iProxy->MdvppInitializeComplete(this, KErrNotReady);
+		}
+		return;
+	}
+	if (!iSurfaceHandler)
+    {
+    	TRAP(err, iSurfaceHandler = CNGAPostProcSurfaceHandler::NewL());
+    	if (err != KErrNone)
+    	{
+    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to create SurfaceHandler."), this);
+    	    if (iProxy)
+			{
+				iProxy->MdvppInitializeComplete(this, err);
+			}
+			return;
+    	}
+    }
+    if (!iSessionManager)
+    {
+    	TRAP(err, iSessionManager = CNGAPostProcSessionManager::NewL());
+    	if (err != KErrNone)
+    	{
+    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to create SessionManager."), this);
+    	    if (iProxy)
+			{
+				iProxy->MdvppInitializeComplete(this, err);
+			}
+			return;
+    	}
+    	iSessionManager->SetObserver(*this);
+    }
+
+  	if (iInputDecoderDevice)
+	{
+		MMmfVideoResourceHandler* handler = NULL;
+		handler = (MMmfVideoResourceHandler*)iInputDecoderDevice->CustomInterface(KUidMmfVideoResourceManagement);
+		if (handler)
+		{
+			handler->MmvrhSetObserver((MMmfVideoResourceObserver*)this);
+		}
+		else
+		{
+			PP_DEBUG(_L("ppHwDev[%x]:Initialize() decoder yet to implement MMmfVideoResourceHandler CI"), this);
+		}
+		
+		MMmfVideoPropertiesNotifier* VPHandler = NULL;
+		VPHandler = (MMmfVideoPropertiesNotifier*)iInputDecoderDevice->CustomInterface(KUidMmfVideoPropertiesManagement);
+		if (VPHandler)
+		{
+			PP_DEBUG(_L("ppHwDev[%x]:Initialize() Register for video property changes"), this);
+			VPHandler->MmvpnSetObserver((MMmfVideoPropertiesObserver*)this);
+		}
+		else
+		{
+			PP_DEBUG(_L("ppHwDev[%x]:Initialize() decoder yet to implement MMmfVideoPropertiesNotifier CI"), this);
+		}
+	}
+		
+    // Initialize picture counters
+	iPictureCounters.iPicturesSkipped 	= 0;
+	iPictureCounters.iPicturesDisplayed = 0;
+	iPictureCounters.iTotalPictures = 0;
+	iOverflowPictureCounter = 0;
+	
+	iPPState = EInitialized;
+	if(iPostInitializeResponse)
+	{
+		
+		TRAP(err, iPostInitializeResponse->MmpirPostInitializeResponseL());
+	}
+	
+	if(!err)
+	{
+		TRAP(err, iSessionManager->CreateNotifierL(iInfo().iBuffers));
+	}
+	else
+	{
+		iPPState = EInitializing;
+	}
+	
+	if (iProxy)
+	{
+		iProxy->MdvppInitializeComplete(this, err);
+	}
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize --"), this);
+}
+
+void CNGAPostProcHwDevice::WritePictureL(TVideoPicture* aPicture) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePicture bufId = %d"), this,GetID(aPicture));
+	TVideoPicture* pic;
+	if (iPPState==EInitializing || iPPState==EStopped || iIsInputEnded)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePictureL() FAILED: Unexpected state"), this);
+        User::Leave(KErrNotReady);
+	}
+
+    if(!aPicture)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePictureL() FAILED: Invalid argument"), this);
+		User::Leave(KErrArgument);
+	}
+	pic = aPicture;	
+	iPictureCounters.iTotalPictures++;
+	if((iPPState != EPlaying) && (iFirstPictureUpdated))
+	{
+	//If decoder is fast enough, it can happen between Initialize->Start time gap between 
+	//DecodeHwDevice and PostProc_HwDevice. OR between Pause->Resume time gap as well.
+		AddToQ(pic);
+	}
+	else if( iInputQ.Count() > 0 )
+	{
+		AddToQ(pic);
+		AttemptToPost();
+	}
+	else
+	{
+		TTimeToPost timeToPost = EPostIt;
+		TInt64 delta = 0;
+	    if(iFirstPictureUpdated)
+		{
+			timeToPost = (TTimeToPost)IsTimeToPost(pic, delta);
+			if(!IsGceReady())
+		    {  
+				PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePictureL GCE not ready"), this );
+				if(timeToPost == EPostIt)
+				{
+                    timeToPost = EDelayIt;
+				}
+		    }
+		    if (delta > 0x7FFFFFFF)
+		    {
+		         PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePictureL Too large delta .. skipping"), this ); 
+		         timeToPost = ESkipIt;
+		    }
+		}
+		else
+		{
+			if(!iSurfaceCreatedEventPublished)
+                {
+                    PublishSurfaceCreated();
+                }
+			iFirstPictureUpdated = ETrue;
+		}
+		
+
+		switch(timeToPost)
+		{
+			case EDelayIt:
+			{
+				if(AddToQ(pic) != 0)
+				{
+					break;
+				}
+				iPostingTimer->Cancel();
+				SetTimer(delta);
+			}
+			break;
+			case EPostIt:
+			{
+		
+				if(iIsColorConversionNeeded)
+				{
+					TVideoPicture* ccPic;				
+	    			ccPic = DoColorConvert(pic); // output will be in ccPic
+	    			pic = ccPic;			   
+				}
+						
+				#ifdef _DUMP_YUV_FRAMES
+				captureYuv(pic);
+				#endif
+				TInt err = iSessionManager->PostPicture(iSurfaceId, GetID(pic), ETrue); 
+				if(err == KErrNone)
+				{
+				    iProcessQ.Append(pic);
+					iCurrentPlaybackPosition = pic->iTimestamp;
+				}
+				else
+				{
+					ReleasePicture(pic);
+				}
+			}
+			break;
+			case ESkipIt:
+			{
+				ReleasePicture(pic); 
+				PicturesSkipped();
+			}
+			break;
+		}
+    }
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePicture --"), this);
+}
+
+
+CPostProcessorInfo* 
+CNGAPostProcHwDevice::PostProcessorInfoLC() 
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:PostProcessorInfoLC() ++"), this);
+    TUncompressedVideoFormat yuvFormat;
+    RArray<TUint32>                     SupportedPostProcess;
+    TBool                               SupportedHwAcceleration = ETrue;   //Non-Accelerated ETrue, 
+    TYuvToRgbCapabilities               SupportedYuvToRgbCapab; 
+    TInt32                              SupportedRotations = ERotateNone; // no rotation supported
+    
+    TBool                               SupportedArbitraryScaling = EFalse; // no scaling supported
+    RArray<TScaleFactor>                SupportedScaleFactors;
+    TBool                               SupportedAntiAliasing = EFalse;
+    
+    //default
+    yuvFormat.iDataFormat                     = EYuvRawData;
+    yuvFormat.iYuvFormat.iYuv2RgbMatrix       = 0;
+    yuvFormat.iYuvFormat.iRgb2YuvMatrix       = 0;
+    yuvFormat.iYuvFormat.iAspectRatioNum      = 1;
+    yuvFormat.iYuvFormat.iAspectRatioDenom    = 1;
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt709Range1;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout          = EYuvDataInterleavedBE;
+    
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt709Range0;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataInterleavedBE;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt709Range0;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataInterleavedLE;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+            
+	yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt709Range1;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataInterleavedLE;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+            
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt601Range0;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataInterleavedBE;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt601Range1;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataInterleavedBE;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+            
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt601Range0;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataInterleavedLE;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt601Range1;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataInterleavedLE;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv422Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+    
+    //YUV 420 planar
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt709Range1;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataPlanar;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma3;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt709Range0;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataPlanar;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma3;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt601Range1;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataPlanar;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma3;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iCoefficients  	  = EYuvBt601Range0;
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma1;
+    yuvFormat.iYuvFormat.iDataLayout    	  = EYuvDataPlanar;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma2;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+
+    yuvFormat.iYuvFormat.iPattern       	  = EYuv420Chroma3;
+    User::LeaveIfError(iSupportedInputFormats.Append(yuvFormat));
+            
+    CPostProcessorInfo* postProcessorInfo = CPostProcessorInfo::NewL( 
+                KUidVideoPostProcHwDevice, 
+                KManufacturer, 
+                KIdentifier, 
+                TVersion(1, 0, 0), 
+                iSupportedInputFormats.Array(),
+                SupportedPostProcess.Array(), 
+                SupportedHwAcceleration,   
+                ETrue,      //Direct Display
+                SupportedYuvToRgbCapab, 
+                SupportedRotations, 
+                SupportedArbitraryScaling,
+                SupportedScaleFactors.Array(), 
+                SupportedAntiAliasing);
+                
+    CleanupStack::PushL(postProcessorInfo);            
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:PostProcessorInfoLC() --"), this);
+    return postProcessorInfo;
+}
+
+void CNGAPostProcHwDevice::MmvprcGetPlayRateCapabilitiesL(TVideoPlayRateCapabilities& aCap)
+{       
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcGetPlayRateCapabilitiesL ++"), this);       
+     aCap.iPlayForward = ETrue;       
+     aCap.iPlayBackward = ETrue;       
+     aCap.iStepForward = ETrue;       
+     aCap.iStepBackward = ETrue;       
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcGetPlayRateCapabilitiesL --"), this);       
+}       
+
+void CNGAPostProcHwDevice::MmvprcSetPlayRateL(const TInt aRate)
+{       
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcSetPlayRateL ++"), this);       
+     iPlayRate = aRate;
+     if (iPlayRate<0)        
+     {       
+         iKeyFrameMode = ETrue;    
+     }       
+     else        
+     {       
+         iKeyFrameMode = EFalse;   
+         ResetCountingBuffer();       
+     }       
+     //In fast forward go direct to key frame mode if speed >4X =     
+    if (iPlayRate>KDefPlayRate*4)
+     {       
+         if (iFPObserver)        
+         {       
+             iFPObserver->MmvproKeyFrameModeRequest();       
+             iKeyFrameMode=ETrue;       
+         }       
+     }       
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcSetPlayRateL=%d --"), this, aRate);       
+}       
+
+TInt CNGAPostProcHwDevice::MmvprcPlayRateL()
+{       
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcPlayRateL= ++"), this);       
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcPlayRateL= --"), this);       
+    return iPlayRate;       
+}       
+
+void CNGAPostProcHwDevice::MmvprcStepFrameL(const TInt aStep)
+{       
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcStepFrameL= ++"), this);       
+    iStepFrameCount = aStep;       
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcStepFrameL=%d --"), this, aStep);       
+}       
+
+void CNGAPostProcHwDevice::MmvprcSetObserver(MMmfVideoPlayRateObserver& aObserver)
+{       
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcSetObserver ++"), this);       
+    iFPObserver  = &aObserver;
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvprcSetObserver --"), this);
+} 
+
+void CNGAPostProcHwDevice::MmvsoSetSecureOutputL(TBool aSecure)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvsoSetSecureOutputL aSecure = %d++"), this, aSecure);     
+	TInt err = KErrNone;  
+    if(aSecure)
+	{
+		iSurfaceMask = surfaceHints::EAllowInternalOnly;
+	}
+	else
+	{
+		iSurfaceMask = surfaceHints::EAllowAllExternals;
+	}
+	if(!iSurfaceId.IsNull())
+	{
+		err = AddHints();
+		if(err != KErrNone)
+		{
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvsoSetSecureOutputL -- leaving err = %d"), this, err);
+			User::Leave(err);
+		}
+	}
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvsoSetSecureOutputL --"), this);
+}
+
+void CNGAPostProcHwDevice::MmavsoSetAllowedOutputL(TUint aAllowedOutputMask)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmavsoSetAllowedOutputL aAllowedOutputMask=0x%08x ++"), this,aAllowedOutputMask);  
+   TInt err = KErrNone;
+   iSurfaceMask = surfaceHints::EAllowInternalOnly;
+    if (aAllowedOutputMask == EVideoAllowAll)
+    {
+        iSurfaceMask = surfaceHints::EAllowAllExternals;
+    }
+    else if (aAllowedOutputMask == EVideoAllowInternalOnly)
+    {
+        iSurfaceMask = surfaceHints::EAllowInternalOnly;
+    }
+    else 
+    {
+        // we hope to find some valid output prefs
+        if (aAllowedOutputMask & EVideoAllowAnalog)
+        {
+            iSurfaceMask |= surfaceHints::EAllowAnalog;
+        }
+        if (aAllowedOutputMask & EVideoAllowMacroVision)
+        {
+            iSurfaceMask |= surfaceHints::EAllowAnalogProtectionRequired;
+        }
+        if (aAllowedOutputMask & EVideoAllowHDMI)
+        {
+            iSurfaceMask |= surfaceHints::EAllowDigital;
+        }
+        if (aAllowedOutputMask & EVideoAllowHdmiHdcpRequested)
+        {
+            iSurfaceMask |= surfaceHints::EAllowDigitalProtectionRequested;
+        }
+        if (aAllowedOutputMask & EVideoAllowHdmiHdcpRequired)
+        {
+            iSurfaceMask |= surfaceHints::EAllowDigitalProtectionRequired;
+        }
+    }
+    
+	if((!iSurfaceId.IsNull()))
+	{
+		err = AddHints();
+		if(err != KErrNone)
+		{
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmavsoSetAllowedOutputL -- leaving err = %d"), this, err);
+			User::Leave(err);
+		}
+	}
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmavsoSetAllowedOutputL --"), this);
+}	
+
+void CNGAPostProcHwDevice::SetPostProcessTypesL(TUint32 /*aCombination*/) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetPostProcessTypesL ++"), this);
+	
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetPostProcessTypesL --"), this);
+}
+
+void CNGAPostProcHwDevice::SetInputCropOptionsL(const TRect& /*aRect*/) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputCropOptionsL ++"), this);
+   
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetInputCropOptionsL --"), this);
+}    
+
+void CNGAPostProcHwDevice::SetYuvToRgbOptionsL( const TYuvToRgbOptions&  /*aOptions*/, const TYuvFormat& /*aYuvFormat*/, TRgbFormat /*aRgbFormat*/) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetYuvToRgbOptionsL ++"), this);
+
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetYuvToRgbOptionsL --"), this);
+}
+
+void CNGAPostProcHwDevice::SetYuvToRgbOptionsL(const TYuvToRgbOptions& /*aOptions*/)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetYuvToRgbOptionsL ++"), this);
+
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetYuvToRgbOptionsL --"), this);
+}
+
+void CNGAPostProcHwDevice::SetRotateOptionsL(TRotationType ) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetRotateOptionsL ++"), this);
+    
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetRotateOptionsL --"));
+}
+
+void CNGAPostProcHwDevice::SetScaleOptionsL(const TSize& /*aTargetSize*/, TBool /*aAntiAliasFiltering*/) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetScaleOptionsL ++"), this);
+    
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetScaleOptionsL --"), this);
+}
+
+void CNGAPostProcHwDevice::SetOutputCropOptionsL(const TRect& /*aRect*/) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetOutputCropOptionsL ++"), this);
+    
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetOutputCropOptionsL --"), this);
+}
+
+void CNGAPostProcHwDevice::SetPostProcSpecificOptionsL(const TDesC8& ) 
+{ 
+    //ignore 
+}
+
+void CNGAPostProcHwDevice::CommitL() 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:CommitL ++"), this);
+
+   	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:CommitL --"), this);
+}
+
+void CNGAPostProcHwDevice::Revert() 
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Revert ++"), this);
+    
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Revert --"), this);
+}
+
+void CNGAPostProcHwDevice::StartDirectScreenAccessL( const TRect& /*aVideoRect*/, CFbsScreenDevice& /*aScreenDevice*/, const TRegion& /*aClipRegion*/) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:StartDSA ++"), this);
+    
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:StartDSA --"), this);
+}
+
+void CNGAPostProcHwDevice::AbortDirectScreenAccess() 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AbortDSA ++"), this);
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AbortDSA --"), this);
+}
+
+void CNGAPostProcHwDevice::SetScreenClipRegion(const TRegion& /*aRegion*/) 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetScreenClipRegion ++"), this);
+    
+    
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetScreenClipRegion --"), this);
+}		    
+
+void CNGAPostProcHwDevice::SetPauseOnClipFail(TBool ) 
+{ 
+    //ignore. Post Processor will always behave as aPause==False. 
+}
+
+TBool CNGAPostProcHwDevice::IsPlaying()
+{
+	if( iPPState == EPlaying)
+	{
+    	return ETrue; 
+    }
+    else
+    {
+    	return EFalse;
+    }
+}
+
+void CNGAPostProcHwDevice::Redraw() 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw ++"), this);
+	TInt err = KErrNone;
+	if(iRedrawSurfaceInUse && !iRedrawDone)
+	{
+        err = AddHints();
+        if (err != KErrNone)
+        {
+            PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw -- failed to AddHints %d"), 
+                         this, err);
+            iProxy->MdvppFatalError(this, err);	
+            return;   
+        }
+        PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw registering the temp surface"), this);
+		err = RegisterSurface(iSurfaceId);
+		if (err != KErrNone)
+		{
+		   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw -- failed to Register Surface %d"), 
+		   				this, err);
+		   	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   		iSurfaceId = TSurfaceId::CreateNullId();
+			iProxy->MdvppFatalError(this, err);	
+			return;   				
+		}
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw registering the temp surface done"), this);
+        err = iSessionManager->PostPicture(iSurfaceId, 0, EFalse);
+		if (err != KErrNone)
+		{
+			iProxy->MdvppFatalError(this, err);	
+			return;
+		}
+        PublishSurfaceCreated();
+        iRedrawDone = ETrue;
+    }
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw --"), this);
+}
+
+void CNGAPostProcHwDevice::Start() 
+{  
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Start ++"), this);
+	iPPState = EPlaying;
+	
+	//TBC: when buffers given to post proc even before start. 
+	//Even the buffers must be available to PostProc but not displayed. 
+	//This will happen only when neighbouring decodeHwDevice decodes earlier than Start()
+	//call. Need to check if MDF guidelines allow this.
+	AttemptToPost();
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Start --"), this);
+}
+
+void CNGAPostProcHwDevice::Stop() 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Stop ++"), this);
+    iPPState = EStopped;
+	if (iSessionManager)
+	{
+	    iSessionManager->CancelNotifiers();
+	}
+	if (iPostingTimer)
+	{
+        iPostingTimer->Cancel();
+	}
+	ReleaseProcessQ();
+	ReleaseInputQ();
+
+	//Stop must keep on displaying the last frame. Blank Screen must not be visible
+	//to client. No Unregistering of surface should happen here. 
+	//This Req is not necessary anymore. Only applicable to Pause.
+	
+	RDebug::Printf("------ Statistics of Post Processor ------");
+    RDebug::Printf("    Pictures Received : %d", iPictureCounters.iTotalPictures);
+    RDebug::Printf("    Pictures Displayed: %d", iPictureCounters.iPicturesDisplayed);
+    RDebug::Printf("    Pictures Skipped  : %d", iPictureCounters.iPicturesSkipped);
+    RDebug::Printf("------------------------------------------");
+    
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Stop --"), this);
+}
+
+void CNGAPostProcHwDevice::Pause()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Pause ++"), this);
+	iPPState = EPaused;
+    iPostingTimer->Cancel();
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Pause --"), this);
+}
+
+void CNGAPostProcHwDevice::Resume()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Resume ++"), this);
+	iPPState = EPlaying;
+	AttemptToPost();
+   	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Resume --"), this);
+}
+
+void CNGAPostProcHwDevice::SetPosition(const TTimeIntervalMicroSeconds& aPlaybackPosition) 
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetPosition ++"), this);
+    
+    if (iPPState == EInitializing)
+    { 
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetPosition FAILED: Unexpected state"), this);
+        return;
+    }
+    if (iPPState == EPaused)
+    {	
+        iFirstPictureUpdated = EFalse;
+    }
+    iCurrentPlaybackPosition = aPlaybackPosition;  
+    
+    ReleaseInputQ();
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetPosition --"), this);
+}
+
+void CNGAPostProcHwDevice::FreezePicture(const TTimeIntervalMicroSeconds& ) 
+{ 
+    //TODO:
+}
+
+void CNGAPostProcHwDevice::ReleaseFreeze(const TTimeIntervalMicroSeconds&  ) 
+{ 
+    //TODO:
+}
+
+TTimeIntervalMicroSeconds 
+CNGAPostProcHwDevice::PlaybackPosition() 
+{ 
+	if (iPPState == EInitializing)
+    {
+        return TTimeIntervalMicroSeconds(0);
+    }
+    
+    return iCurrentPlaybackPosition; 
+}
+
+TUint CNGAPostProcHwDevice::PictureBufferBytes() 
+{   //TODO 
+    return 0; 
+}
+
+void CNGAPostProcHwDevice::GetPictureCounters( CMMFDevVideoPlay::TPictureCounters&  aCounters) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetPictureCounters ++"), this);
+	
+	if (iPPState == EInitializing)
+		return;
+	aCounters = iPictureCounters;
+	
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetPictureCounters --"), this);
+}
+
+void CNGAPostProcHwDevice::SetComplexityLevel(TUint ) 
+{ 
+    //not required 
+}
+
+TUint CNGAPostProcHwDevice::NumComplexityLevels() 
+{ 
+    //not required 
+    return 1; 
+}
+
+void CNGAPostProcHwDevice::GetComplexityLevelInfo(TUint , CMMFDevVideoPlay::TComplexityLevelInfo& ) 
+{ 
+    //not required 
+}
+
+void CNGAPostProcHwDevice::ReturnPicture(TVideoPicture* ) 
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReturnPicture +-"), this);
+    //not required for direct rendering 
+}
+
+TBool CNGAPostProcHwDevice::GetSnapshotL(TPictureData& aPictureData, const TUncompressedVideoFormat& /*aFormat*/)
+{ 
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetSnapshotL %d %d ++"), this, iVBMEnabled, iProcessQ.Count());
+	TVideoPicture* 		pic = NULL;
+	TInt 				err = KErrNone;
+	TBool				frameAvailable =EFalse;
+	tWndParam			inputCropWindow;
+	tWndParam			outputCropWindow;
+	tBaseVideoFrame		inputFrame;
+	inputFrame.lum 		= NULL; 
+	
+	if(aPictureData.iDataFormat == ERgbFbsBitmap)
+	{	
+		if(iProcessQ.Count())
+		{
+			pic = iProcessQ[0]; //frame already submitted for display
+		}
+		else if(iInputQ.Count())
+		{
+			pic = iInputQ[0]; //frame yet to be displayed
+		}
+		if(pic) 
+		{
+			if (iVBMEnabled)
+		    {
+				inputFrame.lum	= (TUint8*)pic->iData.iRawData->Ptr();
+			}
+			else
+			{
+				if (iInputDecoderDevice)
+				{
+					MMmfVideoFetchFrame* VFHandler = NULL;
+					VFHandler = (MMmfVideoFetchFrame*)iInputDecoderDevice->CustomInterface(KUidMMFVideoFetchFrame);
+					if (VFHandler)
+					{
+						PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetSnapshotL() fetch frame"), this);
+						inputFrame.lum = (TUint8*)VFHandler->MmvffGetFrame(GetID(pic));
+					}
+					else
+					{
+						PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetSnapshotL() decoder yet to implement MMmfVideoFetchFrame CI"), this);
+					}
+				}
+			}
+		}
+		if(inputFrame.lum)
+		{
+			inputFrame.cb	= inputFrame.lum + iPicSize.iWidth * iPicSize.iHeight;
+			
+			if( ((iVideoFormat.iYuvFormat.iPattern == EYuv420Chroma1) ||
+				(iVideoFormat.iYuvFormat.iPattern == EYuv420Chroma2) ||
+	    		(iVideoFormat.iYuvFormat.iPattern == EYuv420Chroma3) ))						
+			{
+				inputFrame.cr = inputFrame.lum + (iPicSize.iWidth * iPicSize.iHeight*5)/4;
+			}
+			else
+			{
+				inputFrame.cr = inputFrame.lum + (iPicSize.iWidth * iPicSize.iHeight*3)/2;
+			}
+			
+			inputFrame.width	= (unsigned short)iPicSize.iWidth;
+			inputFrame.height	= (unsigned short)iPicSize.iHeight;
+			
+			outputCropWindow.wndHeight  = iPicSize.iHeight;	
+			outputCropWindow.wndWidth	= iPicSize.iWidth; 	
+			outputCropWindow.xOffset	= 0;
+			outputCropWindow.yOffset	= 0;
+			
+			inputCropWindow.wndHeight  = iPicSize.iHeight;	
+			inputCropWindow.wndWidth	= iPicSize.iWidth; 	
+			inputCropWindow.xOffset	= 0;
+			inputCropWindow.yOffset	= 0;
+			
+			RFbsSession fbs;
+			User::LeaveIfError(fbs.Connect());
+			CFbsBitmap* iOutBitmap = aPictureData.iRgbBitmap;
+			TInt status = iOutBitmap->Resize(iPicSize);
+			if (status == KErrNone)
+			{
+				// Lock the heap to prevent the FBS server from invalidating the address
+		        iOutBitmap->LockHeap();
+		        TUint8* dataAddress = (TUint8*)iOutBitmap->DataAddress();
+				err = ColorConvert(&inputFrame, dataAddress, &inputCropWindow, &outputCropWindow);
+				iOutBitmap->UnlockHeap();
+				frameAvailable = ETrue;
+			}
+			fbs.Disconnect();
+		}
+	}
+	else
+	{
+		err = KErrNotSupported;
+	}
+	if(err != KErrNone)
+	{
+		User::Leave(err);
+	}
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:GetSnapshotL --"), this);
+	return(frameAvailable);
+}
+
+void CNGAPostProcHwDevice::InputEnd() 
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:InputEnd ++"), this);
+    
+	if (iPPState!=EPlaying && iPPState!=EPaused)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:InputEnd FAILED: Unexpected state"), this);
+        return;
+	}
+    iIsInputEnded = ETrue;
+    
+    if( (iProcessQ.Count() <= 1) && (iInputQ.Count() == 0))
+        {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:InputEnd() Stream end"), this);
+		iProxy->MdvppStreamEnd();
+	}
+    
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:InputEnd --"), this);
+}
+
+TAny* CNGAPostProcHwDevice::CustomInterface(TUid aInterface)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:CustomInterface UID = %d ++"), this, aInterface.iUid);
+	
+	if (aInterface == KUidMmfVideoBufferManagement)
+    {
+      return (MMmfVideoBufferManagement *)this;
+    }
+	if (aInterface == KUidMMFVideoSurfaceSupport)
+	{
+      return (MMMFVideoSurfaceSupport *)this;
+    }
+	if (aInterface == KUidMMFVideoSurfaceHandleControl)
+	{
+    	return (MMmfVideoSurfaceHandleControl *)this;
+  }    
+    if (aInterface == KUidMmfVideoPlayRateControl)
+    {
+      return (MMmfVideoPlayRateControl *)this;
+    } 
+    if (aInterface == KMmfVideoAdvancedSecureOutputUid)
+    {
+      return (MMmfAdvancedVideoSecureOutput *)this;
+    }
+    if (aInterface == KUidMmfVideoResourceManagement)
+    {
+      return (MMmfVideoResourceObserver *)this;
+    } 
+    if (aInterface == KUidMmfPostInitializeRequest)
+    {
+      return (MMmfPostInitializeRequest *)this;
+    }
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:CustomInterface --"), this);
+    return NULL;
+}
+
+void CNGAPostProcHwDevice::BufferAvailable(TInt aBufId, TInt aStatus)
+{ 
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:CNGAPostProcHwDevice::BufferAvailable aStatus = %d aBufId = %d++"), this, aStatus, aBufId);
+    TVideoPicture* pic = NULL;
+    if((aStatus != KErrNone) && (aStatus != KErrOverflow) && (aStatus != KErrNotVisible))
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:BufferAvailable FAILED: aStatus = %d"), this, aStatus);
+		iProxy->MdvppFatalError(this, aStatus);
+	}
+
+	if(aStatus == KErrOverflow)
+	{
+		iOverflowPictureCounter++;
+		PicturesSkipped();
+	}
+    	
+    if (iVBMEnabled)
+    {
+		for(TInt i=0; i < iProcessQ.Count(); i++)
+		{
+			if(iVBMBufferReferenceQ[aBufId] == iProcessQ[i])
+			{
+				pic = iProcessQ[i];
+				iProcessQ.Remove(i);				
+				ReturnPicToDecoder(pic);
+				if (iIsColorConversionNeeded)
+				{
+				    AddPictureToColorConversionQ(pic);
+				}
+				else
+				{
+				    AddPictureToVBMQ(pic);
+				}
+				break;
+			}
+		} 
+	}
+	else
+	{
+	    for(TInt i=0; i < iProcessQ.Count(); i++)
+		{
+			TInt bufId;
+			if (iUsingExternalSurface)
+			{
+				bufId = GetExternalBufferID(iProcessQ[i]);
+			}
+			else
+			{
+				bufId = GetID(iProcessQ[i]);
+			}
+			
+			if (aBufId == bufId)
+			{
+				pic = iProcessQ[i];
+				iProcessQ.Remove(i);
+				ReturnPicToDecoder(pic);
+				break;
+			}
+		} 
+	}
+	
+	if(aStatus == KErrNone)
+	{
+		if (!iKeyFrameMode && iPlayRate>KDefPlayRate)     
+		{   
+		 	if (iSkippedFramesCountingBuffer[iCurrentPosInFramesCountingBuffer]==1)        
+		 	{       
+		 		iSkippedFramesCountingBuffer[iCurrentPosInFramesCountingBuffer] = 0;       
+		 		iSkippedFramesInLast64Frames--;       
+		 	}       
+		 	iCurrentPosInFramesCountingBuffer = ++iCurrentPosInFramesCountingBuffer%64;       
+		} 
+		iPictureCounters.iPicturesDisplayed++;
+		if (iStepFrameCount != 0)
+        {       
+        	iStepFrameCount > 0 ? iStepFrameCount-- : iStepFrameCount++;		            	      
+            if (iStepFrameCount==0 && iFPObserver)        
+            {       
+            	iFPObserver->MmvproStepFrameComplete(pic->iTimestamp);       
+            }       
+        }
+	}
+	
+	if(iPPState == EPlaying)
+	{
+		AttemptToPost();
+	}
+
+	if( iIsInputEnded && (iProcessQ.Count() <= 1)  && (iInputQ.Count() == 0))
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:BufferAvailable() Stream end"), this);
+		iProxy->MdvppStreamEnd();
+	}
+	
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:CNGAPostProcHwDevice::BufferAvailable --"), this);
+}
+
+//=== MMmfVideoBufferManagement ===
+void CNGAPostProcHwDevice::MmvbmSetObserver(MMmfVideoBufferManagementObserver* aObserver)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetObserver() ++"), this);
+
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetObserver FAILED: Unexpected state"), this);
+        iProxy->MdvppFatalError(this, KErrNotReady);
+	}
+
+    iVBMObserver  = aObserver;
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetObserver() --"), this);
+}
+    
+
+void CNGAPostProcHwDevice::MmvbmEnable(TBool aEnable)
+{
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmEnable FAILED: Unexpected state"), this);
+        iProxy->MdvppFatalError(this, KErrNotReady);
+	}
+
+    iVBMEnabled = aEnable;
+}
+    
+void CNGAPostProcHwDevice::MmvbmSetBufferOptionsL(const TBufferOptions& aOptions)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetBufferOptionsL ++"), this);
+
+    if (iPPState != EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetBufferOptionsL FAILED: Unexpected state"), this);
+        User::Leave(KErrNotReady);
+	}
+
+    // why limiting the number of buffers? any particular reason for this?
+    //if (aOptions.iNumInputBuffers > KMaxVBMBuffers || aOptions.iNumInputBuffers <= 1)          //at least two buffers
+    if (aOptions.iNumInputBuffers <= 1)          //at least two buffers
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetBufferOptionsL FAILED: Input buffer count limit"), this);
+        User::Leave(KErrNotSupported);
+	}
+
+    if (aOptions.iNumInputBuffers == 0 
+        || aOptions.iBufferSize.iWidth <= KMinVBMInputWidth 
+        || aOptions.iBufferSize.iHeight <= KMinVBMInputHeight  
+        || aOptions.iBufferSize.iWidth > KMaxVBMInputWidth 
+        || aOptions.iBufferSize.iHeight > KMaxVBMInputHeight)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetBufferOptionsL FAILED: Unexpected buffer size"), this);
+        User::Leave(KErrArgument);
+	}
+
+    iVBMBufferOptions.iNumInputBuffers  = aOptions.iNumInputBuffers;
+    iVBMBufferOptions.iBufferSize       = aOptions.iBufferSize;
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmSetBufferOptionsL --"), this);
+}
+
+void CNGAPostProcHwDevice::MmvbmGetBufferOptions(TBufferOptions& aOptions)
+{
+    if (iPPState == EInitializing)
+    {
+    	aOptions = iVBMBufferOptions;
+    }
+    else
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferOptions FAILED: Unexpected state"), this);
+        iProxy->MdvppFatalError(this, KErrNotReady);
+	}
+}
+    
+TVideoPicture* CNGAPostProcHwDevice::MmvbmGetBufferL(const TSize& aSize)
+    {
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() ++"), this);
+    
+    TInt err = KErrNone;
+    TVideoPicture* lPic = NULL;
+
+    if (iPPState == EInitializing)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() FAILED: Unexpected state"), this);
+        User::Leave(KErrNotReady);
+	  }
+
+    if (aSize.iWidth < KMinVBMInputWidth 
+        || aSize.iHeight < KMinVBMInputHeight
+        || aSize.iWidth > iVBMBufferOptions.iBufferSize.iWidth 
+        || aSize.iHeight > iVBMBufferOptions.iBufferSize.iHeight)
+  	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() FAILED: Unexpected buffer size w=%d h=%d "), this,aSize.iWidth,aSize.iHeight );
+        User::Leave(KErrNotSupported);
+		}
+		
+		if(iVBMBufferReferenceQ.Count() == 0)
+		{
+			iPicSize = aSize;
+			err = SetupSurface();
+			if(err)
+			{
+					PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() Surface Setup Failed %d"), this, err);
+					User::Leave(err);
+			}
+		}
+		
+    if(!iVBMBufferQ.Count())
+    {
+       PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() WARNING: Queue buffer count zero"), this);
+        return NULL;
+    }
+
+    lPic    = iVBMBufferQ[0];
+    iVBMBufferQ.Remove(0);
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() -- %d"), this, lPic);
+    return lPic;
+}
+    
+void CNGAPostProcHwDevice::MmvbmReleaseBuffer(TVideoPicture* aBuffer)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmReleaseBuffer() ++"), this);
+
+    if(!aBuffer)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmReleaseBuffer() FAILED: Invalid buffer ptr"), this);
+    	iProxy->MdvppFatalError(this, KErrArgument);
+	}
+
+    TInt err = iVBMBufferQ.Append(aBuffer);
+    if (err)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmReleaseBuffer() FAILED: Failed to append"), this);
+		iProxy->MdvppFatalError(this, err);
+	}
+
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmReleaseBuffer() --"), this);
+}
+
+//=== MMMFVideoSurfaceSupport ===
+
+void CNGAPostProcHwDevice::MmvssUseSurfaces()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssUseSurfaces() ++"), this);
+	// do nothing
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssUseSurfaces() --"), this);
+}
+
+TInt CNGAPostProcHwDevice::MmvshcCreateSurface(const RSurfaceManager::TSurfaceCreationAttributes& aAttributes, TInt aHandle, TSurfaceId& aSurfaceId)
+    {
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvshcCreateSurface() ++"), this);
+    TInt err(KErrNone);
+    
+    if(!iSurfaceId.IsNull())
+    {
+        PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssCreateSurface Cleaning Surface"), this);
+        
+		if (iVideoSurfaceObserver && iSurfaceCreatedEventPublished)
+		{
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvshcCreateSurface - Telling client to remove old surface"), this);
+			iVideoSurfaceObserver->MmvsoRemoveSurface();
+			iSurfaceCreatedEventPublished = EFalse;
+		}
+		else
+		{
+			// We never told the client about the surface, so we must destroy it ourselves
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface - Destroying old surface"), this);
+			TInt numScreens = iWsSession.NumberOfScreens();
+    		for(TInt i=0;i < numScreens;i++)
+    		{
+    			iWsSession.UnregisterSurface(i, iSurfaceId);
+    		}
+   			iWsSession.Flush();
+			iSurfaceHandler->DestroySurface(iSurfaceId);
+		}
+		//remove any handle to chunk. not needed perhaps
+		iChunk.Close();
+		
+    }
+        
+    // Create the surface handler if it doesn't exist.
+    if (!iSurfaceHandler)
+    {
+        TRAP(err, iSurfaceHandler = CNGAPostProcSurfaceHandler::NewL());
+        if (err != KErrNone)
+        {
+            PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssCreateSurface -- failed to create SurfaceHandler."), this);
+            return err;
+        }
+    }
+         
+    iChunk.SetHandle(aHandle);
+    err = iSurfaceHandler->CreateSurface(aAttributes, aSurfaceId, iChunk);
+    if (err != KErrNone)
+    {
+       PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssCreateSurface -- failed to create surface %d"), this, err);
+       return err;
+    }
+    iSurfaceId = aSurfaceId;
+    iIsExternalChunk = ETrue;
+
+    err = RegisterSurface(iSurfaceId);
+    if (err != KErrNone)
+    {
+       PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssCreateSurface -- failed RegisterSurface %d"), this, err);
+       iSurfaceHandler->DestroySurface(iSurfaceId);
+       iSurfaceId = TSurfaceId::CreateNullId();
+       return err;
+    }
+    
+    err = iSurfaceHandler->SurfaceInfo(iSurfaceId, iInfo);
+    if (err != KErrNone)
+    {
+        PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssCreateSurface -- failed to get Surface info %d"), this, err);
+        return err;
+    }
+
+    if(iAttributes().iPixelFormat == EUidPixelFormatYUV_422Interleaved) 
+        {
+            iVideoFrameBufSize          = iInfo().iSize.iWidth * iInfo().iSize.iHeight * 2;
+        }
+        else
+        {//EStUidPixelFormatYUV_420MB
+        // EUidPixelFormatYUV_420Planar            
+            iVideoFrameBufSize          =  iInfo().iSize.iWidth * iInfo().iSize.iHeight * 3/2;
+        }
+    
+     
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvshcCreateSurface err=%d"), this, err);
+    return err;
+    }
+
+void CNGAPostProcHwDevice::MmvssSetObserver(MMMFVideoSurfaceObserver& aObserver)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSetObserver() ++"), this);
+	iVideoSurfaceObserver = &aObserver;
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSetObserver() --"), this);
+}
+
+void CNGAPostProcHwDevice::MmvssGetSurfaceParametersL(TSurfaceId& aSurfaceId, 
+						TRect& aCropRect, TVideoAspectRatio& aPixelAspectRatio)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssGetSurfaceParametersL() ++"), this);
+
+	iSurfaceHandler->SurfaceInfo(iSurfaceId, iInfo);
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssGetSurfaceParametersL() \
+		surfaceWidth = %d surfaceHeight = %d SurfaceId = 0x%x --"), 
+		this, iInfo().iSize.iWidth, iInfo().iSize.iHeight, iSurfaceId);
+	aSurfaceId = iSurfaceId;
+		aCropRect = TRect(0, 0, iInfo().iSize.iWidth, iInfo().iSize.iHeight);
+		if((iPicSize.iWidth > 0) && (iPicSize.iHeight > 0))
+		{
+			aCropRect.Intersection( iPicSize);
+		}
+	aPixelAspectRatio = TVideoAspectRatio(iAspectRatioNum,iAspectRatioDenom);
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssGetSurfaceParametersL()  \
+		cropRectWidth = %d cropRectHeight = %d"), this, aCropRect.Width(), aCropRect.Height());
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssGetSurfaceParametersL()  \
+		PAR Num = %d PAR Denom = %d"), this, aPixelAspectRatio.iNumerator, aPixelAspectRatio.iDenominator);
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssGetSurfaceParametersL() --"), this);
+}
+
+void CNGAPostProcHwDevice::MmvssSurfaceRemovedL(const TSurfaceId& aSurfaceId)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSurfaceRemovedL()++"), this);
+	if(!aSurfaceId.IsNull())
+	{
+	    if(iSurfaceId == aSurfaceId)
+        {//closing down top surface....current surface.
+            if(iSessionManager)
+            {
+                iSessionManager->CancelNotifiers();
+            }
+	    }
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSurfaceRemovedL(): UnregisterSurface ID = 0x%x"), this, aSurfaceId );
+		TInt numScreens = iWsSession.NumberOfScreens();
+		for(TInt i=0;i < numScreens;i++)
+		{
+			iWsSession.UnregisterSurface(i, aSurfaceId);
+		}
+		iWsSession.Flush();
+		iSurfaceHandler->DestroySurface(aSurfaceId);
+		if(iSurfaceId == aSurfaceId)
+		{
+			iSurfaceCreatedEventPublished = EFalse;
+			iSurfaceId = TSurfaceId::CreateNullId();
+			 if(!iIsExternalChunk)
+			 {
+				iChunk.Close();
+			 }
+		}
+	}
+
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSurfaceRemovedL() --"), this);
+}
+
+// === MMmfVideoPropertiesObserver ===
+    
+void CNGAPostProcHwDevice::MmvpoUpdateVideoProperties(const TYuvFormat& aYuvFormat, const TSize& aPictureSize)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvpoUpdateVideoProperties ++"), this);
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvpoUpdateVideoProperties PAR \
+		iAspectRatioNum = %d, iAspectRatioDenom = %d"), this,
+					 aYuvFormat.iAspectRatioNum,aYuvFormat.iAspectRatioDenom);
+	iPicSize = aPictureSize;
+	iAspectRatioNum = aYuvFormat.iAspectRatioNum;
+	iAspectRatioDenom = aYuvFormat.iAspectRatioDenom;
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvpoUpdateVideoProperties Picture Size \
+		iWidth = %d, iHeight = %d, iSurfaceCreatedEventPublished = %d"), 
+		this, iPicSize.iWidth,iPicSize.iHeight, iSurfaceCreatedEventPublished?1:0);
+			 
+	if(iVPObserver)
+	{
+		iVPObserver->MmvpoUpdateVideoProperties(aYuvFormat, aPictureSize);
+	} 
+	if(iVideoSurfaceObserver && iSurfaceCreatedEventPublished)
+	{
+    	iVideoSurfaceObserver->MmvsoSurfaceParametersChanged(); 
+    }
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvpoUpdateVideoProperties --"), this);
+}
+
+// === MMmfVideoResourceObserver ===
+
+void CNGAPostProcHwDevice::MmvroResourcesLost(TUid )
+{
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost ++"), this);
+    if(!iResourceLost)
+    {
+		iResourceLost = ETrue;
+		iRedrawDone = EFalse;
+		Pause();
+		ReleaseInputQ();
+		iSessionManager->CancelNotifiers();
+		ReleaseProcessQ();
+		if(iVideoSurfaceObserver && iSurfaceCreatedEventPublished)
+		{
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost - Telling client to remove surface"), this);
+			iVideoSurfaceObserver->MmvsoRemoveSurface();
+			iSurfaceCreatedEventPublished = EFalse;
+		}
+	}
+	else if(iResourceLost && iRedrawDone)
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost ResourceLost happening \
+					while Postprocessor is already in ResourceLoss state"), 
+	   				this);
+		iProxy->MdvppFatalError(this, KErrHardwareNotAvailable);	   				
+	    return;		
+	}
+	else
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost Ignoring the \
+					duplicate ResourceLoss call"), 
+	   				this);
+	}
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost --"), this);
+}
+
+// === MMmfVideoPropertiesNotifier ===
+    
+void CNGAPostProcHwDevice::MmvpnSetObserver(MMmfVideoPropertiesObserver* aObserver)
+{
+	PP_DEBUG(_L("ppHwDev[%x]::MmvpnSetObserver ++"), this);
+	iVPObserver = aObserver;
+	PP_DEBUG(_L("ppHwDev[%x]::MmvpnSetObserver --"), this);
+}
+
+void CNGAPostProcHwDevice::MmvroResourcesRestored(TUid )
+{
+   	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvroResourcesRestored ++"), this);
+	iFirstPictureUpdated = EFalse;
+	iResourceLost = EFalse;
+   	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvroResourcesRestored state=%d --"), 
+   			this, iPPState);
+}
+
+void CNGAPostProcHwDevice::MmvshcSetSurfaceHandle(const TSurfaceId &aSurfaceID)
+{
+    
+    SetupExternalSurface(aSurfaceID);
+    
+}
+
+void CNGAPostProcHwDevice::MmvshcRedrawBufferToSurface(TPtrC8& aRedrawBuffer)
+{
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface ++"), this);
+	
+    TUint8*         lPtr;
+    TInt 			offset;
+
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface -- Creating %d x %d surface"), this, iPicSize.iWidth, iPicSize.iHeight);
+
+   	TInt err = KErrNone;
+	SetSurfaceAttributes(iPicSize, 1); 
+	
+  	err = iSurfaceHandler->CreateSurface(iAttributes, iSurfaceId);
+  	if (err != KErrNone)
+	{
+	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvshcRedrawBufferToSurface -- failed to create Surface %d"), 
+	   				this, err);
+		iProxy->MdvppFatalError(this, err);	   				
+	    return;
+	}
+
+	err = iSurfaceHandler->SurfaceInfo(iSurfaceId, iInfo);
+	if (err != KErrNone)
+	{
+	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvshcRedrawBufferToSurface -- failed to get Surface info %d"), 
+	   				this, err);
+	   	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   	iSurfaceId = TSurfaceId::CreateNullId();
+		iProxy->MdvppFatalError(this, err);	   				
+	    return;
+	}
+
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvshcRedrawBufferToSurface() \
+		surfaceWidth = %d surfaceHeight = %d surfaceStride = %d"), this, iInfo().iSize.iWidth, iInfo().iSize.iHeight, iInfo().iStride);
+
+	TInt redrawBufferSize = aRedrawBuffer.Size();
+	TInt surfaceSize = iInfo().iStride * iInfo().iSize.iHeight;
+
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface RedrawBuffer size= %d Surface size = %d"), this, redrawBufferSize, surfaceSize);
+
+	// Check whether redraw buffer will fit onto the surface.
+	// If this check fails then we won't raise a fatal error - We just won't create the redraw surface
+	if (redrawBufferSize > surfaceSize)
+	{
+    	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface Redraw buffer size larger than surface size"), this);
+    	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   	iSurfaceId = TSurfaceId::CreateNullId();
+    	return;
+	}
+
+	err = iSurfaceHandler->MapSurface(iSurfaceId, iChunk);
+	if (err != KErrNone)
+	{
+	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvshcRedrawBufferToSurface -- failed to map Surface %d"), 
+	   				this, err);
+	   	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   	iSurfaceId = TSurfaceId::CreateNullId();
+		iProxy->MdvppFatalError(this, err);	   				
+	    return;
+	}
+	iIsExternalChunk = EFalse;
+    if((err = iSurfaceHandler->GetBufferOffset(iSurfaceId, 0, offset)) != KErrNone)
+    {
+    	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface offset query failed %d"), this, err);
+    	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   	iSurfaceId = TSurfaceId::CreateNullId();
+		iChunk.Close();
+    	iProxy->MdvppFatalError(this, err);
+    	return;
+    }
+
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface offset = %d"), this, offset);
+
+	lPtr = reinterpret_cast<TUint8*>(iChunk.Base() + offset);
+	memcpy((TAny *)lPtr, (TAny *)aRedrawBuffer.Ptr(), redrawBufferSize);
+
+	iRedrawSurfaceInUse = ETrue;
+
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface(): New surface = 0x%x"), this, iSurfaceId);
+
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface error = %d --"), this, err);
+}
+
+TInt CNGAPostProcHwDevice::SetupExternalSurface(const TSurfaceId &aSurfaceID)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface(): aSurfaceID = 0x%x"), this, aSurfaceID );
+
+    TInt err = KErrNone;
+    
+    if(!iSurfaceId.IsNull())
+    {
+		if (iVideoSurfaceObserver && iSurfaceCreatedEventPublished)
+		{
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface - Telling client to remove old surface"), this);
+			iVideoSurfaceObserver->MmvsoRemoveSurface();
+			iSurfaceCreatedEventPublished = EFalse;
+		}
+		else
+		{
+			// We never told the client about the surface, so we must destroy it ourselves
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface - Destroying old surface"), this);
+			TInt numScreens = iWsSession.NumberOfScreens();
+    		for(TInt i=0;i < numScreens;i++)
+    		{
+    			iWsSession.UnregisterSurface(i, iSurfaceId);
+    		}
+   			iWsSession.Flush();
+			iSurfaceHandler->DestroySurface(iSurfaceId);
+		}
+
+		iChunk.Close();
+	}
+    
+    iSurfaceId            = aSurfaceID;
+    iUsingExternalSurface = ETrue;
+    iRedrawSurfaceInUse = EFalse;
+
+    // Create the surface handler if it doesn't exist.
+    if (!iSurfaceHandler)
+    {
+        TRAP(err, iSurfaceHandler = CNGAPostProcSurfaceHandler::NewL());
+        if (err != KErrNone)
+        {
+           PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface -- failed to create SurfaceHandler."), this);
+            return err;
+        }
+    }
+    
+    err = iSurfaceHandler->OpenSurface(iSurfaceId);
+    if (err != KErrNone)
+	{
+	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface -- failed OpenSurface %d"), 
+	   				this, err);
+	    return err;
+	}
+    err = AddHints();
+    if (err != KErrNone)
+    {
+        PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface -- failed to AddHints %d"), 
+                    this, err);
+        return err;
+    }
+	err = RegisterSurface(iSurfaceId);
+	if (err != KErrNone)
+	{
+	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface -- failed RegisterSurface %d"), 
+	   				this, err);
+	   	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   	iSurfaceId = TSurfaceId::CreateNullId();
+	    return err;
+	}
+
+    err = iSurfaceHandler->SurfaceInfo(iSurfaceId, iInfo);
+    if (err != KErrNone)
+    {
+        PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface -- failed to get Surface info %d"), 
+                     this, err);
+        return err;
+    }
+ 
+  PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface err=%d"), this, err);
+   return err;
+}
+
+//=== Internal ===
+TVideoPicture* CNGAPostProcHwDevice::CreateBuffersL(TInt aBufId)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::CreateBuffersL ++"), this);
+	
+	TVideoPicture*          lVideoPicture = NULL;
+    TUint8*                 lPtr;
+    TPtr8*                  lTemp;
+    TInt 					offset;
+    
+	lVideoPicture = new (ELeave) TVideoPicture;
+    CleanupStack::PushL(lVideoPicture);
+    if(TInt err = iSurfaceHandler->GetBufferOffset(iSurfaceId, aBufId, offset) != KErrNone)
+    {
+    	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::CreateBuffersL offset query failed %d"), this, err);
+    }
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::CreateBuffersL offset = %d id =%d --"), this, offset, aBufId);
+    
+	lPtr = reinterpret_cast<TUint8*>(iChunk.Base() + offset);
+
+    lTemp = new (ELeave) TPtr8(lPtr, 0, (iVideoFrameBufSize ));
+    CleanupStack::PushL(lTemp);
+
+    lVideoPicture->iData.iRawData   = lTemp;
+    lVideoPicture->iHeader = NULL ;
+    lVideoPicture->iLayerBitRates = NULL ;
+    
+    CleanupStack::Pop(2);
+    
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::CreateVBMBuffersL --"), this);
+    return lVideoPicture;
+}
+
+void CNGAPostProcHwDevice::CreateVBMBuffersL()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::CreateVBMBuffersL ++"), this);
+    
+    TInt err = KErrNone;
+    TVideoPicture* pic = NULL;
+    iVBMBufferReferenceQ.Reset();
+    iVBMBufferQ.Reset();
+    iColorConversionQ.Reset();
+
+    for(TInt i = 0; i < iVBMBufferOptions.iNumInputBuffers; i++)
+    {
+        TRAP(err, pic = CreateBuffersL(i));
+	    	if (err != KErrNone)
+	    	{
+	    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to create VBM buffer %d"), this, err);
+	    	    User::Leave(err);
+	    	}
+
+        // This will hold the references which will be used in destructor
+        User::LeaveIfError(iVBMBufferReferenceQ.Append(pic));
+        User::LeaveIfError(iVBMBufferQ.Append(pic));
+    }
+    if(iIsColorConversionNeeded)
+    {
+		    for(TInt i = iVBMBufferOptions.iNumInputBuffers ; 
+		    				 i < (iVBMBufferOptions.iNumInputBuffers + KColorConversionBuffers ); i++)
+		    {
+		        TRAP(err, pic = CreateBuffersL(i));
+			    	if (err != KErrNone)
+			    	{
+			    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to create VBM buffer %d"), this, err);
+			    	    User::Leave(err);
+			    	}
+		
+		        // This will hold the references which will be used in destructor
+		        User::LeaveIfError(iVBMBufferReferenceQ.Append(pic));
+		        User::LeaveIfError(iColorConversionQ.Append(pic));
+		    }
+		}
+	    
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::CreateVBMBuffersL --"), this);
+}
+
+void CNGAPostProcHwDevice::ReturnPicToDecoder(TVideoPicture* aPic)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReturnPicToDecoder ++"), this);
+	if (aPic == NULL)
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseInputPicture FAILED: Invalid pic ptr."), this);
+		return;
+	}
+	
+   	if (iInputDecoderDevice)
+    {
+       PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseInputPicture .. before return picture. 2"), this);
+        iInputDecoderDevice->ReturnPicture(aPic);
+    }
+	
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReturnPicToDecoder --"), this);
+}
+
+TInt CNGAPostProcHwDevice::AttemptToPost()
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AttemptToPost ++ Q:%d"), this, iInputQ.Count());
+   if (iPPState == EPaused)
+   {
+        return KErrNone;
+   }
+
+    TInt err = KErrNotReady;
+    TInt count = iInputQ.Count();
+    TBool bDone = EFalse;
+    TVideoPicture* pic = PeekQ();   		
+  	while(pic && !bDone)
+  	{
+	    if(!IsGceReady())
+		{  
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AttemptToPost GCE not ready"), this );
+			return err; //no need to catch this error
+		}
+		TInt64 delta = 0;
+		TTimeToPost	timeToPost = (TTimeToPost)IsTimeToPost(pic, delta);
+		switch(timeToPost)
+		{
+			case EDelayIt:
+			{
+				iPostingTimer->Cancel();
+				SetTimer(delta);
+				bDone = ETrue;
+			}
+			break;
+			case EPostIt:
+			{
+				RemoveFromQ(); // remove the pic that was returned by PeekQ				
+				if(iIsColorConversionNeeded)
+				{
+				    TVideoPicture* ccPic;
+    				ccPic = DoColorConvert(pic); // output will be in ccPic
+    				pic = ccPic;
+			    }
+				
+                #ifdef _DUMP_YUV_FRAMES
+                    captureYuv(pic);
+                #endif
+				TInt err = iSessionManager->PostPicture(iSurfaceId, GetID(pic), ETrue); 
+				if(err == KErrNone)
+				{
+				    iProcessQ.Append(pic);
+					iCurrentPlaybackPosition = pic->iTimestamp;
+					if(!iFirstPictureUpdated)
+					{
+						iFirstPictureUpdated = ETrue;
+						if(!iSurfaceCreatedEventPublished)
+                    	{
+                        	PublishSurfaceCreated();
+                    	}
+					}
+				}
+				else
+				{
+					ReleasePicture(pic);
+				}
+										 					
+				
+			}	// end of postit
+			break;
+			case ESkipIt: 
+			{
+				RemoveFromQ();
+				ReleasePicture(pic);
+				PicturesSkipped();				
+			}
+			break;
+		} // end of switch
+		
+		// get the next picture
+		pic = PeekQ();	
+    } // end of while
+    
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AttemptToPost --"), this);
+ 	return err;
+}
+
+TInt CNGAPostProcHwDevice::IsTimeToPost(TVideoPicture* frame, TInt64& delta)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:IsTimeToPost ++"), this);
+
+    if (!frame)
+    {
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:IsTimeToPost FAILED: Invalid frame ptr."), this);
+		return KErrGeneral;
+	}
+
+    TInt resp = EPostIt;
+    // Frame presentation time
+    TInt64 uPresTime = frame->iTimestamp.Int64();
+      
+    // Check if this is an out of order frame in case of forward playback
+    if((iCurrentPlaybackPosition.Int64() > uPresTime) && (iPlayRate > 0))    
+    {      
+         PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:IsTimeToPost : Out of order frame (forward playback) Tfm=%d"), this,(TInt)uPresTime);
+         resp = ESkipIt;  //drop      
+    }      // Check if this is an out of order frame in case of backward playback
+    else if((iCurrentPlaybackPosition.Int64() < uPresTime) && (iPlayRate < 0))    
+    {      
+        PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:IsTimeToPost : Out of order frame (backward playback) Tfm=%d"), this,(TInt)uPresTime);
+        resp = ESkipIt;  //drop      
+    }
+    else if (iClockSource)
+    {
+        // The time to sync with.
+        TInt64 uSyncTime = iClockSource->Time().Int64();
+        
+        delta = uPresTime - uSyncTime;
+        if (( delta > KRenderAhead ) &&  (iPlayRate > 0))	// Delay condition not checked for 
+        {													// backward playback
+        	resp = EDelayIt;  //wait
+        }
+        else if ( (delta < (-KMaxRenderDelay) && (iPlayRate > 0))
+          		||  ((delta > KMaxRenderDelay) && (iPlayRate < 0)))
+        {
+            resp = ESkipIt;  //drop
+        }
+       PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:IsTimeToPost .. Tfm=%d, Tcs=%d, delta=%d"), this, (TInt)uPresTime, (TInt)uSyncTime, (TInt)delta);
+    }       
+   
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:IsTimeToPost -- %d BufID = %d"), this, resp, GetID(frame));
+    return resp;
+}
+
+void CNGAPostProcHwDevice::ReleaseInputQ()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseInputQ ++ Q = %d"), this, iInputQ.Count());
+    while (iInputQ.Count()>0)
+    {
+    	ReleasePicture(iInputQ[0]);
+        iInputQ.Remove(0);
+    }
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseInputQ --"), this);
+}
+
+void CNGAPostProcHwDevice::ReleaseProcessQ()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseProcessQ ++ Q = %d"), this, iProcessQ.Count() );
+	TVideoPicture* pic = NULL;
+	
+    while (iProcessQ.Count()>0)
+    {
+		pic = iProcessQ[0];
+		iProcessQ.Remove(0);
+		ReturnPicToDecoder(pic);
+    }
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseProcessQ --"), this);
+}
+
+void CNGAPostProcHwDevice::ReleasePicture(TVideoPicture *pic)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleasePicture ++"), this);
+	if (pic == NULL)
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseInputPicture FAILED: Invalid pic ptr."), this);
+		return;
+	}
+	
+   	if (iInputDecoderDevice)
+    {
+       PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleaseInputPicture .. before return picture. 2"), this);
+        iInputDecoderDevice->ReturnPicture(pic);
+    }
+	if (iVBMEnabled)
+    {
+        iVBMBufferQ.Append(pic);
+
+        if ( !iIsInputEnded && iPPState != EStopped )
+        {
+            iVBMObserver->MmvbmoNewBuffers();
+        }
+	}
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ReleasePicture --"), this);
+}
+
+void CNGAPostProcHwDevice::PublishSurfaceCreated()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:PublishSurfaceCreated ++"), this);   
+	if(iVideoSurfaceObserver)
+	{
+		iVideoSurfaceObserver->MmvsoSurfaceCreated();
+		iSurfaceCreatedEventPublished = ETrue;
+	}
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:PublishSurfaceCreated --"), this);
+}
+
+TInt CNGAPostProcHwDevice::SetupSurface()
+{
+	TInt err = KErrNone;
+	if(iVBMEnabled && iVBMObserver)
+    {
+    	SetSurfaceAttributes(iVBMBufferOptions.iBufferSize, iVBMBufferOptions.iNumInputBuffers);
+    	
+	  	err = iSurfaceHandler->CreateSurface(iAttributes, iSurfaceId);
+	  	if (err != KErrNone)
+    	{
+    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to create Surface %d"), this, err);
+    	    return err;
+    	}
+    	err = iSurfaceHandler->MapSurface(iSurfaceId, iChunk);
+    	if (err != KErrNone)
+    	{
+    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to map Surface %d"), this, err);
+    	  	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   		iSurfaceId = TSurfaceId::CreateNullId();
+    	    return err;
+    	}
+    	err = iSurfaceHandler->SurfaceInfo(iSurfaceId, iInfo);
+    	if (err != KErrNone)
+    	{
+    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to get Surface info %d"), this, err);
+    	   	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   		iSurfaceId = TSurfaceId::CreateNullId();
+    	    return err;
+    	}
+    	TRAP(err, CreateVBMBuffersL());
+    	if (err != KErrNone)
+    	{
+    	   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to create VBM buffer %d"), this, err);
+    	   	iSurfaceHandler->DestroySurface(iSurfaceId);
+	   		iSurfaceId = TSurfaceId::CreateNullId();
+    	    return err;
+    	}
+        err = AddHints();
+        if (err != KErrNone)
+        {
+            PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to AddHints %d"), this, err);
+            return err;
+        }
+        err = RegisterSurface(iSurfaceId);
+        if (err != KErrNone)
+        {
+            PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Initialize -- failed to RegisterSurface %d"), this, err);
+            iSurfaceHandler->DestroySurface(iSurfaceId);
+            iSurfaceId = TSurfaceId::CreateNullId();
+            return err;
+        }
+        
+    }
+    return err;
+} 
+
+void CNGAPostProcHwDevice::SetSurfaceAttributes(const TSize& aSize, TInt aNumBuf)
+{
+	iAttributes().iSize                   = aSize; // size of the video frame
+    iAttributes().iBuffers            	  = aNumBuf;
+    
+    /* The stride needs to be calculated for the surface manager to know
+    how much memory to allocate */
+    
+    if(iAttributes().iPixelFormat == EUidPixelFormatYUV_420Planar)
+    	{
+    		iAttributes().iStride       = aSize.iWidth * 3/2;
+    		iVideoFrameBufSize			= aSize.iWidth * aSize.iHeight * 3/2;
+    	}
+    	else
+    	{
+    		iAttributes().iStride       = aSize.iWidth * 2;
+    		iVideoFrameBufSize			= aSize.iWidth * aSize.iHeight * 2;
+    	}
+    		
+    if(iIsColorConversionNeeded)
+    {
+    	iAttributes().iBuffers            = aNumBuf + KColorConversionBuffers;
+    }
+    else
+    {
+    	iAttributes().iBuffers            = aNumBuf;	
+    }
+    
+    iAttributes().iOffsetToFirstBuffer    = 0;
+#if defined __WINSCW__ 
+    iAttributes().iAlignment              = 4;
+#else //on hw, its always better to have page aligned chunks
+    iAttributes().iAlignment              = -1;
+#endif
+    iAttributes().iContiguous             = ETrue;
+    iAttributes().iHintCount              = 0;
+    iAttributes().iMappable               = ETrue;
+}
+
+TInt CNGAPostProcHwDevice::GetID(TVideoPicture *aPicture)
+{
+    if (iUsingExternalSurface)
+    {
+	    return GetExternalBufferID(aPicture);
+    }
+    else
+    {
+        TUint8* aPtr = (TUint8*) aPicture->iData.iRawData->Ptr();
+        return( (TInt) ((aPtr - iChunk.Base() - iAttributes().iOffsetToFirstBuffer) / 
+			(iVideoFrameBufSize )));
+    }
+}
+
+TInt CNGAPostProcHwDevice::GetExternalBufferID(TVideoPicture *aPicture)
+{
+    // currently type cast the pointer as buffer ID.
+    // FIXME once the new data structure is available.
+    return( (TInt) aPicture->iData.iRawData->Ptr());
+}
+
+TInt CNGAPostProcHwDevice::RegisterSurface(const TSurfaceId& aSurfaceId)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:RegisterSurface(): RegisterSurface ID = 0x%x"), this, aSurfaceId);
+	TInt err = KErrNone;
+	TInt numScreens = iWsSession.NumberOfScreens();
+	for(TInt i=0; (i < numScreens && err == KErrNone); i++)
+	{
+		err = iWsSession.RegisterSurface(i, aSurfaceId);
+	}	
+	return(err);
+}
+
+TInt CNGAPostProcHwDevice::IsGceReady()
+{
+    if(iProcessQ.Count() >= KMaxBuffersGceCanHold)
+    {
+    		return EFalse;
+    }
+    return ETrue;
+}
+
+void CNGAPostProcHwDevice::SetTimer(TInt64 aDelta)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetTimer .. aDelta=%d"), this, (TInt)aDelta);
+	if(aDelta <= KRenderAhead)
+	{
+		if(aDelta < 0)
+		{
+			iPostingTimer->After(aDelta * -1);
+		}
+		else
+		{
+			iPostingTimer->After((aDelta - KRenderAhead) * -1);
+		}
+	}
+	else
+	{
+		iPostingTimer->After(aDelta - KRenderAhead - KPostingOfset);
+	}
+}
+//
+// Convert YUV420 to YUV422InterLeaved.
+//
+TInt CNGAPostProcHwDevice::ConvertPostProcBuffer(TVideoPicture* pSrc, TVideoPicture* pDest)
+{
+    PP_DEBUG(_L("CMdfPostingSurfaceProxy::ConvertPostProcBuffer ++"));
+    TInt err = KErrNone;
+    if (!pDest && !pSrc)
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ConvertPostProcBuffer FAILED: Invalid pic pSrc %x pDest %x."), this, pSrc, pDest);
+		return KErrArgument;
+	}
+    
+    // --- Prepare wrappers ---
+    tBaseVideoFrame tFrame420, tFrame422;
+    TInt    frameSize = pSrc->iData.iDataSize.iWidth * pSrc->iData.iDataSize.iHeight;
+
+   PP_DEBUG(_L("CMdfPostingSurfaceProxy::ConvertPostProcBuffer .. w=%d, h=%d"), pSrc->iData.iDataSize.iWidth, pSrc->iData.iDataSize.iHeight);
+
+    tFrame420.width = pSrc->iData.iDataSize.iWidth;
+    tFrame420.height= pSrc->iData.iDataSize.iHeight;
+    tFrame420.lum   = (TUint8*)pSrc->iData.iRawData->Ptr();
+    tFrame420.cb    = (TUint8*)tFrame420.lum + frameSize;
+    tFrame420.cr    = (TUint8*)tFrame420.lum + (frameSize*5)/4;
+    
+    tFrame422.width = pSrc->iData.iDataSize.iWidth;
+    tFrame422.height= pSrc->iData.iDataSize.iHeight;
+    tFrame422.lum   = (TUint8*)pDest->iData.iRawData->Ptr();
+    tFrame422.cb    = 0;
+    tFrame422.cr    = 0;
+    
+    // --- Convertion to posting buffer ---
+    TInt stride     = pSrc->iData.iDataSize.iWidth * 2;
+    EBufferLayout422 layout = YUV422INT_BE;
+        
+    err = gColorConvYUVtoYUV422Int(&tFrame420, &tFrame422, layout, stride);
+    if(err != KErrNone)
+    {
+    		PP_DEBUG(_L("CNGAPostProcHwDevice::ConvertPostProcBuffer .. err= %d."), err);
+    }
+	return err;
+}   
+
+void CNGAPostProcHwDevice::AddPictureToVBMQ(TVideoPicture *pic)
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AddPictureToVBMQ ++"), this);
+    iVBMBufferQ.Append(pic);
+
+    if ( !iIsInputEnded && iPPState != EStopped )
+    {
+        iVBMObserver->MmvbmoNewBuffers();
+    }
+	
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AddPictureToVBMQ --"), this);
+}
+
+void CNGAPostProcHwDevice::AddPictureToColorConversionQ(TVideoPicture *pic)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AddPictureToColorConversionQ ++"), this);
+    iColorConversionQ.Append(pic);
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AddPictureToColorConversionQ --"), this);
+}
+
+#ifdef _DUMP_YUV_FRAMES
+void CNGAPostProcHwDevice::captureYuv(TVideoPicture* aPicture)
+{
+	char buf[128];              
+	sprintf(buf, "c:\\fb%d.yuv", count++);          
+	FILE *fp = ::fopen(buf, "w");
+	TInt size = aPicture->iData.iRawData->Size();
+	//{FILE* f1 = fopen(MY_LOG_FILE_NAME, "a+"));if(f1){fprintf(f1, "Size  %d \n"), size );fclose(f1); }}
+
+	::fwrite(aPicture->iData.iRawData->Ptr(), 1, size, fp);
+	::fclose(fp);    	
+}
+#endif
+
+void CNGAPostProcHwDevice::ResetCountingBuffer()
+{       
+	memset(iSkippedFramesCountingBuffer,0,sizeof(iSkippedFramesCountingBuffer));
+    iSkippedFramesInLast64Frames = 0;       
+    iCurrentPosInFramesCountingBuffer = 0;       
+} 
+
+void CNGAPostProcHwDevice::PicturesSkipped()
+{       
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:PicturesSkipped ++"), this);
+	iPictureCounters.iPicturesSkipped++;
+	if (!iKeyFrameMode && iPlayRate>KDefPlayRate)
+    {       
+    	if (iSkippedFramesCountingBuffer[iCurrentPosInFramesCountingBuffer]==0)        
+        {       
+        	iSkippedFramesCountingBuffer[iCurrentPosInFramesCountingBuffer] = 1;       
+            iSkippedFramesInLast64Frames++;       
+            if (iSkippedFramesInLast64Frames>KMaxAllowedSkipInNFrames && iFPObserver )       
+            {       
+            	iFPObserver->MmvproKeyFrameModeRequest();       
+                iKeyFrameMode=ETrue;       
+                ResetCountingBuffer();       
+            }       
+        }       
+        iCurrentPosInFramesCountingBuffer = ++iCurrentPosInFramesCountingBuffer%64;       
+    }
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:PicturesSkipped --"), this);   
+}
+
+TVideoPicture* CNGAPostProcHwDevice::DoColorConvert(TVideoPicture* aPicture)
+{
+    TVideoPicture *pOutPicture  = aPicture;
+    					    		
+	if(iColorConversionQ.Count())
+    {
+	    pOutPicture    = iColorConversionQ[0];
+	    iColorConversionQ.Remove(0);
+	    ConvertPostProcBuffer(aPicture, pOutPicture);
+	   	pOutPicture->iTimestamp = aPicture->iTimestamp;
+	    ReleasePicture(aPicture);    	    
+    }				    
+    else
+    {
+       PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePictureL() FAILED: color conversion"), this);
+    }
+
+	return pOutPicture;
+}
+
+TInt CNGAPostProcHwDevice::AddToQ(TVideoPicture* aPicture)
+{
+	TVideoPicture* pic = aPicture;
+	TInt pos = -1;
+	if(iInputQ.Count() == 0)
+	{
+		iInputQ.Append(pic);
+	}
+	else
+	{
+		pos = iInputQ.Count()-1;
+		for(; pos >= 0; pos--)
+		{
+			if(pic->iTimestamp.Int64() > iInputQ[pos]->iTimestamp.Int64())
+			{
+				break;
+			}
+		} 
+		if(iInputQ.Count() == pos+1)
+		{
+			iInputQ.Append(pic);
+		}
+		else
+		{
+			iInputQ.Insert(pic, pos+1);
+		}
+	}
+	return pos+1;
+}
+
+void CNGAPostProcHwDevice::RemoveFromQ()
+{
+	if(iInputQ.Count())
+	{
+		if(iPlayRate > 0)
+		{
+			iInputQ.Remove(0);
+		}
+		else
+		{
+			iInputQ.Remove(iInputQ.Count()-1);
+		}
+	}
+}
+
+TVideoPicture* CNGAPostProcHwDevice::PeekQ()
+{	
+	TVideoPicture *pic = NULL;
+	if(iInputQ.Count())
+	{
+		if(iPlayRate > 0)
+		{			
+			pic = iInputQ[0];
+		}
+		else
+		{			
+			pic = iInputQ[iInputQ.Count()-1];
+		}	
+	}
+	return pic;
+}
+
+TInt CNGAPostProcHwDevice::AddHints()
+{
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AddHints iSurfaceMask 0x%08x ++"), this, iSurfaceMask);
+   TInt err = KErrNone;
+   iHint.Set(iSurfaceKey,iSurfaceMask,ETrue);
+   err = iSurfaceHandler->AddSurfaceHint(iSurfaceId,iHint);
+   if(err == KErrAlreadyExists)
+   {
+		err = KErrNone;
+		err = iSurfaceHandler->SetSurfaceHint(iSurfaceId,iHint);
+   }
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AddHints. err = %d --"), this,err);
+   iHint.iKey.iUid = surfaceHints::KSurfaceContent;
+   iHint.iValue = surfaceHints::EVideoPlayback;
+   iHint.iMutable = ETrue;
+   err = iSurfaceHandler->AddSurfaceHint(iSurfaceId,iHint);
+   if(err == KErrAlreadyExists)
+   {
+		err = KErrNone;
+		err = iSurfaceHandler->SetSurfaceHint(iSurfaceId,iHint);
+   }
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:AddHints. err = %d --"), this,err);
+   return err;
+}
+
+TInt CNGAPostProcHwDevice::ColorConvert(tBaseVideoFrame* aInputFrame, TUint8* aDestPtr, tWndParam* aInputCropWindow, tWndParam* aOutputCropWindow)
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ColorConvert ++"), this);
+	__ASSERT_ALWAYS(aDestPtr, User::Invariant());
+	TInt				lError = E_SUCCESS;
+	TInt				err = KErrNone;
+	
+	err = SetSourceFormat();
+	if(err == KErrNone)
+	{
+    	err = SetSourceRange();
+    	if(err == KErrNone)
+    	{
+						
+			lError = Emz_VDec_gColorConv_YUVtoRGB(aInputFrame,aDestPtr, 
+						aInputCropWindow, aOutputCropWindow, iSourceFormat,
+						EBitmapColor16MU, iSourceRange);
+
+			if(lError)
+			{
+				if(lError == E_OUT_OF_MEMORY)
+					{
+					err = KErrNoMemory;
+					}
+				else if(lError == E_FAILURE)
+					{
+					err = KErrNotSupported;
+					}
+				else
+					{
+					err = KErrGeneral;
+					}
+			}
+		}
+	}
+	
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:ColorConvert --"), this);
+	return err;
+}
+
+TInt CNGAPostProcHwDevice::SetSourceFormat()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetSourceFormatL ++"), this);
+	TInt err = KErrNone;
+	switch (iVideoFormat.iYuvFormat.iPattern)
+	{
+	    case EYuv420Chroma1:
+    		iSourceFormat = EYuv420Chroma1_Planar;
+    		break;
+        case EYuv420Chroma2:
+    		iSourceFormat = EYuv420Chroma2_Planar;
+    		break;
+        case EYuv420Chroma3:
+    		iSourceFormat = EYuv420Chroma3_Planar;
+    		break;
+	    case EYuv422Chroma1:
+			if( iVideoFormat.iYuvFormat.iDataLayout == EYuvDataInterleavedLE)
+    			iSourceFormat = EYuv422Chroma1_LE;
+	    	else if( iVideoFormat.iYuvFormat.iDataLayout == EYuvDataInterleavedBE )
+				iSourceFormat = EYuv422Chroma1_BE;
+			else
+			    err = KErrArgument;
+			break;
+    	case EYuv422Chroma2:
+    		if( iVideoFormat.iYuvFormat.iDataLayout == EYuvDataInterleavedLE)
+	    		iSourceFormat = EYuv422Chroma2_LE;
+    		else if( iVideoFormat.iYuvFormat.iDataLayout == EYuvDataInterleavedBE )
+    			iSourceFormat = EYuv422Chroma2_BE;
+			else
+			    err = KErrArgument;
+			break;
+      default:
+    		err = KErrNotSupported;
+	}
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetSourceFormatL --"), this);
+	return err;
+}
+
+
+TInt CNGAPostProcHwDevice::SetSourceRange()
+{
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetSourceRangeL ++"), this);
+	TInt err = KErrNone;
+	switch (iVideoFormat.iYuvFormat.iCoefficients)
+	{
+	    case EYuvBt601Range0:
+			iSourceRange = EITU601_5_REDUCEDRANGE;
+            break;
+        case EYuvBt601Range1:
+			iSourceRange = EITU601_5_FULLRANGE;
+			break;
+        case EYuvBt709Range0:
+			iSourceRange = EB709_REDUCEDRANGE;
+			break;
+        case EYuvBt709Range1:
+			iSourceRange = EB709_FULLRANGE;
+            break;
+	    default:
+		    err = KErrNotSupported;
+    }
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetSourceRangeL --"), this);
+    return err;
+}
+
+CNGAPostProcTimer::CNGAPostProcTimer( CNGAPostProcHwDevice& aParent )
+:CTimer(EPriorityHigh),iParent(aParent)
+{
+	CActiveScheduler::Add(this);
+}
+
+CNGAPostProcTimer::~CNGAPostProcTimer()
+{
+	PP_DEBUG(_L("CNGAPostProcTimer[%x]:~CNGAPostProcTimer ++"), this);
+	Cancel();
+	PP_DEBUG(_L("CNGAPostProcTimer[%x]:~CNGAPostProcTimer --"), this);
+}
+
+CNGAPostProcTimer* CNGAPostProcTimer::NewL( CNGAPostProcHwDevice& aParent )
+{
+	CNGAPostProcTimer* self = new (ELeave)CNGAPostProcTimer(aParent);
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	return self;
+}
+
+void CNGAPostProcTimer::ConstructL()
+{
+	CTimer::ConstructL();
+}
+
+void CNGAPostProcTimer::RunL()
+{
+	PP_DEBUG(_L("CNGAPostProcTimer[%x]:RunL ++"), this);
+	if (iStatus ==KErrCancel)
+	{
+		PP_DEBUG(_L("CNGAPostProcNotifier[%x]:CNGAPostProcNotifier:RunL State canceled"), this);
+		return;
+	}
+	iParent.AttemptToPost();
+	PP_DEBUG(_L("CNGAPostProcTimer[%x]:RunL --"), this);
+}
+
+void CNGAPostProcHwDevice::MmpirPostInitializeRequest(MMmfPostInitializeResponse& aResponse)
+	{
+	iPostInitializeResponse = &aResponse;
+	}