photosgallery/viewframework/texturemanager/src/glxbitmapdecoderwrapper.cpp
branchRCL_3
changeset 60 5b3385a43d68
child 75 01504893d9cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/viewframework/texturemanager/src/glxbitmapdecoderwrapper.cpp	Wed Sep 01 12:33:26 2010 +0100
@@ -0,0 +1,415 @@
+/*
+* 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:    Texture Manager component/Decodes the Image in step for large sized images
+ *
+*/
+
+
+
+
+// INCLUDE FILES
+#include "glxbitmapdecoderwrapper.h"
+#include <glxtracer.h>      //  For Log
+#include <bitmaptransforms.h>
+#include <imageconversion.h>
+#include <ExifRead.h>
+#include <glxlog.h>
+#include <hal.h>
+#include <hal_data.h>
+#include <mglxcache.h>
+#include <oommonitorsession.h>
+#include <e32math.h>
+#include <apgcli.h>
+
+namespace
+    {
+    const TInt KGlxDecodingThreshold = 3000000;
+    const TInt KGlxDecodingThresholdDimension = 2000;
+
+    // Photos low_ram_threshold [8.637 MB] as in oomconfig.xml
+    const TInt KGlxCriticalRAMForPhotos = 9056550;
+    const TInt KGlxDecodeBitmapFactor = 3;
+    
+    _LIT(KMimeJpeg,"image/jpeg");
+    _LIT(KMimeJpg,"image/jpg");
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CGlxBitmapDecoderWrapper* CGlxBitmapDecoderWrapper::NewL(
+        MGlxBitmapDecoderObserver* aObserver)
+    {
+    TRACER("CGlxBitmapDecoderWrapper::NewL()");
+    CGlxBitmapDecoderWrapper* self = new (ELeave) CGlxBitmapDecoderWrapper();
+    CleanupStack::PushL(self);
+    self->ConstructL(aObserver);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CGlxBitmapDecoderWrapper::CGlxBitmapDecoderWrapper() :
+    CActive(EPriorityLow)
+    {
+    TRACER("CGlxBitmapDecoderWrapper::CGlxBitmapDecoderWrapper()");
+    }		
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CGlxBitmapDecoderWrapper::~CGlxBitmapDecoderWrapper()
+    {
+    TRACER("CGlxBitmapDecoderWrapper::~CGlxBitmapDecoderWrapper()");
+    iFs.Close();
+    Cancel();
+    if (iImageDecoder)
+        {
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+        }
+    if (iImagePath)
+        {
+        delete iImagePath;
+        iImagePath = NULL;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+void CGlxBitmapDecoderWrapper::ConstructL(MGlxBitmapDecoderObserver* aObserver)
+    {
+    TRACER("CGlxBitmapDecoderWrapper::ConstructL ");
+    iObserver = aObserver;
+    User::LeaveIfError(iFs.Connect());
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------------------------
+// DoDecodeImageL
+// ---------------------------------------------------------------------------		
+void CGlxBitmapDecoderWrapper::DoDecodeImageL(const TDesC& aSourceFileName,
+        TInt aIndex)
+    {
+    TRACER("CGlxBitmapDecoderWrapper::DoDecodeImageL()");
+    GLX_LOG_URI("CGlxBitmapDecoderWrapper::DoDecodeImageL(%S)",
+            &aSourceFileName);
+
+    iThumbnailIndex = aIndex;
+
+#ifdef _DEBUG
+    iStartTime.HomeTime();
+#endif                          
+
+    if (iImageDecoder)
+        {
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+        }
+
+    CImageDecoder::TOptions options =
+            (CImageDecoder::TOptions) (CImageDecoder::EOptionNoDither
+                    | CImageDecoder::EOptionAlwaysThread);
+
+    // Use extended JPEG decoder
+    GLX_DEBUG1("DoDecodeImageL:: EHwImplementation" );
+    TRAPD( err, iImageDecoder = CExtJpegDecoder::FileNewL(
+                    CExtJpegDecoder::EHwImplementation, iFs,
+                    aSourceFileName, options ) );
+    GLX_DEBUG2("DoDecodeImageL:: EHwImplementation (%d)", err);
+    if (KErrNone != err)
+        {
+        TRAP(err,iImageDecoder = CExtJpegDecoder::FileNewL(
+                        CExtJpegDecoder::ESwImplementation, iFs,
+                        aSourceFileName, options ) );
+        GLX_DEBUG2("DoDecodeImageL:: ESwImplementation (%d)", err);
+        if (KErrNone != err)
+            {
+            GLX_DEBUG1("DoDecodeImageL::CImageDecoder");
+            // Not a JPEG - use standard decoder
+            iImageDecoder = CImageDecoder::FileNewL(iFs, aSourceFileName,
+                    options);
+            }
+        }
+#ifdef _DEBUG
+    iStopTime.HomeTime();
+    GLX_DEBUG2("*** Decoder Creation took <%d> us ***",
+            (TInt)iStopTime.MicroSecondsFrom(iStartTime).Int64());
+#endif                          
+
+    TSize imageSize = iImageDecoder->FrameInfo().iOverallSizeInPixels;
+    GLX_DEBUG3("GlxDecoderWrapper::DecodeImageL() - OverallSize: w=%d, h=%d",
+            imageSize.iWidth, imageSize.iHeight);
+    iOriginalSize.iWidth = imageSize.iWidth;
+    iOriginalSize.iHeight = imageSize.iHeight;
+
+    if (iBitmap)
+        {
+        delete iBitmap;
+        iBitmap = NULL;
+        }
+    
+    if (iImagePath)
+        {
+        delete iImagePath;
+        iImagePath = NULL;
+        }
+    iImagePath = aSourceFileName.Alloc();
+    
+    DecodeImageL();
+    }
+
+// ---------------------------------------------------------------------------
+// DecodeImageL
+// ---------------------------------------------------------------------------
+//
+void CGlxBitmapDecoderWrapper::DecodeImageL()
+    {
+    TRACER("CGlxBitmapDecoderWrapper::DecodeImageL()");
+    TReal32 mFactor = 1;
+    TReal mFactor1 = 1;
+    TReal32 mFactor2 = 1;
+    //Set Size according to level and state
+    TReal32 width = iOriginalSize.iWidth;
+    TReal32 height = iOriginalSize.iHeight;
+
+    if (KGlxDecodingThreshold < (width * height))
+        {
+        TReal tempFactor = TReal32(KGlxDecodingThreshold)
+                / (width * height);
+        User::LeaveIfError(Math::Sqrt(mFactor1, tempFactor));
+        GLX_DEBUG2("DecodeImageL() - mFactor1 = %f", mFactor1);
+        }
+
+    if (KGlxDecodingThresholdDimension < width
+            || KGlxDecodingThresholdDimension < height)
+        {
+        mFactor2 = TReal32(KGlxDecodingThresholdDimension) / Max(width,
+                height);
+        GLX_DEBUG2("DecodeImageL() - mFactor2 = %f", mFactor2);
+        }
+
+    mFactor = Min(TReal32(mFactor1), mFactor2);
+    GLX_DEBUG2("DecodeImageL() - Final mFactor = %f", mFactor);
+
+    // create the destination bitmap
+    if (!iBitmap)
+        {
+        TInt freeMemory = 0;
+        HAL::Get(HALData::EMemoryRAMFree, freeMemory);
+        width *= mFactor;
+        height *= mFactor;
+        TInt minmemorytodecode = KGlxDecodeBitmapFactor * width * height;
+        GLX_DEBUG3("DecodeImageL: minmemorytodecode=%d, freememory=%d",
+                minmemorytodecode, freeMemory);
+        
+        iTargetBitmapSize.iWidth = width;
+        iTargetBitmapSize.iHeight = height;
+        GLX_DEBUG3("DecodeImageL: iTargetBitmapSize w=%d, h=%d",
+                iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
+        __ASSERT_DEBUG(width > 0 && height > 0, Panic(EGlxPanicIllegalArgument));      
+
+        if (minmemorytodecode < (freeMemory - KGlxCriticalRAMForPhotos))
+            {
+            GLX_DEBUG1("DecodeImageL:RAM available decoding image");            
+            iBitmap = new (ELeave) CFbsBitmap();
+            iBitmap->Create(ReCalculateSizeL(),
+                    iImageDecoder->FrameInfo().iFrameDisplayMode);
+#ifdef _DEBUG
+            iStartTime.HomeTime(); // Get home time
+#endif                          
+            iImageDecoder->Convert(&iStatus, *iBitmap);
+            }
+        else
+            {
+            //case when sufficient memory is not available
+            //request OOM FW to release the required memory
+            GLX_DEBUG1("DecodeImageL:insufficient RAM - request OOM");
+            TInt err = OOMRequestFreeMemoryL(minmemorytodecode);
+            if (err == KErrNoMemory)
+                {
+                //if OOM fails, release Photos Cache
+                GLX_DEBUG1("DecodeImageL:insufficient RAM - OOM failed"
+                        " - request Cache");
+                MGlxCache* cacheManager = MGlxCache::InstanceL();
+                cacheManager->ReleaseRAML(ETrue);
+                cacheManager->Close();
+                //Try and release memory again
+                err = OOMRequestFreeMemoryL(minmemorytodecode);
+                }
+            if (err != KErrNoMemory)
+                {
+                GLX_DEBUG1("DecodeImageL:Sufficient RAM available");                
+                iBitmap = new (ELeave) CFbsBitmap();
+                iBitmap->Create(ReCalculateSizeL(),
+                        iImageDecoder->FrameInfo().iFrameDisplayMode);
+#ifdef _DEBUG
+                iStartTime.HomeTime(); // Get home time
+#endif                          
+                iImageDecoder->Convert(&iStatus, *iBitmap);
+                }
+            else
+                {
+                GLX_DEBUG1("NOT ENOUGH MEMORY - "
+                        "Using the Fullscreen Thumbnail For Zoom");
+                //release the file held by decoder immediately.
+                iImageDecoder->Cancel();
+                delete iImageDecoder;
+                iImageDecoder = NULL;
+                //Inform the client that there is no decode happened and there we take care 
+                //of showing the fullscreen thumbnail.
+                iObserver->HandleBitmapDecodedL(iThumbnailIndex, NULL);
+                return;
+                }
+            }
+
+        SetActive();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// RunL
+// ---------------------------------------------------------------------------
+//
+void CGlxBitmapDecoderWrapper::RunL()
+    {
+    TRACER("CGlxBitmapDecoderWrapper::RunL()");
+    if( iStatus == KErrNone )
+        {
+        iObserver->HandleBitmapDecodedL(iThumbnailIndex,iBitmap);
+        iBitmap = NULL;
+
+        //release the file held by decoder immediately.
+        GLX_DEBUG1("CGlxBitmapDecoderWrapper::RunL:Decoding Finished");
+        iImageDecoder->Cancel();
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+#ifdef _DEBUG
+        iStopTime.HomeTime();
+        GLX_DEBUG2("*** Image Decode took <%d> us ***", 
+                       (TInt)iStopTime.MicroSecondsFrom(iStartTime).Int64());            
+#endif                          
+
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// DoCancel
+// ---------------------------------------------------------------------------
+//
+void CGlxBitmapDecoderWrapper::DoCancel()
+    {
+    TRACER("CGlxBitmapDecoderWrapper::DoCancel ");
+    if(iImageDecoder)
+        {
+        GLX_DEBUG1("CGlxBitmapDecoderWrapper::DoCancel iImageDecoder delete");
+        iImageDecoder->Cancel();
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+        }
+    if(iBitmap)
+        {
+        delete iBitmap;
+        iBitmap = NULL;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// OOMRequestFreeMemoryL
+// ---------------------------------------------------------------------------
+//
+TInt CGlxBitmapDecoderWrapper::OOMRequestFreeMemoryL(TInt aBytesRequested)
+    {
+    TRACER("CGlxBitmapDecoderWrapper::OOMRequestFreeMemoryL");
+    GLX_LOG_INFO1("CGlxBitmapDecoderWrapper::OOMRequestFreeMemoryL() "
+            "aBytesRequested=%d", aBytesRequested);
+    ROomMonitorSession oomMonitor;
+    User::LeaveIfError(oomMonitor.Connect());
+    // No leaving code after this point, so no need to use cleanup stack
+    // for oomMonitor
+    TInt errorCode = oomMonitor.RequestFreeMemory(aBytesRequested);
+    GLX_LOG_INFO1("CGlxBitmapDecoderWrapper::OOMRequestFreeMemoryL(1) "
+            "errorCode=%d",errorCode);
+    if (errorCode != KErrNone)
+        {
+        // try one more time 
+        errorCode = oomMonitor.RequestFreeMemory(aBytesRequested);
+        GLX_LOG_INFO1("CGlxBitmapDecoderWrapper::OOMRequestFreeMemoryL(2) "
+                "errorCode=%d",errorCode);
+        }
+    oomMonitor.Close();
+    return errorCode;
+    }
+
+// -----------------------------------------------------------------------------
+// DoesMimeTypeNeedsRecalculateL()
+// -----------------------------------------------------------------------------
+//
+TBool CGlxBitmapDecoderWrapper::DoesMimeTypeNeedsRecalculateL()
+    {
+    TRACER("CGlxBitmapDecoderWrapper::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("CGlxBitmapDecoderWrapper::DoesMimeTypeNeedsRecalculateL - jpeg");
+        return EFalse;
+        }
+    else
+        {
+        GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL - non jpeg");
+        return ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// ReCalculateSize 
+// -----------------------------------------------------------------------------
+TSize CGlxBitmapDecoderWrapper::ReCalculateSizeL()
+    {
+    TRACER("CGlxBitmapDecoderWrapper::ReCalculateSizeL()");
+    if (DoesMimeTypeNeedsRecalculateL())
+        {
+        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("CGlxBitmapDecoderWrapper::ReCalculateSizeL() "
+                        "destSize=%d, %d",destSize.iWidth,destSize.iHeight);
+        return destSize;
+        }
+    else
+        {
+        return iTargetBitmapSize;
+        }
+    }