photosgallery/viewframework/dataprovider/src/glxdrmgiftexturecreator.cpp
branchRCL_3
changeset 26 5b3385a43d68
child 27 34937ec34dac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/viewframework/dataprovider/src/glxdrmgiftexturecreator.cpp	Wed Sep 01 12:33:26 2010 +0100
@@ -0,0 +1,500 @@
+/*
+ * 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:    DRM Gif Texture creator implementation
+ *
+ */
+
+#include <e32math.h>
+#include <imageconversion.h> 
+#include <glxtracer.h>
+#include <glxlog.h>
+#include <alf/ialfwidgeteventhandler.h>     //  The interface for event handlers used by widget controls
+#include <mul/imulmodel.h>                  // An interface for the data model
+#include <alf/alfutil.h>                        // AlfUtil
+#include <glxmedia.h>
+
+#include "glxtexturemanager.h"
+#include "glxbinding.h"
+#include "glxuiutility.h"
+#include "glxdrmgiftexturecreator.h"
+#include "glxdrmgifactivedecoder.h"
+
+// Default frame interval for animation, in microseconds
+const TInt KDefaultFrameInterval = 100000;
+
+// -----------------------------------------------------------------------------
+// NewLC
+// -----------------------------------------------------------------------------
+CGlxDrmGifTextureCreator* CGlxDrmGifTextureCreator::NewL(
+        const CGlxBinding& aBinding, const TGlxMedia& aMedia,
+        TInt aItemIndex, Alf::IMulModel* aModel)
+    {
+    TRACER("CGlxDrmGifTextureCreator* CGlxDrmGifTextureCreator::NewL()");
+    CGlxDrmGifTextureCreator* self = new (ELeave) CGlxDrmGifTextureCreator(
+            aBinding, aMedia, aItemIndex, aModel);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor 
+// -----------------------------------------------------------------------------
+CGlxDrmGifTextureCreator::~CGlxDrmGifTextureCreator()
+    {
+    TRACER("CGlxDrmGifTextureCreator::~CGlxDrmGifTextureCreator()");
+    ReleaseContent();
+
+    // Delete the animation timer
+    if (iAnimationTimer)
+        {
+        iAnimationTimer->Cancel();
+        delete iAnimationTimer;
+        }
+
+    iUiUtility->Close();
+
+    delete iGlxDecoderAO;
+
+    iFsSession.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// ReleaseContent 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::ReleaseContent()
+    {
+    TRACER("void CGlxDrmGifTextureCreator::ReleaseContent()");
+    iBitmapReady = EFalse;
+    iAnimCount = 0;
+    iAnimateFlag = EFalse;
+    iTransparencyPossible = EFalse;
+    iFrameShift = EFalse;
+
+    if (iGlxDecoderAO)
+        {
+        iGlxDecoderAO->Cancel();
+        }
+
+    if (iAnimationTimer)
+        {
+        iAnimationTimer->Cancel();
+        }
+
+    for (TInt i = 0; i < iFrameCount; i++)
+        {
+        GLX_LOG_INFO1("DrmGif: ReleaseContent() Releasing AnimBitmaps %d", i);
+        delete (iDecodedBitmap[i]);
+        iDecodedBitmap[i] = NULL;
+        delete (iDecodedMask[i]);
+        iDecodedMask[i] = NULL;
+        }
+
+    if (iUiUtility && iMedia)
+        {
+        iUiUtility->GlxTextureManager().RemoveTexture(iMedia->Id());
+        }
+
+    if (iImageDecoder)
+        {
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Constructor
+// -----------------------------------------------------------------------------
+CGlxDrmGifTextureCreator::CGlxDrmGifTextureCreator(
+        const CGlxBinding& aBinding, const TGlxMedia& aMedia,
+        TInt aItemIndex, Alf::IMulModel* aModel) :
+    iBinding(&aBinding), iMedia(&aMedia), iModel(aModel), iItemIndex(
+            aItemIndex)
+    {
+    TRACER("CGlxDrmGifTextureCreator::CGlxDrmGifTextureCreator()");
+    // Implement nothing here
+    }
+
+// -----------------------------------------------------------------------------
+// ConstructL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::ConstructL()
+    {
+    TRACER("CGlxDrmGifTextureCreator::ConstructL()");
+    iUiUtility = CGlxUiUtility::UtilityL();
+    User::LeaveIfError(iFsSession.Connect());
+    iBitmapReady = EFalse;
+    iAnimCount = 0;
+    iAnimateFlag = EFalse;
+    iTransparencyPossible = EFalse;
+    iFrameShift = EFalse;
+
+    //Set the initial texture, it could be default or the FS texture
+    SetTexture();
+    // Create the active object
+    iGlxDecoderAO = CGlxDRMgifDecoderAO::NewL(this);
+#ifdef _DEBUG
+    iStartTime.HomeTime();
+#endif	
+    CreateImageDecoderL(iMedia->Uri());
+    CreateBitmapAndStartDecodingL();
+    }
+
+// -----------------------------------------------------------------------------
+// UpdateNewImageL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::UpdateNewImageL(const TGlxMedia& aMedia,
+        TInt aItemIndex)
+    {
+    TRACER("CGlxDrmGifTextureCreator::UpdateNewImageL()");
+    GLX_LOG_INFO1("DrmGif: UpdateNewImageL() aItemIndex=%d", aItemIndex);
+    if (aItemIndex == iItemIndex)
+        {
+        return;
+        }
+
+    // First release the contents before proceeding further
+    ReleaseContent();
+
+    iItemIndex = aItemIndex;
+    iMedia = &aMedia;
+
+    iBitmapReady = EFalse;
+    iAnimCount = 0;
+    iAnimateFlag = EFalse;
+    iTransparencyPossible = EFalse;
+    iFrameShift = EFalse;
+
+    //Set the initial texture, it could be default or the FS texture
+    SetTexture();
+#ifdef _DEBUG
+    iStartTime.HomeTime();
+#endif
+    CreateImageDecoderL(iMedia->Uri());
+    CreateBitmapAndStartDecodingL();
+    }
+
+// -----------------------------------------------------------------------------
+// AnimateDRMGifItem 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::AnimateDRMGifItem(TBool aAnimate)
+    {
+    TRACER("CGlxDrmGifTextureCreator::AnimateDRMGifItem()");
+    if (!iAnimationTimer)
+        {
+        return;
+        }
+
+    if (aAnimate && iBitmapReady)
+        {
+        if (!iAnimationTimer->IsActive())
+            {
+            GLX_LOG_INFO1("DrmGif: AnimateDRMGifItem() - iAnimCount=%d", iAnimCount);
+            GLX_LOG_INFO1("DrmGif: AnimateDRMGifItem() - Frame Interval <%d> us",
+                    (TInt)iFrameInfo.iDelay.Int64());
+            TInt interval =((TInt)iFrameInfo.iDelay.Int64()) ? 
+                ((TInt)iFrameInfo.iDelay.Int64()) : KDefaultFrameInterval;
+            GLX_LOG_INFO1("DrmGif: AnimateDRMGifItem() interval=<%d> us", interval);
+            iAnimationTimer->Start(interval, interval, TCallBack(TimerCallbackL, this));
+            }
+        iAnimateFlag = ETrue;
+        }
+    else
+        {
+        if (iAnimationTimer->IsActive())
+            {
+            iAnimationTimer->Cancel();
+            iAnimateFlag = EFalse;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// RefreshL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::RefreshL()
+    {
+    TRACER("CGlxDrmGifTextureCreator::RefreshL()");
+    GLX_LOG_INFO2("DrmGif: RefreshL() iAnimCount=%d, iFrameShift=%d",
+            iAnimCount, iFrameShift);
+    TInt textureId = KErrNotFound;
+    if (iTransparencyPossible && !iFrameShift)
+        {
+        textureId
+                = (iUiUtility->GlxTextureManager().CreateDRMAnimatedGifTextureL(
+                        *iMedia, iMedia->IdSpaceId(), iAnimCount,
+                        iDecodedBitmap[iAnimCount], iDecodedMask[iAnimCount])).Id();
+        }
+    else
+        {
+        textureId
+                = (iUiUtility->GlxTextureManager().CreateDRMAnimatedGifTextureL(
+                        *iMedia, iMedia->IdSpaceId(), iAnimCount,
+                        iDecodedBitmap[iAnimCount], NULL)).Id();
+        }
+
+    SetTexture(textureId);
+    // Advance animation
+    iAnimCount++;
+    // if animation count is becoming maximum, then reset to animate again 
+    if (iAnimCount >= iFrameCount)
+        {
+        GLX_LOG_INFO("DrmGif: RefreshL() Reset iAnimCount");
+        iAnimCount = 0;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CreateBitmapAndStartDecodingL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::CreateBitmapAndStartDecodingL()
+    {
+    TRACER("CGlxDrmGifTextureCreator::CreateBitmapAndStartDecodingL()");
+    GLX_LOG_INFO1("CreateBitmapAndDecodingL() iAnimCount=%d", iAnimCount);
+    // Create the bitmap and mask as of original image size, and let the 
+    // coverflow widget do the scaling, if required.
+    // This is needed for the transparent gifs frames as the
+    // frame co-ordinates would mismatch if downscaling is applied.
+    TSize frameSize = iImageDecoder->FrameInfo(iAnimCount).iFrameSizeInPixels;
+    GLX_LOG_INFO3("DrmGif: CreateBitmapAndStartDecodingL() - Frame[%d] size=%d,%d",
+            iAnimCount, frameSize.iWidth, frameSize.iHeight);
+
+    iDecodedBitmap[iAnimCount] = new (ELeave) CFbsBitmap();
+    iDecodedBitmap[iAnimCount]->Create(frameSize,
+            iFrameInfo.iFrameDisplayMode);
+    User::LeaveIfNull(iDecodedBitmap[iAnimCount]);
+
+    if (iFrameInfo.iFlags & TFrameInfo::ETransparencyPossible)
+        {
+        iDecodedMask[iAnimCount] = new (ELeave) CFbsBitmap();
+        iDecodedMask[iAnimCount]->Create(frameSize, iFrameInfo.iFlags
+                & TFrameInfo::EAlphaChannel ? EGray256 : EGray2);
+        User::LeaveIfNull(iDecodedMask[iAnimCount]);
+
+        // decoding the image
+        iGlxDecoderAO->ConvertImageL(iDecodedBitmap[iAnimCount],
+                iDecodedMask[iAnimCount], iAnimCount, iImageDecoder);
+        iTransparencyPossible = ETrue;
+        }
+    else
+        {
+        // decoding the image
+        iGlxDecoderAO->ConvertImageL(iDecodedBitmap[iAnimCount], NULL,
+                iAnimCount, iImageDecoder);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// HandleRunL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::HandleRunL(TRequestStatus& aStatus)
+    {
+    TRACER("CGlxDrmGifTextureCreator::HandleRunL()");
+    TInt err = aStatus.Int();
+    GLX_LOG_INFO1("DrmGif: HandleRunL : err=%d", err);
+    if (err != KErrNone)
+        {
+        ReleaseContent();
+        return;
+        }
+
+    GLX_LOG_INFO2("DrmGif: HandleRunL() - Frame=%d/%d",
+            iAnimCount, iFrameCount-1);
+    if (iAnimCount > 0 && iAnimCount < iFrameCount)
+        {
+        TPoint point =
+                iImageDecoder->FrameInfo(iAnimCount).iFrameCoordsInPixels.iTl;
+        GLX_LOG_INFO2("DrmGif: HandleRunL() point=(%d, %d)",
+                point.iX, point.iY );
+        TSize frameSize = iImageDecoder->FrameInfo(iAnimCount).iFrameSizeInPixels;
+        GLX_LOG_INFO2("DrmGif: HandleRunL() - frameSize(%d, %d)",
+                frameSize.iWidth, frameSize.iHeight);
+        // Frame shift is checked,
+        // 1) If the subsequent frame sizes differ from the first frame (or)
+        // 2) If the subsequent frame co-ordinates differ from the first frame
+        if (point != iFrameInfo.iFrameCoordsInPixels.iTl
+                || iFrameInfo.iFrameSizeInPixels != frameSize)
+            {
+            iFrameShift = ETrue;
+            }
+
+        if (iFrameShift)
+            {
+            TSize firstFrameSize = iDecodedBitmap[0]->SizeInPixels();
+            GLX_LOG_INFO2("DrmGif: HandleRunL() - first bitmap size (%d, %d)",
+                    firstFrameSize.iWidth, firstFrameSize.iHeight);
+
+            TDisplayMode dispMode = iDecodedBitmap[0]->DisplayMode();
+            TInt scanLineLength = CFbsBitmap::ScanLineLength(
+                    firstFrameSize.iWidth, dispMode);
+
+            CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
+            CleanupStack::PushL(bitmap);
+            User::LeaveIfError(bitmap->Create(firstFrameSize, dispMode));
+            bitmap->LockHeap();
+            iDecodedBitmap[0]->LockHeap();
+            if (bitmap && bitmap->DataAddress())
+                {
+                memcpy((void*) bitmap->DataAddress(),
+                        (void*) iDecodedBitmap[0]->DataAddress(),
+                        scanLineLength * firstFrameSize.iHeight);
+                }
+            iDecodedBitmap[0]->UnlockHeap();
+            bitmap->UnlockHeap();
+
+            CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bitmap);
+            CleanupStack::PushL(bitmapDevice);
+
+            CFbsBitGc* bitmapGc = CFbsBitGc::NewL();
+            CleanupStack::PushL(bitmapGc);
+            bitmapGc->Activate(bitmapDevice);
+
+            if (iTransparencyPossible)
+                {
+                GLX_LOG_INFO("DrmGif: HandleRunL() BitBltMasked");
+                bitmapGc->BitBltMasked(point, iDecodedBitmap[iAnimCount],
+                        iOrigImageDimensions, iDecodedMask[iAnimCount],
+                        EFalse);
+                }
+            else
+                {
+                GLX_LOG_INFO("DrmGif: HandleRunL() BitBlt");
+                bitmapGc->BitBlt(point, iDecodedBitmap[iAnimCount]);
+                }
+
+            delete iDecodedBitmap[iAnimCount];
+            iDecodedBitmap[iAnimCount] = bitmap;
+            CleanupStack::PopAndDestroy(bitmapGc);
+            CleanupStack::PopAndDestroy(bitmapDevice);
+            CleanupStack::Pop(bitmap);
+            }
+        }
+
+    if (iAnimCount < iFrameCount - 1)
+        {
+        if (!iGlxDecoderAO->IsActive())
+            {
+            iAnimCount++;
+            CreateBitmapAndStartDecodingL();
+            }
+        }
+    else
+        {
+#ifdef _DEBUG
+        iStopTime.HomeTime();
+        GLX_LOG_INFO1("DrmGif: HandleRunL() ConvertImageL took <%d> us",
+                (TInt)iStopTime.MicroSecondsFrom(iStartTime).Int64());
+#endif
+        iBitmapReady = ETrue;
+        iAnimateFlag = ETrue;
+        iAnimCount = 0;
+        ProcessImageL();
+
+        //release imagedecoder after the conversion is over     
+        if (iImageDecoder)
+            {
+            delete iImageDecoder;
+            iImageDecoder = NULL;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// ProcessImageL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::ProcessImageL()
+    {
+    TRACER("CGlxDrmGifTextureCreator::ProcessImageL()");
+    RefreshL();
+    iAnimationTimer->Cancel();
+    if (iAnimateFlag)
+        {
+        GLX_LOG_INFO1("DrmGif: ProcessImageL() - Frame Interval <%d> us",
+                (TInt)iFrameInfo.iDelay.Int64());
+        TInt interval =((TInt)iFrameInfo.iDelay.Int64()) ? 
+            ((TInt)iFrameInfo.iDelay.Int64()) : KDefaultFrameInterval;
+        GLX_LOG_INFO1("DrmGif: ProcessImageL() interval=<%d> us", interval);
+        iAnimationTimer->Start(interval, interval, TCallBack(TimerCallbackL,
+                this));
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CreateImageDecoderL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::CreateImageDecoderL(const TDesC& aImageFile)
+    {
+    TRACER("CGlxDrmGifTextureCreator::CreateImageDecoderL()");
+    GLX_LOG_URI("DrmGif::CreateImageDecoderL(%S)", &aImageFile);
+
+    CImageDecoder::TOptions options =
+            (CImageDecoder::TOptions) (CImageDecoder::EOptionNoDither
+                    | CImageDecoder::EOptionAlwaysThread);
+    // Create a decoder for the image in the named file
+    TRAPD(error,iImageDecoder = CImageDecoder::FileNewL(iFsSession,
+                    aImageFile, options, KNullUid));
+    if (error != KErrNone)
+        {
+        User::Leave(error);
+        }
+    iFrameInfo = iImageDecoder->FrameInfo();
+    iOrigImageDimensions = iImageDecoder->FrameInfo().iOverallSizeInPixels;
+    GLX_LOG_INFO1("DrmGif::CreateImageDecoderL() - Gif Frame Interval <%d> us",
+            (TInt)iFrameInfo.iDelay.Int64());
+    iFrameCount = iImageDecoder->FrameCount();
+
+    // We are creating array of KGlxMaxFrameCount frames
+    // So re-setting the array-count with the no.
+    // It will animate till that no. of frames.
+    if (iFrameCount > KGlxMaxFrameCount)
+        {
+        iFrameCount = KGlxMaxFrameCount;
+        }
+    //dont create the timer if it is a singleframe.no need to animate
+    if (iFrameCount > 1)
+        {
+        iAnimationTimer = CPeriodic::NewL(CActive::EPriorityLow);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// TimerCallbackL 
+// -----------------------------------------------------------------------------
+TInt CGlxDrmGifTextureCreator::TimerCallbackL(TAny* aThis)
+    {
+    TRACER("CGlxDrmGifTextureCreator::TimerCallbackL()");
+    static_cast<CGlxDrmGifTextureCreator*> (aThis)->ProcessTimerEventL();
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// ProcessTimerEventL 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::ProcessTimerEventL()
+    {
+    TRACER("CGlxDrmGifTextureCreator::ProcessTimerEventL()");
+    ProcessImageL();
+    }
+
+// -----------------------------------------------------------------------------
+// SetTexture 
+// -----------------------------------------------------------------------------
+void CGlxDrmGifTextureCreator::SetTexture(TInt aTextureId)
+    {
+    TRACER("CGlxDrmGifTextureCreator::SetTexture()");
+    auto_ptr<MulVisualItem> item(new (EMM) MulVisualItem());
+    iBinding->PopulateT(*item, *iMedia, ETrue, aTextureId);
+    iModel->SetData(iItemIndex, item);
+    }