photosgallery/viewframework/dataprovider/src/glxdrmgiftexturecreator.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:32:09 +0300
branchRCL_3
changeset 75 01504893d9cb
parent 64 34937ec34dac
permissions -rw-r--r--
Revision: 201039 Kit: 201041

/*
 * 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"
#include <glxdrmutility.h>
#include <glximageviewermanager.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, MGlxMediaList& aMediaList)
    {
    TRACER("CGlxDrmGifTextureCreator* CGlxDrmGifTextureCreator::NewL()");
    CGlxDrmGifTextureCreator* self = new (ELeave) CGlxDrmGifTextureCreator(
            aBinding, aMedia, aItemIndex, aModel, aMediaList);
    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();
    if (iDrmUtility)
        {
        iDrmUtility->Close();
        }
    delete iGlxDecoderAO;
    iFsSession.Close();
    }

// -----------------------------------------------------------------------------
// ReleaseContent 
// -----------------------------------------------------------------------------
void CGlxDrmGifTextureCreator::ReleaseContent()
    {
    TRACER("void CGlxDrmGifTextureCreator::ReleaseContent()");
    iBitmapReady = EFalse;
    iAnimCount = 0;
    iAnimateFlag = EFalse;
    iTransparencyPossible = EFalse;
    iFrameShift = EFalse;

    //delete image viewer instance, if present.
    if ( iImageViewerInstance )
        {
        iImageViewerInstance->DeleteInstance();
        }
    
    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, MGlxMediaList& aMediaList) :
    iBinding(&aBinding), iMedia(&aMedia), iModel(aModel), iItemIndex(
            aItemIndex), iMediaList(aMediaList)
    {
    TRACER("CGlxDrmGifTextureCreator::CGlxDrmGifTextureCreator()");
    // Implement nothing here
    }

// -----------------------------------------------------------------------------
// ConstructL 
// -----------------------------------------------------------------------------
void CGlxDrmGifTextureCreator::ConstructL()
    {
    TRACER("CGlxDrmGifTextureCreator::ConstructL()");
    iUiUtility = CGlxUiUtility::UtilityL();
    User::LeaveIfError(iFsSession.Connect());
    
    //Create DRM Utility to check DRM rights validity 
    iDrmUtility = CGlxDRMUtility::InstanceL();
    // Create the active object
    iGlxDecoderAO = CGlxDRMgifDecoderAO::NewL(this);
    
    //Set the initial texture.And create and starts the Image Decoder
    SetInitialTextureAndStartDecodingL();
    }

// -----------------------------------------------------------------------------
// UpdateNewImageL 
// -----------------------------------------------------------------------------
void CGlxDrmGifTextureCreator::UpdateNewImageL(const TGlxMedia& aMedia,
        TInt aItemIndex)
    {
    TRACER("CGlxDrmGifTextureCreator::UpdateNewImageL()");
    GLX_LOG_INFO1("DrmGif: UpdateNewImageL() aItemIndex=%d", aItemIndex);
    
    //Start Decoding only if the aItemIndex refers to new Item index
    if (aItemIndex == iItemIndex)
        {
        //All textures were flushed when in background.
        //so, when app. comes to foreground again and DRM Rights have expired for 
        //current item, then create default Texture.
        if(iUiUtility->GetForegroundStatus() && IsDRMRightsExpiredL())
            {
            SetTexture();
            }
        return;
        }

    // First release the contents before proceeding further
    ReleaseContent();

    iItemIndex = aItemIndex;
    iMedia = &aMedia;

    //Set the initial texture.And create and starts the Image Decoder
    SetInitialTextureAndStartDecodingL();
    }

// -----------------------------------------------------------------------------
// SetInitialTextureAndStartDecodingL 
// -----------------------------------------------------------------------------
void CGlxDrmGifTextureCreator::SetInitialTextureAndStartDecodingL()
    {
    TRACER("CGlxDrmGifTextureCreator::SetInitialTextureAndStartDecodingL()");
    
    iBitmapReady = EFalse;
    iAnimCount = 0;
    iAnimateFlag = EFalse;
    iTransparencyPossible = EFalse;
    iFrameShift = EFalse;

    //Creates the image viewer instance, if not created already.
    iImageViewerInstance = CGlxImageViewerManager::InstanceL();    
    __ASSERT_ALWAYS(iImageViewerInstance, Panic(EGlxPanicNullPointer));
    
    //Set the initial texture, it could be default or the FS texture
    SetTexture();
#ifdef _DEBUG
    iStartTime.HomeTime();
#endif
    //Check if DRM Rights are not expired before starting image decoding
    if (!IsDRMRightsExpiredL())
        {
        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(iMediaList.Count())
        {
        const TGlxMedia media = iMediaList.Item(iItemIndex);

        if (iTransparencyPossible && !iFrameShift)
            {
            textureId
                    = (iUiUtility->GlxTextureManager().CreateDRMAnimatedGifTextureL(
                            media, media.IdSpaceId(), iAnimCount,
                            iDecodedBitmap[iAnimCount],
                            iDecodedMask[iAnimCount])).Id();
            }
        else
            {
            textureId
                    = (iUiUtility->GlxTextureManager().CreateDRMAnimatedGifTextureL(
                            media, media.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());
    if (iMediaList.Count())
        {
        iBinding->PopulateT(*item, iMediaList.Item(iItemIndex), ETrue, aTextureId);
        iModel->SetData(iItemIndex, item);
        }
    }

// -----------------------------------------------------------------------------
// IsDRMRightsExpiredL
// -----------------------------------------------------------------------------
//
TBool CGlxDrmGifTextureCreator::IsDRMRightsExpiredL()
    {
    TRACER("CGlxDrmGifTextureCreator::IsDRMRightsExpiredL");
    //To check if DRM rights are expired
    TBool expired = EFalse;
    TMPXGeneralCategory cat = iMedia->Category();
    
    if (iImageViewerInstance->IsPrivate())
        {
        expired = !iDrmUtility->DisplayItemRightsCheckL
                            (iImageViewerInstance->ImageFileHandle(),(cat == EMPXImage));
        }
    else
        {
        expired = !iDrmUtility->DisplayItemRightsCheckL(iMedia->Uri(), (cat == EMPXImage));
        }
    return expired;
    }