--- /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;
+ }
+ }