mdfdevvideoextensions/nga_mdf_postprocessor/src/NGAPostProcHwDevice.cpp
changeset 29 eb1e5d7cc688
parent 15 c1e808730d6c
child 31 ae0addfe117e
--- a/mdfdevvideoextensions/nga_mdf_postprocessor/src/NGAPostProcHwDevice.cpp	Thu Jun 24 10:37:45 2010 +0100
+++ b/mdfdevvideoextensions/nga_mdf_postprocessor/src/NGAPostProcHwDevice.cpp	Fri Jul 09 12:23:13 2010 +0100
@@ -19,7 +19,6 @@
 #include "NGAPostProcHwDevice.h"
 #include "NGAPostProcSessionManager.h"
 #include "NGAPostProcSurfaceHandler.h"
-#include "common.h"
 
 // post-processor info
 const TUid KUidVideoPostProcHwDevice = {KUidNGAPostProcHwDeviceImplUid};
@@ -47,6 +46,11 @@
 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
@@ -95,6 +99,7 @@
             iVideoFrameBufSize(0),
             iResourceLost(EFalse),
             iRedrawDone(EFalse),
+			iRedrawSurfaceInUse(EFalse),
             iVBMObserver(NULL),
             count(0),
             iSurfaceMask(surfaceHints::EAllowAllExternals),
@@ -102,6 +107,8 @@
             iVideoSurfaceObserver(NULL),
             iVPObserver(NULL),
             iPicSize(0,0),
+			iAspectRatioNum(1),
+			iAspectRatioDenom(1),
             iStepFrameCount(0),
             iPlayRate(KDefPlayRate),
             iKeyFrameMode(EFalse),
@@ -142,6 +149,10 @@
     {
         TVideoPicture* pic = iVBMBufferReferenceQ[0];
         iVBMBufferReferenceQ.Remove(0);
+        if (iColorConversionQ.Count()>0)
+    	{
+	        iColorConversionQ.Remove(0);
+	    }
 
         if (pic->iHeader) delete pic->iHeader;
         delete pic->iData.iRawData;
@@ -154,6 +165,9 @@
     iVBMBufferReferenceQ.Reset();
     iVBMBufferReferenceQ.Close();
     
+    iColorConversionQ.Reset();
+    iColorConversionQ.Close();
+    
     iVBMBufferQ.Reset();
     iVBMBufferQ.Close();
     
@@ -168,7 +182,12 @@
     	if(!iSurfaceId.IsNull())
     	{
     		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::UnregisterSurface"), this);
-    		iWsSession.UnregisterSurface(0, iSurfaceId);
+			TInt numScreens = iWsSession.NumberOfScreens();
+    		for(TInt i=0;i < numScreens;i++)
+    		{
+    			iWsSession.UnregisterSurface(i, iSurfaceId);
+    		}
+    		iWsSession.Flush();
         	iSurfaceHandler->DestroySurface(iSurfaceId);
     	}
         delete iSurfaceHandler;
@@ -196,11 +215,15 @@
         User::Leave(KErrNotReady);
 	  }
 
-
-		if( ((aFormat.iYuvFormat.iPattern == EYuv420Chroma1) ||
-			(aFormat.iYuvFormat.iPattern == EYuv420Chroma2) ||
-    		(aFormat.iYuvFormat.iPattern == EYuv420Chroma3) ))
+		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
@@ -349,7 +372,7 @@
 
 void CNGAPostProcHwDevice::WritePictureL(TVideoPicture* aPicture) 
 { 
-	PP_DEBUG(_L("CNGAPostProcHwDevice:WritePicture ++"));
+	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePicture bufId = %d"), this,GetID(aPicture));
 	TVideoPicture* pic;
 	if (iPPState==EInitializing || iPPState==EStopped || iIsInputEnded)
     {
@@ -363,15 +386,18 @@
 		User::Leave(KErrArgument);
 	}
 	pic = aPicture;	
-    if (iInputQ.Count() > 0)
-    {
-        AddToQ(pic);
-        AttemptToPost();
-    }
-    else
-    {
-		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePicture bufId = %d"), this,GetID(pic));
-		iPictureCounters.iTotalPictures++;
+	iPictureCounters.iTotalPictures++;
+	if((iPPState != EPlaying) && (iFirstPictureUpdated))
+	{
+		AddToQ(pic);
+	}
+	else if( iInputQ.Count() > 0 )
+	{
+		AddToQ(pic);
+		AttemptToPost();
+	}
+	else
+	{
 		TInt64 delta = 0;
 		TTimeToPost iTimeToPost = (TTimeToPost)IsTimeToPost(pic, delta);
 		if(!IsGceReady())
@@ -387,7 +413,13 @@
 	         PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:WritePictureL Too large delta .. skipping"), this ); 
 	         iTimeToPost = ESkipIt;
 	    }
-	
+		if(!iFirstPictureUpdated)
+		{
+            if(iTimeToPost == EDelayIt)
+            {
+                iTimeToPost = EPostIt;
+            }
+		}
 		switch(iTimeToPost)
 		{
 			case EDelayIt:
@@ -420,7 +452,10 @@
 				if(!iFirstPictureUpdated)
 				{
 					iFirstPictureUpdated = ETrue;
-					PublishSurfaceCreated();
+                    if(!iSurfaceCreatedEventPublished)
+                    {
+                        PublishSurfaceCreated();
+                    }
 				}
 			}
 			break;
@@ -827,12 +862,12 @@
 { 
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw ++"), this);
 	TInt err = KErrNone;
-	if(iResourceLost && !iRedrawDone)
+	if(iRedrawSurfaceInUse && !iRedrawDone)
 	{
         err = AddHints();
         if (err != KErrNone)
         {
-            PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost -- failed to AddHints %d"), 
+            PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw -- failed to AddHints %d"), 
                          this, err);
             iProxy->MdvppFatalError(this, err);	
             return;   
@@ -841,7 +876,7 @@
 		err = RegisterSurface(iSurfaceId);
 		if (err != KErrNone)
 		{
-		   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost -- failed to Register Surface %d"), 
+		   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw -- failed to Register Surface %d"), 
 		   				this, err);
 		   	iSurfaceHandler->DestroySurface(iSurfaceId);
 	   		iSurfaceId = TSurfaceId::CreateNullId();
@@ -860,6 +895,7 @@
 {  
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Start ++"), this);
 	iPPState = EPlaying;
+	AttemptToPost();
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Start --"), this);
 }
 
@@ -904,7 +940,10 @@
 		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetPosition FAILED: Unexpected state"), this);
         return;
     }
-    
+    if (iPPState == EPaused)
+    {	
+        iFirstPictureUpdated = EFalse;
+    }
     iCurrentPlaybackPosition = aPlaybackPosition;  
     
     ReleaseInputQ();
@@ -971,6 +1010,107 @@
     //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;
+			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);
@@ -1208,12 +1348,13 @@
 		
 		if(iVBMBufferReferenceQ.Count() == 0)
 		{
-				err = SetupSurface(aSize);
-				if(err)
-				{
-						PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() Surface Setup Failed %d"), this, err);
-						User::Leave(err);
-				}
+			iPicSize = aSize;
+			err = SetupSurface(aSize);
+			if(err)
+			{
+					PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvbmGetBufferL() Surface Setup Failed %d"), this, err);
+					User::Leave(err);
+			}
 		}
 		
     if(!iVBMBufferQ.Count())
@@ -1280,10 +1421,12 @@
 		{
 			aCropRect.Intersection( iPicSize);
 		}
-	aPixelAspectRatio = TVideoAspectRatio(1,1);
-	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssGetSurfaceParametersL()--  \
-		cropRectWidth = %d cropRectHeight = %d --"), this, aCropRect.Width(), aCropRect.Height());
-
+	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)
@@ -1292,10 +1435,20 @@
 	if(!aSurfaceId.IsNull())
 	{
 		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSurfaceRemovedL(): UnregisterSurface ID = 0x%x"), this, aSurfaceId );
-		iWsSession.UnregisterSurface(0, 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();
+			iChunk.Close();
+		}
 	}
-		
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSurfaceRemovedL() --"), this);
 }
 
@@ -1307,7 +1460,9 @@
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvpoUpdateVideoProperties PAR \
 		iAspectRatioNum = %d, iAspectRatioDenom = %d"), this,
 					 aYuvFormat.iAspectRatioNum,aYuvFormat.iAspectRatioDenom);
-					 iPicSize = aPictureSize;
+	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);
@@ -1336,7 +1491,12 @@
 		ReleaseInputQ();
 		iSessionManager->CancelUpdate();
 		ReleaseProcessQ();
-		iVideoSurfaceObserver->MmvsoRemoveSurface();
+		if(iVideoSurfaceObserver && iSurfaceCreatedEventPublished)
+		{
+			PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost - Telling client to remove surface"), this);
+			iVideoSurfaceObserver->MmvsoRemoveSurface();
+			iSurfaceCreatedEventPublished = EFalse;
+		}
 	}
 	else if(iResourceLost && iRedrawDone)
 	{
@@ -1382,24 +1542,15 @@
 
 void CNGAPostProcHwDevice::MmvshcRedrawBufferToSurface(TPtrC8& aRedrawBuffer)
 {
-    PP_DEBUG(_L("CNGAPostProcHwDevice::MmvshcRedrawBufferToSurface ++"), this);
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface ++"), this);
 	
-	TSize 			surfaceSize; 
     TUint8*         lPtr;
     TInt 			offset;
-    if(iPicSize.iWidth > iPicSize.iHeight)
-    {
-    	surfaceSize.iWidth = iPicSize.iWidth;
-    	surfaceSize.iHeight = iPicSize.iWidth;
-    }
-    else
-    {
-    	surfaceSize.iWidth = iPicSize.iHeight;
-    	surfaceSize.iHeight = iPicSize.iHeight;
-    }
+
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface -- Creating %d x %d surface"), this, iPicSize.iWidth, iPicSize.iHeight);
 
    	TInt err = KErrNone;
-	SetSurfaceAttributes(surfaceSize, 1); 
+	SetSurfaceAttributes(iPicSize, 1); 
 	
   	err = iSurfaceHandler->CreateSurface(iAttributes, iSurfaceId);
   	if (err != KErrNone)
@@ -1409,6 +1560,36 @@
 		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)
 	{
@@ -1419,49 +1600,63 @@
 		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 --"), this, iInfo().iSize.iWidth, iInfo().iSize.iHeight);
 
     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 aRedrawBuffer.Size()= %d  --"), this, offset, aRedrawBuffer.Size());
-    
+
+    PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::MmvshcRedrawBufferToSurface offset = %d"), this, offset);
+
 	lPtr = reinterpret_cast<TUint8*>(iChunk.Base() + offset);
-	memcpy((TAny *)lPtr, (TAny *)aRedrawBuffer.Ptr(), aRedrawBuffer.Size());
-	
+	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())
     {
-    	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:SetupExternalSurface Cleaning ReDraw Surface"), this);
-		iVideoSurfaceObserver->MmvsoRemoveSurface();
+		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)
     {
@@ -1652,7 +1847,10 @@
 				if(!iFirstPictureUpdated)
 				{
 					iFirstPictureUpdated = ETrue;
-					PublishSurfaceCreated();
+                    if(!iSurfaceCreatedEventPublished)
+                    {
+                        PublishSurfaceCreated();
+                    }
 				}	
 			}	// end of postit
 			break;
@@ -1688,12 +1886,12 @@
     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))    
+    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))    
+    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      
@@ -1716,7 +1914,7 @@
        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"), this, resp);
+   PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:IsTimeToPost -- %d BufID = %d"), this, resp, GetID(frame));
     return resp;
 }
 
@@ -1901,7 +2099,13 @@
 TInt CNGAPostProcHwDevice::RegisterSurface(const TSurfaceId& aSurfaceId)
 {
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:RegisterSurface(): RegisterSurface ID = 0x%x"), this, aSurfaceId);
-	return(iWsSession.RegisterSurface(0, 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()
@@ -2047,6 +2251,7 @@
 	    pOutPicture    = iColorConversionQ[0];
 	    iColorConversionQ.Remove(0);
 	    ConvertPostProcBuffer(aPicture, pOutPicture);
+	   	pOutPicture->iTimestamp = aPicture->iTimestamp;
 	    ReleasePicture(aPicture);    	    
     }				    
     else
@@ -2131,9 +2336,123 @@
 		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)
 {