photosgallery/viewframework/tvout/src/glxhdmisurfaceupdater.cpp
branchRCL_3
changeset 60 5b3385a43d68
child 68 5b238bc8ffb6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/viewframework/tvout/src/glxhdmisurfaceupdater.cpp	Wed Sep 01 12:33:26 2010 +0100
@@ -0,0 +1,1055 @@
+/*
+ * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:    
+ *
+ */
+
+#include <graphics/surface.h>
+#include <graphics/surfacemanager.h>
+#include <graphics/surfaceupdateclient.h>
+#include <graphics/surface_hints.h>
+#include <e32math.h>
+#include <apgcli.h>
+
+#include <imageconversion.h> 
+#include <fbs.h>
+#include <glxtracer.h>
+#include <glxlog.h>
+#include <glxgeneraluiutilities.h>
+
+#include "glxactivecallback.h"
+#include "glxhdmisurfaceupdater.h"
+#include "glxactivedecoder.h"
+#include <bitdev.h> 
+
+const TInt KMulFactorToCreateBitmap = 4;
+const TInt KZoomDelay = 10000;
+//100 , is decide for 20 steps of zooming , with each step being 5 pixels.
+const TInt KMaxZoomLimit = 100;
+//evey time we zoom , there is a increase in the ht amd width by 10 pixels.
+const TInt KSingleStepForZoom = 10;
+
+_LIT(KMimeJpeg,"image/jpeg");
+_LIT(KMimeJpg,"image/jpg");
+
+// -----------------------------------------------------------------------------
+// NewLC
+// -----------------------------------------------------------------------------
+CGlxHdmiSurfaceUpdater* CGlxHdmiSurfaceUpdater::NewL(RWindow* aWindow,
+        const TDesC& aImageFile, const TDesC& aNextImageFile,
+        CFbsBitmap* aFsBitmap, MGlxGenCallback* aCallBack,
+        MGlxHDMIDecoderObserver& aDecoderObserver)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater* CGlxHdmiSurfaceUpdater::NewL()");
+    CGlxHdmiSurfaceUpdater* self = new (ELeave) CGlxHdmiSurfaceUpdater(
+            aWindow, aCallBack, aDecoderObserver);
+    CleanupStack::PushL(self);
+    self->ConstructL(aFsBitmap, aImageFile, aNextImageFile);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// destructor 
+// -----------------------------------------------------------------------------
+CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater()");
+    GLX_LOG_INFO(
+            "CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater()-EHdmiDisconnected");
+    TRAP_IGNORE(iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDisconnected));
+
+    ReleaseContent();
+    if (iWindow)
+        {
+        iWindow->RemoveBackgroundSurface(ETrue);
+        }
+    if (iTimer && iTimer->IsActive()) // Check for a CPeriodic Instance
+        {
+        iTimer->Cancel();
+        }
+    delete iTimer;
+    if (iGlxDecoderAO)
+        {
+        delete iGlxDecoderAO;
+        }
+    iGlxDecoderAO = NULL;
+    iFsSession.Close();
+    if (iSurfManager)
+        {
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater() - Close");
+        if (iSurfSessionConnected)
+            {
+            iSurfUpdateSession.Close();
+            }
+        if (iSurfChunk)
+            {
+            iSurfChunk->Close();
+            }
+        delete iSurfChunk;
+        iSurfChunk = NULL;
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater(). iSurfManager->CloseSurface()");
+        iSurfManager->CloseSurface(iSurfId);
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater(). iSurfManager->Close()");
+        iSurfManager->Close();
+        delete iSurfManager;
+        iSurfManager = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// ReleaseContent 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ReleaseContent()
+    {
+    TRACER("void CGlxHdmiSurfaceUpdater::ReleaseContent()");
+    if (iGlxDecoderAO)
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -1");
+        iGlxDecoderAO->Cancel();
+        }
+    if (iFsBitmap)
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -2");
+        delete iFsBitmap;
+        iFsBitmap = NULL;
+        }
+    for (TInt i = 0; i <= 2; i++)
+        {
+        GLX_LOG_INFO1("CGlxHdmiSurfaceUpdater::ReleaseContent() -3, %d", i);
+        delete iDecodedBitmap[i];
+        iDecodedBitmap[i] = NULL;
+        }
+    GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -4");
+    if (iSurfBufferAO && iSurfBufferAO->IsActive())
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -5");
+        iSurfBufferAO->Cancel();
+        }
+    if (iImageDecoder)
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -6");
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+        }
+    if (iSurfSessionConnected && iSurfManager)
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -7");
+        iSurfUpdateSession.CancelAllUpdateNotifications();
+        }
+    if (iImagePath)
+        {
+        delete iImagePath;
+        iImagePath = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTor 
+// -----------------------------------------------------------------------------
+CGlxHdmiSurfaceUpdater::CGlxHdmiSurfaceUpdater(RWindow* aWindow,
+        MGlxGenCallback* aCallBack, MGlxHDMIDecoderObserver& aDecoderObserver) :
+    iWindow(aWindow), iCallBack(aCallBack), iShwFsThumbnail(ETrue),
+            iIsNonJpeg(EFalse), iDecoderObserver(aDecoderObserver)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::CGlxHdmiSurfaceUpdater()");
+    // Implement nothing here
+    }
+
+// -----------------------------------------------------------------------------
+// ConstructL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ConstructL(CFbsBitmap* aFsBitmap,
+        const TDesC& aImageFile, const TDesC& aNextImageFile)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ConstructL()");
+    // Initiate the HDMI by assigning the necessary values
+    InitiateHdmiL(aFsBitmap, aImageFile, aNextImageFile);
+
+    TInt error = iFsSession.Connect();
+    GLX_LOG_INFO1(
+            "CGlxHdmiSurfaceUpdater::ConstructL() FsSession Connect error = %d",
+            error);
+    User::LeaveIfError(error);
+    iShiftToCloning = EFalse;
+    iDecodingCurrent = EFalse;
+    iDecodingNext = EFalse;
+    iDecodingNextFailed = EFalse;
+    // Create the active object
+    iGlxDecoderAO = CGlxHdmiDecoderAO::NewL(this);
+
+    // Create the HDMI Decoder
+    CreateImageDecoderL();
+
+    // Create the Bitmap
+    CreateBitmapL();
+
+    // Create the surface and AO for updating the surface
+    TRAP_IGNORE( CreateHdmiL());
+
+    if (iSurfManager)
+        {
+        error = iSurfUpdateSession.Connect();
+        GLX_LOG_INFO1(
+                "CGlxHdmiSurfaceUpdater::ConstructL() Surface update Session Connect error = %d",
+                error);
+        User::LeaveIfError(error);
+        iSurfSessionConnected = ETrue;
+
+        if (!aNextImageFile.Length())
+            {
+            ShowFsThumbnailL();
+            }
+        else
+            {
+            // Modify the surface position with respect to the buffer size 
+            ModifySurfacePostion();
+            }
+#ifdef _DEBUG
+        iStartTime.HomeTime();
+#endif
+        //start decoding the image    
+        iGlxDecoderAO->ConvertImageL(*iDecodedBitmap[EJpgDecodedBitmapIndex],
+                iImageDecoder);
+        iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingStarted);
+        iDecodingCurrent = ETrue;
+        }
+    iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
+    }
+
+// -----------------------------------------------------------------------------
+// UpdateNewImageL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::UpdateNewImageL(const TDesC& aImageFile,
+        const TDesC& aNextImageFile, CFbsBitmap* aFsBitmap)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::UpdateNewImageL()");
+    if (!aImageFile.CompareC(*iImagePath) && !iDecodingCurrent
+            && !iDecodingNext)
+        {
+        iNextImagePath = aNextImageFile.Alloc();
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::UpdateNewImageL() - Decoded Image is ready ");
+        if (iDecodingNextFailed)
+            {
+            ShiftToCloningMode();
+            iDecodingNextFailed = EFalse;
+            }
+        else if (iSurfManager)
+            {
+            iShwFsThumbnail = EFalse;
+            if (iIsNonJpeg)
+                {
+                // if this is non jpeg image, make sure we scale the bitmap
+                ScaleDecodedBitmapL( ENonJpgDecodedBitmapIndex);
+                }
+            // Modify the surface position with respect to the buffer size 
+            ModifySurfacePostion();
+            ProcessTvImage();
+            iWindow->SetBackgroundSurface(iConfig, ETrue);
+            iBitmapReady = ETrue;
+            return;
+            }
+        }
+    else
+        {
+        ReleaseContent();
+		if (iNextImagePath)
+			{
+			delete iNextImagePath;
+			iNextImagePath = NULL;
+			}
+		// Ongoing decoding is cancelled if any,reset the decoding flags. 
+		iDecodingNext = EFalse;
+		iDecodingCurrent = EFalse;
+		}
+    // Initiate the HDMI by assigning the necessary values
+    InitiateHdmiL(aFsBitmap, aImageFile, aNextImageFile);
+    //Cancel the zoom timers if any
+    if (iTimer->IsActive())
+        {
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::UpdateNewImageL() - Cancel Timer");
+        iTimer->Cancel();
+        }
+
+    // Create the HDMI Decoder
+    CreateImageDecoderL();
+
+    // Create the Bitmap
+    CreateBitmapL();
+    if (iSurfManager)
+        {
+        // Create the surface and AO for updating the surface
+        CreateHdmiL( EFalse);
+        }
+    else
+        {
+        TRAP_IGNORE( CreateHdmiL(ETrue));
+        }
+
+#ifdef _DEBUG
+    iStartTime.HomeTime();
+#endif
+    if (iSurfManager)
+        {
+        // Show FS Thumbnail
+        ShowFsThumbnailL();
+        //start decoding the image
+        iGlxDecoderAO->ConvertImageL(*iDecodedBitmap[EJpgDecodedBitmapIndex],
+                iImageDecoder);
+        iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingStarted);
+        iDecodingCurrent = ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// InitiateHdmiL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::InitiateHdmiL(CFbsBitmap* aFsBitmap,
+        const TDesC& aImageFile, const TDesC& aNextImageFile)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::InitiateHdmiL()");
+    iImagePath = aImageFile.Alloc();
+    iNextImagePath = aNextImageFile.Alloc();
+    iFsBitmap = new (ELeave) CFbsBitmap;
+    iFsBitmap->Duplicate(aFsBitmap->Handle());
+    iIsNonJpeg = EFalse;
+    iTvScreenSize = iWindow->Size();
+
+    iBitmapReady = EFalse;
+    iLeftCornerForZoom.iX = 0;
+    iLeftCornerForZoom.iY = 0;
+
+    iZoom = ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CreateHDMI 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::CreateHdmiL(TBool aCreateSurface)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::CreateHdmiL()");
+
+    if (aCreateSurface)
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::CreateHdmiL() Create Surface");
+        CreateSurfaceL();
+        }
+
+    // Active objects for double buffered draw signalling
+    if (!iSurfBufferAO)
+        {
+        iSurfBufferAO = new (ELeave) CGlxActiveCallBack(TCallBack(
+                SurfBuffer0ReadyL, this), CActive::EPriorityStandard - 1);
+        CActiveScheduler::Add( iSurfBufferAO);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CreateSurfaceL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::CreateSurfaceL()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::CreateSurfaceL()");
+    iSurfManager = new (ELeave) RSurfaceManager();
+    TInt error = iSurfManager->Open();
+    GLX_LOG_INFO1(
+            "CGlxHdmiSurfaceUpdater::CreateSurfaceL Open Surface manager error = %d",
+            error);
+    User::LeaveIfError(error);
+
+    //Need to set the surface Hint for the surface to indicate
+    //that photos do not need overscan compensation and the image will
+    //be displayed in 720p resolution. 
+    //Refer error: HJVA-85DD25 for more info.
+    RSurfaceManager::THintPair surfHint;
+    TUid uid(KNullUid);
+    uid.iUid = surfaceHints::KSurfaceContent;
+    surfHint.Set(uid, surfaceHints::EStillImage, EFalse);
+
+    RSurfaceManager::TSurfaceCreationAttributesBuf attributes;
+    attributes().iPixelFormat = EUidPixelFormatARGB_8888;// EUidPixelFormatYUV_420Planar;
+    attributes().iSize = iTvScreenSize;
+
+    attributes().iBuffers = 1;
+    attributes().iStride = iTvScreenSize.iWidth * KMulFactorToCreateBitmap;
+    attributes().iAlignment = KMulFactorToCreateBitmap;
+    attributes().iContiguous = EFalse;
+    attributes().iMappable = ETrue;
+    attributes().iSurfaceHints = &surfHint;
+    attributes().iHintCount = 1;
+
+    error = iSurfManager->CreateSurface(attributes, iSurfId);
+    GLX_LOG_INFO1(
+            "CGlxHdmiSurfaceUpdater::CreateSurfaceL, Creating surface error : %d",
+            error);
+    if (error == KErrNoMemory)
+        {
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::CreateSurfaceL(). iSurfManager->Close()");
+        iSurfManager->Close();
+        delete iSurfManager;
+        iSurfManager = NULL;
+        if (iShiftToCloning == EFalse)
+            {
+            GlxGeneralUiUtilities::ShowErrorNoteL(error); // Show Low Memory Popup Once before shifting to Cloning Mode
+            iShiftToCloning = ETrue;
+            }
+        ShiftToCloningMode(); // Shift from Posting Mode to Cloning Mode
+        }
+    User::LeaveIfError(error);
+
+    //Map the surface and stride the surface info
+    MapSurfaceL();
+    // Set the Configuration to the surface ID when creating a surface
+    iConfig.SetSurfaceId(iSurfId);
+    }
+
+// -----------------------------------------------------------------------------
+// MapSurfaceL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::MapSurfaceL()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::MapSurfaceL()");
+
+    //Create chunk to map it to the surface ID.
+    iSurfChunk = new (ELeave) RChunk();
+    User::LeaveIfNull( iSurfChunk);
+    TInt error = iSurfManager->MapSurface(iSurfId, *iSurfChunk);
+    GLX_LOG_INFO1(
+            "CGlxHdmiSurfaceUpdater::MapSurfaceL(), MapSurface error : %d",
+            error);
+    User::LeaveIfError(error);
+
+    // Get the info from the surfaceManager
+    // and store pointers to the pixel data
+    RSurfaceManager::TInfoBuf info;
+    error = iSurfManager->SurfaceInfo(iSurfId, info);
+    GLX_LOG_INFO1(
+            "CGlxHdmiSurfaceUpdater::MapSurfaceL(), SurfaceInfo error : %d",
+            error);
+    User::LeaveIfError(error);
+
+    iSurfaceStride = info().iStride;
+    TInt offset = 0;
+    iSurfManager->GetBufferOffset(iSurfId, 0, offset);
+    iSurfBuffer = iSurfChunk->Base() + offset;
+    }
+
+// -----------------------------------------------------------------------------
+// SurfBuffer0ReadyL 
+// -----------------------------------------------------------------------------
+TInt CGlxHdmiSurfaceUpdater::SurfBuffer0ReadyL(TAny* aObject)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::SurfBuffer0ReadyL()");
+    CGlxHdmiSurfaceUpdater* self =
+            reinterpret_cast<CGlxHdmiSurfaceUpdater*> (aObject);
+    if (!self->iShwFsThumbnail)
+        {
+        self->iDecodingCurrent = EFalse;
+        if (self->iNextImagePath->Length())
+            {
+            self->DecodeNextImageL();
+            }
+        else
+            {
+            self->iDecoderObserver.HandleHDMIDecodingEventL(
+                    EHdmiDecodingCompleted);
+            }
+        }
+    return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// Refresh 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::Refresh()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::Refresh()");
+    // copy the decoded bitmap on to the surface
+    SwapBuffers();
+
+    // refresh the window
+    iCallBack->DoGenCallback();
+    }
+
+// -----------------------------------------------------------------------------
+// SwapBuffers
+// This is used to sawp the buffers shown and to be shown 
+// After this is done, a refresh to the window should be done to refresh the TV
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::SwapBuffers()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::SwapBuffers()");
+    TInt bitmapIndex = KErrNotFound;
+
+    if (iShwFsThumbnail) // show FS thumbnail
+        {
+        bitmapIndex = EFSBitmapIndex;
+        }
+    else if (iIsNonJpeg && !iShwFsThumbnail) // this indicates it is non jpeg image and decoding finished
+        {
+        bitmapIndex = ENonJpgDecodedBitmapIndex;
+        }
+    else // if none of the above state means it is jpeg image and decoding finished
+        {
+        bitmapIndex = EJpgDecodedBitmapIndex;
+        }
+
+    // Lock the heap so that subsequent call to dataaddress doesnt happen
+    iDecodedBitmap[bitmapIndex]->LockHeap();
+
+    // Data stride
+    TUint fs = iDecodedBitmap[bitmapIndex]->DataStride();
+
+    //Bitmap address from where the data has to be copied.
+    TUint8* from = (TUint8*) iDecodedBitmap[bitmapIndex]->DataAddress();
+
+    //surface chunk address to where the bitmap data has to be copied.
+    TUint8* to = (TUint8*) iSurfBuffer;
+
+    // To buffer (32 bit colors)
+    TUint ts = iSurfaceStride;
+    //No of bytes to be copied on to the surface.
+    TUint bytes = iDecodedBitmap[bitmapIndex]->SizeInPixels().iWidth
+            * KMulFactorToCreateBitmap;
+
+    GLX_LOG_INFO2(
+            "CGlxHdmiSurfaceUpdater::SwapBuffers() - decodeSize width = %d and height %d",
+            iDecodedBitmap[bitmapIndex]->SizeInPixels().iWidth,
+            iDecodedBitmap[bitmapIndex]->SizeInPixels().iHeight);
+
+    // Copy the bitmap on to the surface.
+    for (TInt y = iDecodedBitmap[bitmapIndex]->SizeInPixels().iHeight; y > 0; y--)
+        {
+        Mem::Copy(to, from, bytes);
+        to += ts;
+        from += fs;
+        }
+    iDecodedBitmap[bitmapIndex]->UnlockHeap();
+    }
+
+// -----------------------------------------------------------------------------
+// CreateBitmapL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::CreateBitmapL()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::CreateBitmapL()");
+    TSize imageSize = iImageDecoder->FrameInfo().iOverallSizeInPixels;
+    GLX_LOG_INFO2(
+            "CGlxHdmiSurfaceUpdater::StartImageDecodeL() - bitmapsize=%d, %d",
+            imageSize.iWidth, imageSize.iHeight);
+    TReal32 scaleFactor = 0.0f;
+    if (iTvScreenSize.iWidth * imageSize.iHeight > iTvScreenSize.iHeight
+            * imageSize.iWidth)
+        {
+        scaleFactor = (TReal32) iTvScreenSize.iHeight
+                / (TReal32) imageSize.iHeight;
+        }
+    else
+        {
+        scaleFactor = (TReal32) iTvScreenSize.iWidth
+                / (TReal32) imageSize.iWidth;
+        }
+    GLX_LOG_INFO1(
+            "CGlxHdmiSurfaceUpdater::StartImageDecodeL() - scaleFactor=%f",
+            scaleFactor);
+    iTargetBitmapSize.iHeight = imageSize.iHeight * scaleFactor;
+    iTargetBitmapSize.iWidth = imageSize.iWidth * scaleFactor;
+    GLX_LOG_INFO2(
+            "CGlxHdmiSurfaceUpdater::StartImageDecodeL() - targetBitmapSize=%d, %d",
+            iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
+    //create the bitmap for the required size
+    iDecodedBitmap[EJpgDecodedBitmapIndex] = new (ELeave) CFbsBitmap();
+    // to check if the Mimetype is supported by the decoder to to arbitary scaling
+    // if not then we recalculate the size
+    TInt err = iDecodedBitmap[EJpgDecodedBitmapIndex]->Create(
+            ReCalculateSizeL(), EColor16MU);
+    User::LeaveIfNull( iDecodedBitmap[EJpgDecodedBitmapIndex]);
+    }
+
+// -----------------------------------------------------------------------------
+// DoesMimeTypeNeedsRecalculateL()
+// -----------------------------------------------------------------------------
+//
+TBool CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL");
+    RApaLsSession session;
+    TDataType mimeType;
+    TUid uid;
+
+    User::LeaveIfError(session.Connect());
+    CleanupClosePushL(session);
+    User::LeaveIfError(session.AppForDocument(iImagePath->Des(), uid,
+            mimeType));
+    CleanupStack::PopAndDestroy(&session);
+
+    if (mimeType.Des().Compare(KMimeJpeg) == 0 || mimeType.Des().Compare(
+            KMimeJpg) == 0)
+        {
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL - jpeg");
+        return EFalse;
+        }
+    else
+        {
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL - non jpeg");
+        return ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// ReCalculateSize 
+// -----------------------------------------------------------------------------
+TSize CGlxHdmiSurfaceUpdater::ReCalculateSizeL()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ReCalculateSizeL()");
+    if (DoesMimeTypeNeedsRecalculateL())
+        {
+        iIsNonJpeg = ETrue;
+        TSize fullFrameSize = iImageDecoder->FrameInfo().iOverallSizeInPixels;
+        // calculate the reduction factor on what size we need
+        TInt reductionFactor = iImageDecoder->ReductionFactor(fullFrameSize,
+                iTargetBitmapSize);
+        // get the reduced size onto destination size
+        TSize destSize;
+        User::LeaveIfError(iImageDecoder->ReducedSize(fullFrameSize,
+                reductionFactor, destSize));
+        GLX_LOG_INFO2(
+                "CGlxHdmiSurfaceUpdater::ReCalculateSizeL() - destSize=%d, %d",
+                destSize.iWidth, destSize.iHeight);
+        return destSize;
+        }
+    else
+        {
+        return iTargetBitmapSize;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// HandleRunL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::HandleRunL(TRequestStatus& aStatus)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::HandleRunL()");
+
+#ifdef _DEBUG
+    iStopTime.HomeTime();
+    GLX_LOG_INFO1("CGlxHdmiSurfaceUpdater::HandleRunL() ConvertImageL took"
+            " <%d> us", (TInt)iStopTime.MicroSecondsFrom(iStartTime).Int64());
+#endif
+    if (iDecodingNext)
+        {
+        iDecodingNext = EFalse;
+        if (aStatus.Int() != KErrNone)
+            {
+            GLX_LOG_INFO("HandleRunL - Next Convert failed");
+            iDecodingNextFailed = ETrue;
+            }
+        //Inform the observer that image decoding is completed
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::HandleRunL-EHdmiDecodingCompleted");
+        iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingCompleted);
+        }
+    else
+        {
+        iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingFirstCompleted);
+        if (aStatus.Int() != KErrNone)
+            {
+            GLX_LOG_INFO("HandleRunL - Convert failed");
+            ShiftToCloningMode();
+            }
+        else if (iSurfManager)
+            {
+            iShwFsThumbnail = EFalse;
+            if (iIsNonJpeg)
+                {
+                // if this is non jpeg image, make sure we scale the bitmap
+                ScaleDecodedBitmapL( ENonJpgDecodedBitmapIndex);
+                }
+            ProcessTvImage();
+            iBitmapReady = ETrue;
+            }
+        }
+    //release imagedecoder after the conversion is over
+    if (iImageDecoder)
+        {
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CreateImageDecoderL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::CreateImageDecoderL()
+    {
+    TRACER("CGlxHdmiController::CreateImageDecoderL()");
+    // Create a decoder for the image in the named file
+    TRAPD(error, iImageDecoder = CImageDecoder::FileNewL(iFsSession,
+            iImagePath->Des(), CImageDecoder::EOptionAlwaysThread, KNullUid));
+    GLX_LOG_INFO1("CreateImageDecoderL CImageDecoder:FileNewL error %d",
+            error);
+    User::LeaveIfError( error);
+    }
+
+// -----------------------------------------------------------------------------
+// ActivateZoom 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ActivateZoom(TBool aAutoZoomOut)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ActivateZoom()");
+    iZoom = ETrue;
+    iAutoZoomOut = aAutoZoomOut;
+    if (iTimer->IsActive())
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ActivateZoom() - Cancel Timer");
+        iTimer->Cancel();
+        }
+
+    if (!iTimer->IsActive() && iBitmapReady)
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ActivateZoom() - Start Timer");
+        iTimer->Start(KZoomDelay, KZoomDelay, TCallBack(TimeOut, this));
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// DeactivateZoom 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::DeactivateZoom()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::DeactivateZoom()");
+
+    if (iTimer->IsActive())
+        {
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::DeactivateZoom() - Cancel Timer");
+        iTimer->Cancel();
+        }
+    if (!iTimer->IsActive() && iBitmapReady && iLeftCornerForZoom.iX)
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::DeactivateZoom() - Start Timer");
+        iZoom = EFalse;
+        iTimer->Start(KZoomDelay, KZoomDelay, TCallBack(TimeOut, this));
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// TimeOut
+// ---------------------------------------------------------------------------
+//  
+TInt CGlxHdmiSurfaceUpdater::TimeOut(TAny* aSelf)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::TimeOut");
+    if (aSelf)
+        {
+        CGlxHdmiSurfaceUpdater* self =
+                static_cast<CGlxHdmiSurfaceUpdater*> (aSelf);
+        if (self)
+            {
+            self->Zoom(ETrue);
+            }
+        }
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// Zoom 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::Zoom(TBool aZoom)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::Zoom()");
+
+    if (!iBitmapReady)
+        {
+        return;
+        }
+
+    if (iLeftCornerForZoom.iX == KMaxZoomLimit)
+        {
+        iZoom = EFalse;
+        //If autozoomout is not set then cancel the timer and do
+        //the zoom out on DeactivateZoom.
+        if (!iAutoZoomOut)
+            {
+            iTimer->Cancel();
+            }
+        }
+    if (aZoom && iZoom)
+        {
+        iTargetBitmapSize.iWidth = TInt(iTargetBitmapSize.iWidth
+                - KSingleStepForZoom);
+        iTargetBitmapSize.iHeight = TInt(iTargetBitmapSize.iHeight
+                - KSingleStepForZoom);
+        iLeftCornerForZoom.iX = iLeftCornerForZoom.iX + KSingleStepForZoom
+                / 2;
+        iLeftCornerForZoom.iY = iLeftCornerForZoom.iY + KSingleStepForZoom
+                / 2;
+        GLX_LOG_INFO2(
+                "CGlxHdmiSurfaceUpdater::Zoom()--- 2,iTargetBitmapSize.iWidth = %d, iTargetBitmapSize.iHeight = %d",
+                iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
+        iConfig.SetViewport(TRect(iLeftCornerForZoom.iX,
+                iLeftCornerForZoom.iY, iTargetBitmapSize.iWidth,
+                iTargetBitmapSize.iHeight));
+        }
+    else
+        {
+        iTargetBitmapSize.iWidth = TInt(iTargetBitmapSize.iWidth
+                + KSingleStepForZoom);
+        iTargetBitmapSize.iHeight = TInt(iTargetBitmapSize.iHeight
+                + KSingleStepForZoom);
+        iLeftCornerForZoom.iX = iLeftCornerForZoom.iX - KSingleStepForZoom
+                / 2;
+        iLeftCornerForZoom.iY = iLeftCornerForZoom.iY - KSingleStepForZoom
+                / 2;
+        if (iLeftCornerForZoom.iX == 0)
+            {
+            iTimer->Cancel();
+            iZoom = ETrue;
+            }
+        GLX_LOG_INFO2(
+                "CGlxHdmiSurfaceUpdater::Zoom()--- 4,iTargetBitmapSize.iWidth = %d, iTargetBitmapSize.iHeight = %d",
+                iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
+        iConfig.SetViewport(TRect(iLeftCornerForZoom.iX,
+                iLeftCornerForZoom.iY, iTargetBitmapSize.iWidth,
+                iTargetBitmapSize.iHeight));
+        }
+    iWindow->SetBackgroundSurface(iConfig, ETrue);
+    }
+
+// -----------------------------------------------------------------------------
+// ModifySurfacePostion 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ModifySurfacePostion()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ModifySurfacePostion()");
+    TPoint startPoint(0, 0);
+    if (iTargetBitmapSize.iWidth < iTvScreenSize.iWidth)
+        {
+        startPoint.iX = (iTvScreenSize.iWidth - iTargetBitmapSize.iWidth) / 2;
+        }
+    if (iTargetBitmapSize.iHeight < iTvScreenSize.iHeight)
+        {
+        startPoint.iY = (iTvScreenSize.iHeight - iTargetBitmapSize.iHeight)
+                / 2;
+        }
+    GLX_LOG_INFO2(
+            "CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - target iTargetBitmapSize=%d, %d",
+            iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
+    GLX_LOG_INFO2(
+            "CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - startPoint =%d, %d",
+            startPoint.iX, startPoint.iY);
+
+    // target
+    iConfig.SetExtent(TRect(startPoint.iX, startPoint.iY,
+            (iTvScreenSize.iWidth - startPoint.iX), (iTvScreenSize.iHeight
+                    - startPoint.iY)));
+    // source
+    iConfig.SetViewport(TRect(TPoint(0, 0), TSize(iTargetBitmapSize.iWidth,
+            iTargetBitmapSize.iHeight)));
+#ifdef _DEBUG
+    TRect ex, vp;
+    iConfig.GetExtent(ex);
+    iConfig.GetViewport(vp);
+    GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - vp - TL=%d, %d",vp.iTl.iX,vp.iTl.iY);
+    GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - vp - BR=%d, %d",vp.iBr.iX,vp.iBr.iY);
+    GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - ex - TL=%d, %d",ex.iTl.iX,ex.iTl.iY);
+    GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - ex - BR=%d, %d",ex.iBr.iX,ex.iBr.iY);
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// ShiftToCloningMode 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ShiftToCloningMode()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ShiftToCloningMode()");
+    iWindow->RemoveBackgroundSurface(ETrue);
+    }
+
+// -----------------------------------------------------------------------------
+// ShiftToPostingMode 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ShiftToPostingMode()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ShiftToPostingMode()");
+    if (iSurfManager)
+        {
+#ifdef _DEBUG
+        TRect ex, vp;
+        iConfig.GetExtent(ex);
+        iConfig.GetViewport(vp);
+        GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - vp - TL=%d, %d",vp.iTl.iX,vp.iTl.iY);
+        GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - vp - BR=%d, %d",vp.iBr.iX,vp.iBr.iY);
+        GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - ex - TL=%d, %d",ex.iTl.iX,ex.iTl.iY);
+        GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - ex - BR=%d, %d",ex.iBr.iX,ex.iBr.iY);
+#endif
+        iWindow->SetBackgroundSurface(iConfig, ETrue);
+        iShiftToCloning = EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// ShowFsThumbnailL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ShowFsThumbnailL()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ShowFsThumbnailL()");
+    iShwFsThumbnail = ETrue;
+    GLX_LOG_INFO2(
+            "CGlxHdmiSurfaceUpdater::ShowFsThumbnailL() iTargetBitmapSize Width=%d, Height=%d",
+            iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
+    // Modify the surface position with respect to the buffer size 
+    ModifySurfacePostion();
+    // this is for FS thumbnail stored in array pointer 0
+    ScaleDecodedBitmapL( EFSBitmapIndex);
+    // Process the Image to TV
+    ProcessTvImage();
+    // set the surface onto background
+    iWindow->SetBackgroundSurface(iConfig, ETrue);
+    }
+
+// -----------------------------------------------------------------------------
+// ScaleDecodedBitmapL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL(TInt aBitmapIndex)
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL()");
+    GLX_LOG_INFO2(
+            "CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL() iTargetBitmapSize Width=%d, Height=%d",
+            iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
+
+    if (iDecodedBitmap[aBitmapIndex])
+        {
+        delete iDecodedBitmap[aBitmapIndex];
+        iDecodedBitmap[aBitmapIndex] = NULL;
+        }
+    iDecodedBitmap[aBitmapIndex] = new (ELeave) CFbsBitmap();
+    // create destination with size
+    TInt err = iDecodedBitmap[aBitmapIndex]->Create(iTargetBitmapSize,
+            EColor16MU);
+    GLX_LOG_INFO1(
+            "CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL() creating bitmap error, err=%d",
+            err);
+    User::LeaveIfNull( iDecodedBitmap[aBitmapIndex]);
+
+    // Create bitmap device for destination bitmap
+    CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(
+            iDecodedBitmap[aBitmapIndex]);
+    CleanupStack::PushL(bitmapDevice);
+
+    CFbsBitGc* bitmapGc = CFbsBitGc::NewL();
+    CleanupStack::PushL(bitmapGc);
+    bitmapGc->Activate(bitmapDevice);
+    if (aBitmapIndex == EFSBitmapIndex)
+        {
+        // scale the source bitmap which is a FS bitmap
+        bitmapGc->DrawBitmap(TRect(iTargetBitmapSize), iFsBitmap);
+        }
+    else
+        {
+        // scale the source bitmap which is a decoded bitmap
+        bitmapGc->DrawBitmap(TRect(iTargetBitmapSize),
+                iDecodedBitmap[EJpgDecodedBitmapIndex]);
+        }
+
+    CleanupStack::PopAndDestroy(bitmapGc);
+    CleanupStack::PopAndDestroy(bitmapDevice);
+
+    }
+
+// -----------------------------------------------------------------------------
+// ProcessTvImage 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::ProcessTvImage()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::ProcessTvImage()");
+    if (iSurfBufferAO->iStatus != KRequestPending
+            && !iSurfBufferAO->IsActive())
+        {
+        Refresh();
+        iSurfBufferAO->iStatus = KRequestPending;
+        iSurfBufferAO->SetActive();
+        iSurfUpdateSession.NotifyWhenAvailable(iSurfBufferAO->iStatus);
+        TInt err = iSurfUpdateSession.SubmitUpdate(1, iSurfId, 0, NULL);
+        GLX_LOG_INFO1(
+                "CGlxHdmiSurfaceUpdater::ProcessTvImage() Surfaceupdatesession error %d",
+                err);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// DecodeNextImageL 
+// -----------------------------------------------------------------------------
+void CGlxHdmiSurfaceUpdater::DecodeNextImageL()
+    {
+    TRACER("CGlxHdmiSurfaceUpdater::DecodeNextImageL()");
+    ReleaseContent();
+    iImagePath = iNextImagePath->Alloc();
+    if (iNextImagePath)
+        {
+        delete iNextImagePath;
+        iNextImagePath = NULL;
+        }
+    iIsNonJpeg = EFalse;
+    GLX_LOG_INFO("Before - iWindow->Size()");
+    iTvScreenSize = iWindow->Size();
+    GLX_LOG_INFO("After - iWindow->Size()");
+    iBitmapReady = EFalse;
+    iLeftCornerForZoom.iX = 0;
+    iLeftCornerForZoom.iY = 0;
+    iZoom = ETrue;
+    //Cancel the zoom timers if any
+    if (iTimer && iTimer->IsActive())
+        {
+        GLX_LOG_INFO(
+                "CGlxHdmiSurfaceUpdater::UpdateNewImageL() - Cancel Timer");
+        iTimer->Cancel();
+        }
+    // Create the HDMI Decoder
+    CreateImageDecoderL();
+    // Create the Bitmap
+    CreateBitmapL();
+    if (iSurfManager)
+        {
+        // Create the surface and AO for updating the surface
+        CreateHdmiL( EFalse);
+        }
+    else
+        {
+        TRAP_IGNORE( CreateHdmiL(ETrue));
+        }
+
+#ifdef _DEBUG
+    iStartTime.HomeTime();
+#endif
+    if (iSurfManager)
+        {
+        //start decoding the image
+        iGlxDecoderAO->ConvertImageL(*iDecodedBitmap[EJpgDecodedBitmapIndex],
+                iImageDecoder);
+        iDecodingNext = ETrue;
+        iDecodingNextFailed = EFalse;
+        //Inform the Observer that decoding has started
+        iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingStarted);
+        }
+    }
+