diff -r 8e5f6eea9c9f -r 5b3385a43d68 photosgallery/viewframework/texturemanager/src/glxbitmapdecoderwrapper.cpp --- /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 // For Log +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + } + }