/*
* 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:
*
*/
#include <graphics/surface.h>
#include <graphics/surfacemanager.h>
#include <graphics/surfaceupdateclient.h>
#include <graphics/surface_hints.h>
#include <e32math.h>
#include <apgcli.h>
#include <imageconversion.h>
#include <fbs.h>
#include <glxtracer.h>
#include <glxlog.h>
#include <glxgeneraluiutilities.h>
#include "glxactivecallback.h"
#include "glxhdmisurfaceupdater.h"
#include "glxactivedecoder.h"
#include <bitdev.h>
const TInt KMulFactorToCreateBitmap = 4;
const TInt KZoomDelay = 10000;
//100 , is decide for 20 steps of zooming , with each step being 5 pixels.
const TInt KMaxZoomLimit = 100;
//evey time we zoom , there is a increase in the ht amd width by 10 pixels.
const TInt KSingleStepForZoom = 10;
_LIT(KMimeJpeg,"image/jpeg");
_LIT(KMimeJpg,"image/jpg");
// -----------------------------------------------------------------------------
// NewLC
// -----------------------------------------------------------------------------
CGlxHdmiSurfaceUpdater* CGlxHdmiSurfaceUpdater::NewL(RWindow* aWindow,
const TDesC& aImageFile, const TDesC& aNextImageFile,
CFbsBitmap* aFsBitmap, MGlxGenCallback* aCallBack,
MGlxHDMIDecoderObserver& aDecoderObserver)
{
TRACER("CGlxHdmiSurfaceUpdater* CGlxHdmiSurfaceUpdater::NewL()");
CGlxHdmiSurfaceUpdater* self = new (ELeave) CGlxHdmiSurfaceUpdater(
aWindow, aCallBack, aDecoderObserver);
CleanupStack::PushL(self);
self->ConstructL(aFsBitmap, aImageFile, aNextImageFile);
CleanupStack::Pop(self);
return self;
}
// -----------------------------------------------------------------------------
// destructor
// -----------------------------------------------------------------------------
CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater()
{
TRACER("CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater()");
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater()-EHdmiDisconnected");
TRAP_IGNORE(iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDisconnected));
ReleaseContent();
if (iWindow)
{
iWindow->RemoveBackgroundSurface(ETrue);
}
if (iTimer && iTimer->IsActive()) // Check for a CPeriodic Instance
{
iTimer->Cancel();
}
delete iTimer;
if (iGlxDecoderAO)
{
delete iGlxDecoderAO;
}
iGlxDecoderAO = NULL;
iFsSession.Close();
if (iSurfManager)
{
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater() - Close");
if (iSurfSessionConnected)
{
iSurfUpdateSession.Close();
}
if (iSurfChunk)
{
iSurfChunk->Close();
}
delete iSurfChunk;
iSurfChunk = NULL;
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater(). iSurfManager->CloseSurface()");
iSurfManager->CloseSurface(iSurfId);
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::~CGlxHdmiSurfaceUpdater(). iSurfManager->Close()");
iSurfManager->Close();
delete iSurfManager;
iSurfManager = NULL;
}
}
// -----------------------------------------------------------------------------
// ReleaseContent
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ReleaseContent()
{
TRACER("void CGlxHdmiSurfaceUpdater::ReleaseContent()");
if (iGlxDecoderAO)
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -1");
iGlxDecoderAO->Cancel();
}
if (iFsBitmap)
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -2");
delete iFsBitmap;
iFsBitmap = NULL;
}
for (TInt i = 0; i <= 2; i++)
{
GLX_LOG_INFO1("CGlxHdmiSurfaceUpdater::ReleaseContent() -3, %d", i);
delete iDecodedBitmap[i];
iDecodedBitmap[i] = NULL;
}
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -4");
if (iSurfBufferAO && iSurfBufferAO->IsActive())
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -5");
iSurfBufferAO->Cancel();
}
if (iImageDecoder)
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -6");
delete iImageDecoder;
iImageDecoder = NULL;
}
if (iSurfSessionConnected && iSurfManager)
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ReleaseContent() -7");
iSurfUpdateSession.CancelAllUpdateNotifications();
}
if (iImagePath)
{
delete iImagePath;
iImagePath = NULL;
}
}
// -----------------------------------------------------------------------------
// CTor
// -----------------------------------------------------------------------------
CGlxHdmiSurfaceUpdater::CGlxHdmiSurfaceUpdater(RWindow* aWindow,
MGlxGenCallback* aCallBack, MGlxHDMIDecoderObserver& aDecoderObserver) :
iWindow(aWindow), iCallBack(aCallBack), iShwFsThumbnail(ETrue),
iIsNonJpeg(EFalse), iDecoderObserver(aDecoderObserver)
{
TRACER("CGlxHdmiSurfaceUpdater::CGlxHdmiSurfaceUpdater()");
// Implement nothing here
}
// -----------------------------------------------------------------------------
// ConstructL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ConstructL(CFbsBitmap* aFsBitmap,
const TDesC& aImageFile, const TDesC& aNextImageFile)
{
TRACER("CGlxHdmiSurfaceUpdater::ConstructL()");
// Initiate the HDMI by assigning the necessary values
InitiateHdmiL(aFsBitmap, aImageFile, aNextImageFile);
TInt error = iFsSession.Connect();
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::ConstructL() FsSession Connect error = %d",
error);
User::LeaveIfError(error);
iShiftToCloning = EFalse;
iDecodingCurrent = EFalse;
iDecodingNext = EFalse;
iDecodingNextFailed = EFalse;
// Create the active object
iGlxDecoderAO = CGlxHdmiDecoderAO::NewL(this);
// Create the HDMI Decoder
CreateImageDecoderL();
// Create the Bitmap
CreateBitmapL();
// Create the surface and AO for updating the surface
TRAP_IGNORE( CreateHdmiL());
if (iSurfManager)
{
error = iSurfUpdateSession.Connect();
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::ConstructL() Surface update Session Connect error = %d",
error);
User::LeaveIfError(error);
iSurfSessionConnected = ETrue;
if (!aNextImageFile.Length())
{
ShowFsThumbnailL();
}
else
{
// Modify the surface position with respect to the buffer size
ModifySurfacePostion();
}
#ifdef _DEBUG
iStartTime.HomeTime();
#endif
//start decoding the image
iGlxDecoderAO->ConvertImageL(*iDecodedBitmap[EJpgDecodedBitmapIndex],
iImageDecoder);
iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingStarted);
iDecodingCurrent = ETrue;
}
iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
}
// -----------------------------------------------------------------------------
// UpdateNewImageL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::UpdateNewImageL(const TDesC& aImageFile,
const TDesC& aNextImageFile, CFbsBitmap* aFsBitmap)
{
TRACER("CGlxHdmiSurfaceUpdater::UpdateNewImageL()");
if (!aImageFile.CompareC(*iImagePath) && !iDecodingCurrent
&& !iDecodingNext)
{
iNextImagePath = aNextImageFile.Alloc();
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::UpdateNewImageL() - Decoded Image is ready ");
if (iDecodingNextFailed)
{
ShiftToCloningMode();
iDecodingNextFailed = EFalse;
}
else if (iSurfManager)
{
iShwFsThumbnail = EFalse;
if (iIsNonJpeg)
{
// if this is non jpeg image, make sure we scale the bitmap
ScaleDecodedBitmapL( ENonJpgDecodedBitmapIndex);
}
// Modify the surface position with respect to the buffer size
ModifySurfacePostion();
ProcessTvImage();
iWindow->SetBackgroundSurface(iConfig, ETrue);
iBitmapReady = ETrue;
return;
}
}
else
{
ReleaseContent();
if (iNextImagePath)
{
delete iNextImagePath;
iNextImagePath = NULL;
}
// Ongoing decoding is cancelled if any,reset the decoding flags.
iDecodingNext = EFalse;
iDecodingCurrent = EFalse;
}
// Initiate the HDMI by assigning the necessary values
InitiateHdmiL(aFsBitmap, aImageFile, aNextImageFile);
//Cancel the zoom timers if any
if (iTimer->IsActive())
{
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::UpdateNewImageL() - Cancel Timer");
iTimer->Cancel();
}
// Create the HDMI Decoder
CreateImageDecoderL();
// Create the Bitmap
CreateBitmapL();
if (iSurfManager)
{
// Create the surface and AO for updating the surface
CreateHdmiL( EFalse);
}
else
{
TRAP_IGNORE( CreateHdmiL(ETrue));
}
#ifdef _DEBUG
iStartTime.HomeTime();
#endif
if (iSurfManager)
{
// Show FS Thumbnail
ShowFsThumbnailL();
//start decoding the image
iGlxDecoderAO->ConvertImageL(*iDecodedBitmap[EJpgDecodedBitmapIndex],
iImageDecoder);
iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingStarted);
iDecodingCurrent = ETrue;
}
}
// -----------------------------------------------------------------------------
// InitiateHdmiL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::InitiateHdmiL(CFbsBitmap* aFsBitmap,
const TDesC& aImageFile, const TDesC& aNextImageFile)
{
TRACER("CGlxHdmiSurfaceUpdater::InitiateHdmiL()");
iImagePath = aImageFile.Alloc();
iNextImagePath = aNextImageFile.Alloc();
iFsBitmap = new (ELeave) CFbsBitmap;
iFsBitmap->Duplicate(aFsBitmap->Handle());
iIsNonJpeg = EFalse;
iTvScreenSize = iWindow->Size();
iBitmapReady = EFalse;
iLeftCornerForZoom.iX = 0;
iLeftCornerForZoom.iY = 0;
iZoom = ETrue;
}
// -----------------------------------------------------------------------------
// CreateHDMI
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::CreateHdmiL(TBool aCreateSurface)
{
TRACER("CGlxHdmiSurfaceUpdater::CreateHdmiL()");
if (aCreateSurface)
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::CreateHdmiL() Create Surface");
CreateSurfaceL();
}
// Active objects for double buffered draw signalling
if (!iSurfBufferAO)
{
iSurfBufferAO = new (ELeave) CGlxActiveCallBack(TCallBack(
SurfBuffer0ReadyL, this), CActive::EPriorityStandard - 1);
CActiveScheduler::Add( iSurfBufferAO);
}
}
// -----------------------------------------------------------------------------
// CreateSurfaceL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::CreateSurfaceL()
{
TRACER("CGlxHdmiSurfaceUpdater::CreateSurfaceL()");
iSurfManager = new (ELeave) RSurfaceManager();
TInt error = iSurfManager->Open();
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::CreateSurfaceL Open Surface manager error = %d",
error);
User::LeaveIfError(error);
//Need to set the surface Hint for the surface to indicate
//that photos do not need overscan compensation and the image will
//be displayed in 720p resolution.
//Refer error: HJVA-85DD25 for more info.
RSurfaceManager::THintPair surfHint;
TUid uid(KNullUid);
uid.iUid = surfaceHints::KSurfaceContent;
surfHint.Set(uid, surfaceHints::EStillImage, EFalse);
RSurfaceManager::TSurfaceCreationAttributesBuf attributes;
attributes().iPixelFormat = EUidPixelFormatARGB_8888;// EUidPixelFormatYUV_420Planar;
attributes().iSize = iTvScreenSize;
attributes().iBuffers = 1;
attributes().iStride = iTvScreenSize.iWidth * KMulFactorToCreateBitmap;
attributes().iAlignment = KMulFactorToCreateBitmap;
attributes().iContiguous = EFalse;
attributes().iMappable = ETrue;
attributes().iSurfaceHints = &surfHint;
attributes().iHintCount = 1;
error = iSurfManager->CreateSurface(attributes, iSurfId);
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::CreateSurfaceL, Creating surface error : %d",
error);
if (error == KErrNoMemory)
{
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::CreateSurfaceL(). iSurfManager->Close()");
iSurfManager->Close();
delete iSurfManager;
iSurfManager = NULL;
if (iShiftToCloning == EFalse)
{
GlxGeneralUiUtilities::ShowErrorNoteL(error); // Show Low Memory Popup Once before shifting to Cloning Mode
iShiftToCloning = ETrue;
}
ShiftToCloningMode(); // Shift from Posting Mode to Cloning Mode
}
User::LeaveIfError(error);
//Map the surface and stride the surface info
MapSurfaceL();
// Set the Configuration to the surface ID when creating a surface
iConfig.SetSurfaceId(iSurfId);
}
// -----------------------------------------------------------------------------
// MapSurfaceL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::MapSurfaceL()
{
TRACER("CGlxHdmiSurfaceUpdater::MapSurfaceL()");
//Create chunk to map it to the surface ID.
iSurfChunk = new (ELeave) RChunk();
User::LeaveIfNull( iSurfChunk);
TInt error = iSurfManager->MapSurface(iSurfId, *iSurfChunk);
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::MapSurfaceL(), MapSurface error : %d",
error);
User::LeaveIfError(error);
// Get the info from the surfaceManager
// and store pointers to the pixel data
RSurfaceManager::TInfoBuf info;
error = iSurfManager->SurfaceInfo(iSurfId, info);
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::MapSurfaceL(), SurfaceInfo error : %d",
error);
User::LeaveIfError(error);
iSurfaceStride = info().iStride;
TInt offset = 0;
iSurfManager->GetBufferOffset(iSurfId, 0, offset);
iSurfBuffer = iSurfChunk->Base() + offset;
}
// -----------------------------------------------------------------------------
// SurfBuffer0ReadyL
// -----------------------------------------------------------------------------
TInt CGlxHdmiSurfaceUpdater::SurfBuffer0ReadyL(TAny* aObject)
{
TRACER("CGlxHdmiSurfaceUpdater::SurfBuffer0ReadyL()");
CGlxHdmiSurfaceUpdater* self =
reinterpret_cast<CGlxHdmiSurfaceUpdater*> (aObject);
if (!self->iShwFsThumbnail)
{
self->iDecodingCurrent = EFalse;
if (self->iNextImagePath->Length())
{
self->DecodeNextImageL();
}
else
{
self->iDecoderObserver.HandleHDMIDecodingEventL(
EHdmiDecodingCompleted);
}
}
return ETrue;
}
// -----------------------------------------------------------------------------
// Refresh
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::Refresh()
{
TRACER("CGlxHdmiSurfaceUpdater::Refresh()");
// copy the decoded bitmap on to the surface
SwapBuffers();
// refresh the window
iCallBack->DoGenCallback();
}
// -----------------------------------------------------------------------------
// SwapBuffers
// This is used to sawp the buffers shown and to be shown
// After this is done, a refresh to the window should be done to refresh the TV
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::SwapBuffers()
{
TRACER("CGlxHdmiSurfaceUpdater::SwapBuffers()");
TInt bitmapIndex = KErrNotFound;
if (iShwFsThumbnail) // show FS thumbnail
{
bitmapIndex = EFSBitmapIndex;
}
else if (iIsNonJpeg && !iShwFsThumbnail) // this indicates it is non jpeg image and decoding finished
{
bitmapIndex = ENonJpgDecodedBitmapIndex;
}
else // if none of the above state means it is jpeg image and decoding finished
{
bitmapIndex = EJpgDecodedBitmapIndex;
}
// Lock the heap so that subsequent call to dataaddress doesnt happen
iDecodedBitmap[bitmapIndex]->LockHeap();
// Data stride
TUint fs = iDecodedBitmap[bitmapIndex]->DataStride();
//Bitmap address from where the data has to be copied.
TUint8* from = (TUint8*) iDecodedBitmap[bitmapIndex]->DataAddress();
//surface chunk address to where the bitmap data has to be copied.
TUint8* to = (TUint8*) iSurfBuffer;
// To buffer (32 bit colors)
TUint ts = iSurfaceStride;
//No of bytes to be copied on to the surface.
TUint bytes = iDecodedBitmap[bitmapIndex]->SizeInPixels().iWidth
* KMulFactorToCreateBitmap;
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::SwapBuffers() - decodeSize width = %d and height %d",
iDecodedBitmap[bitmapIndex]->SizeInPixels().iWidth,
iDecodedBitmap[bitmapIndex]->SizeInPixels().iHeight);
// Copy the bitmap on to the surface.
for (TInt y = iDecodedBitmap[bitmapIndex]->SizeInPixels().iHeight; y > 0; y--)
{
Mem::Copy(to, from, bytes);
to += ts;
from += fs;
}
iDecodedBitmap[bitmapIndex]->UnlockHeap();
}
// -----------------------------------------------------------------------------
// CreateBitmapL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::CreateBitmapL()
{
TRACER("CGlxHdmiSurfaceUpdater::CreateBitmapL()");
TSize imageSize = iImageDecoder->FrameInfo().iOverallSizeInPixels;
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::StartImageDecodeL() - bitmapsize=%d, %d",
imageSize.iWidth, imageSize.iHeight);
TReal32 scaleFactor = 0.0f;
if (iTvScreenSize.iWidth * imageSize.iHeight > iTvScreenSize.iHeight
* imageSize.iWidth)
{
scaleFactor = (TReal32) iTvScreenSize.iHeight
/ (TReal32) imageSize.iHeight;
}
else
{
scaleFactor = (TReal32) iTvScreenSize.iWidth
/ (TReal32) imageSize.iWidth;
}
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::StartImageDecodeL() - scaleFactor=%f",
scaleFactor);
iTargetBitmapSize.iHeight = imageSize.iHeight * scaleFactor;
iTargetBitmapSize.iWidth = imageSize.iWidth * scaleFactor;
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::StartImageDecodeL() - targetBitmapSize=%d, %d",
iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
//create the bitmap for the required size
iDecodedBitmap[EJpgDecodedBitmapIndex] = new (ELeave) CFbsBitmap();
// to check if the Mimetype is supported by the decoder to to arbitary scaling
// if not then we recalculate the size
TInt err = iDecodedBitmap[EJpgDecodedBitmapIndex]->Create(
ReCalculateSizeL(), EColor16MU);
User::LeaveIfNull( iDecodedBitmap[EJpgDecodedBitmapIndex]);
}
// -----------------------------------------------------------------------------
// DoesMimeTypeNeedsRecalculateL()
// -----------------------------------------------------------------------------
//
TBool CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL()
{
TRACER("CGlxHdmiSurfaceUpdater::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(
"CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL - jpeg");
return EFalse;
}
else
{
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::DoesMimeTypeNeedsRecalculateL - non jpeg");
return ETrue;
}
}
// -----------------------------------------------------------------------------
// ReCalculateSize
// -----------------------------------------------------------------------------
TSize CGlxHdmiSurfaceUpdater::ReCalculateSizeL()
{
TRACER("CGlxHdmiSurfaceUpdater::ReCalculateSizeL()");
if (DoesMimeTypeNeedsRecalculateL())
{
iIsNonJpeg = ETrue;
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(
"CGlxHdmiSurfaceUpdater::ReCalculateSizeL() - destSize=%d, %d",
destSize.iWidth, destSize.iHeight);
return destSize;
}
else
{
return iTargetBitmapSize;
}
}
// -----------------------------------------------------------------------------
// HandleRunL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::HandleRunL(TRequestStatus& aStatus)
{
TRACER("CGlxHdmiSurfaceUpdater::HandleRunL()");
#ifdef _DEBUG
iStopTime.HomeTime();
GLX_LOG_INFO1("CGlxHdmiSurfaceUpdater::HandleRunL() ConvertImageL took"
" <%d> us", (TInt)iStopTime.MicroSecondsFrom(iStartTime).Int64());
#endif
if (iDecodingNext)
{
iDecodingNext = EFalse;
if (aStatus.Int() != KErrNone)
{
GLX_LOG_INFO("HandleRunL - Next Convert failed");
iDecodingNextFailed = ETrue;
}
//Inform the observer that image decoding is completed
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::HandleRunL-EHdmiDecodingCompleted");
iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingCompleted);
}
else
{
iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingFirstCompleted);
if (aStatus.Int() != KErrNone)
{
GLX_LOG_INFO("HandleRunL - Convert failed");
ShiftToCloningMode();
}
else if (iSurfManager)
{
iShwFsThumbnail = EFalse;
if (iIsNonJpeg)
{
// if this is non jpeg image, make sure we scale the bitmap
ScaleDecodedBitmapL( ENonJpgDecodedBitmapIndex);
}
ProcessTvImage();
iBitmapReady = ETrue;
}
}
//release imagedecoder after the conversion is over
if (iImageDecoder)
{
delete iImageDecoder;
iImageDecoder = NULL;
}
}
// -----------------------------------------------------------------------------
// CreateImageDecoderL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::CreateImageDecoderL()
{
TRACER("CGlxHdmiController::CreateImageDecoderL()");
// Create a decoder for the image in the named file
TRAPD(error, iImageDecoder = CImageDecoder::FileNewL(iFsSession,
iImagePath->Des(), CImageDecoder::EOptionNone, KNullUid));
GLX_LOG_INFO1("CreateImageDecoderL CImageDecoder:FileNewL error %d",
error);
User::LeaveIfError( error);
}
// -----------------------------------------------------------------------------
// ActivateZoom
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ActivateZoom(TBool aAutoZoomOut)
{
TRACER("CGlxHdmiSurfaceUpdater::ActivateZoom()");
iZoom = ETrue;
iAutoZoomOut = aAutoZoomOut;
if (iTimer->IsActive())
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ActivateZoom() - Cancel Timer");
iTimer->Cancel();
}
if (!iTimer->IsActive() && iBitmapReady)
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::ActivateZoom() - Start Timer");
iTimer->Start(KZoomDelay, KZoomDelay, TCallBack(TimeOut, this));
}
}
// -----------------------------------------------------------------------------
// DeactivateZoom
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::DeactivateZoom()
{
TRACER("CGlxHdmiSurfaceUpdater::DeactivateZoom()");
if (iTimer->IsActive())
{
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::DeactivateZoom() - Cancel Timer");
iTimer->Cancel();
}
if (!iTimer->IsActive() && iBitmapReady && iLeftCornerForZoom.iX)
{
GLX_LOG_INFO("CGlxHdmiSurfaceUpdater::DeactivateZoom() - Start Timer");
iZoom = EFalse;
iTimer->Start(KZoomDelay, KZoomDelay, TCallBack(TimeOut, this));
}
}
// ---------------------------------------------------------------------------
// TimeOut
// ---------------------------------------------------------------------------
//
TInt CGlxHdmiSurfaceUpdater::TimeOut(TAny* aSelf)
{
TRACER("CGlxHdmiSurfaceUpdater::TimeOut");
if (aSelf)
{
CGlxHdmiSurfaceUpdater* self =
static_cast<CGlxHdmiSurfaceUpdater*> (aSelf);
if (self)
{
self->Zoom(ETrue);
}
}
return KErrNone;
}
// -----------------------------------------------------------------------------
// Zoom
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::Zoom(TBool aZoom)
{
TRACER("CGlxHdmiSurfaceUpdater::Zoom()");
if (!iBitmapReady)
{
return;
}
if (iLeftCornerForZoom.iX == KMaxZoomLimit)
{
iZoom = EFalse;
//If autozoomout is not set then cancel the timer and do
//the zoom out on DeactivateZoom.
if (!iAutoZoomOut)
{
iTimer->Cancel();
}
}
if (aZoom && iZoom)
{
iTargetBitmapSize.iWidth = TInt(iTargetBitmapSize.iWidth
- KSingleStepForZoom);
iTargetBitmapSize.iHeight = TInt(iTargetBitmapSize.iHeight
- KSingleStepForZoom);
iLeftCornerForZoom.iX = iLeftCornerForZoom.iX + KSingleStepForZoom
/ 2;
iLeftCornerForZoom.iY = iLeftCornerForZoom.iY + KSingleStepForZoom
/ 2;
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::Zoom()--- 2,iTargetBitmapSize.iWidth = %d, iTargetBitmapSize.iHeight = %d",
iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
iConfig.SetViewport(TRect(iLeftCornerForZoom.iX,
iLeftCornerForZoom.iY, iTargetBitmapSize.iWidth,
iTargetBitmapSize.iHeight));
}
else
{
iTargetBitmapSize.iWidth = TInt(iTargetBitmapSize.iWidth
+ KSingleStepForZoom);
iTargetBitmapSize.iHeight = TInt(iTargetBitmapSize.iHeight
+ KSingleStepForZoom);
iLeftCornerForZoom.iX = iLeftCornerForZoom.iX - KSingleStepForZoom
/ 2;
iLeftCornerForZoom.iY = iLeftCornerForZoom.iY - KSingleStepForZoom
/ 2;
if (iLeftCornerForZoom.iX == 0)
{
iTimer->Cancel();
iZoom = ETrue;
}
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::Zoom()--- 4,iTargetBitmapSize.iWidth = %d, iTargetBitmapSize.iHeight = %d",
iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
iConfig.SetViewport(TRect(iLeftCornerForZoom.iX,
iLeftCornerForZoom.iY, iTargetBitmapSize.iWidth,
iTargetBitmapSize.iHeight));
}
iWindow->SetBackgroundSurface(iConfig, ETrue);
}
// -----------------------------------------------------------------------------
// ModifySurfacePostion
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ModifySurfacePostion()
{
TRACER("CGlxHdmiSurfaceUpdater::ModifySurfacePostion()");
TPoint startPoint(0, 0);
if (iTargetBitmapSize.iWidth < iTvScreenSize.iWidth)
{
startPoint.iX = (iTvScreenSize.iWidth - iTargetBitmapSize.iWidth) / 2;
}
if (iTargetBitmapSize.iHeight < iTvScreenSize.iHeight)
{
startPoint.iY = (iTvScreenSize.iHeight - iTargetBitmapSize.iHeight)
/ 2;
}
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - target iTargetBitmapSize=%d, %d",
iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - startPoint =%d, %d",
startPoint.iX, startPoint.iY);
// target
iConfig.SetExtent(TRect(startPoint.iX, startPoint.iY,
(iTvScreenSize.iWidth - startPoint.iX), (iTvScreenSize.iHeight
- startPoint.iY)));
// source
iConfig.SetViewport(TRect(TPoint(0, 0), TSize(iTargetBitmapSize.iWidth,
iTargetBitmapSize.iHeight)));
#ifdef _DEBUG
TRect ex, vp;
iConfig.GetExtent(ex);
iConfig.GetViewport(vp);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - vp - TL=%d, %d",vp.iTl.iX,vp.iTl.iY);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - vp - BR=%d, %d",vp.iBr.iX,vp.iBr.iY);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - ex - TL=%d, %d",ex.iTl.iX,ex.iTl.iY);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ModifySurfacePostion() - ex - BR=%d, %d",ex.iBr.iX,ex.iBr.iY);
#endif
}
// -----------------------------------------------------------------------------
// ShiftToCloningMode
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ShiftToCloningMode()
{
TRACER("CGlxHdmiSurfaceUpdater::ShiftToCloningMode()");
iWindow->RemoveBackgroundSurface(ETrue);
}
// -----------------------------------------------------------------------------
// ShiftToPostingMode
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ShiftToPostingMode()
{
TRACER("CGlxHdmiSurfaceUpdater::ShiftToPostingMode()");
if (iSurfManager)
{
#ifdef _DEBUG
TRect ex, vp;
iConfig.GetExtent(ex);
iConfig.GetViewport(vp);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - vp - TL=%d, %d",vp.iTl.iX,vp.iTl.iY);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - vp - BR=%d, %d",vp.iBr.iX,vp.iBr.iY);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - ex - TL=%d, %d",ex.iTl.iX,ex.iTl.iY);
GLX_LOG_INFO2("CGlxHdmiSurfaceUpdater::ShiftToPostingMode() - ex - BR=%d, %d",ex.iBr.iX,ex.iBr.iY);
#endif
iWindow->SetBackgroundSurface(iConfig, ETrue);
iShiftToCloning = EFalse;
}
}
// -----------------------------------------------------------------------------
// ShowFsThumbnailL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ShowFsThumbnailL()
{
TRACER("CGlxHdmiSurfaceUpdater::ShowFsThumbnailL()");
iShwFsThumbnail = ETrue;
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::ShowFsThumbnailL() iTargetBitmapSize Width=%d, Height=%d",
iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
// Modify the surface position with respect to the buffer size
ModifySurfacePostion();
// this is for FS thumbnail stored in array pointer 0
ScaleDecodedBitmapL( EFSBitmapIndex);
// Process the Image to TV
ProcessTvImage();
// set the surface onto background
iWindow->SetBackgroundSurface(iConfig, ETrue);
}
// -----------------------------------------------------------------------------
// ScaleDecodedBitmapL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL(TInt aBitmapIndex)
{
TRACER("CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL()");
GLX_LOG_INFO2(
"CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL() iTargetBitmapSize Width=%d, Height=%d",
iTargetBitmapSize.iWidth, iTargetBitmapSize.iHeight);
if (iDecodedBitmap[aBitmapIndex])
{
delete iDecodedBitmap[aBitmapIndex];
iDecodedBitmap[aBitmapIndex] = NULL;
}
iDecodedBitmap[aBitmapIndex] = new (ELeave) CFbsBitmap();
// create destination with size
TInt err = iDecodedBitmap[aBitmapIndex]->Create(iTargetBitmapSize,
EColor16MU);
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::ScaleDecodedBitmapL() creating bitmap error, err=%d",
err);
User::LeaveIfNull( iDecodedBitmap[aBitmapIndex]);
// Create bitmap device for destination bitmap
CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(
iDecodedBitmap[aBitmapIndex]);
CleanupStack::PushL(bitmapDevice);
CFbsBitGc* bitmapGc = CFbsBitGc::NewL();
CleanupStack::PushL(bitmapGc);
bitmapGc->Activate(bitmapDevice);
if (aBitmapIndex == EFSBitmapIndex)
{
// scale the source bitmap which is a FS bitmap
bitmapGc->DrawBitmap(TRect(iTargetBitmapSize), iFsBitmap);
}
else
{
// scale the source bitmap which is a decoded bitmap
bitmapGc->DrawBitmap(TRect(iTargetBitmapSize),
iDecodedBitmap[EJpgDecodedBitmapIndex]);
}
CleanupStack::PopAndDestroy(bitmapGc);
CleanupStack::PopAndDestroy(bitmapDevice);
}
// -----------------------------------------------------------------------------
// ProcessTvImage
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::ProcessTvImage()
{
TRACER("CGlxHdmiSurfaceUpdater::ProcessTvImage()");
if (iSurfBufferAO->iStatus != KRequestPending
&& !iSurfBufferAO->IsActive())
{
Refresh();
iSurfBufferAO->iStatus = KRequestPending;
iSurfBufferAO->SetActive();
iSurfUpdateSession.NotifyWhenAvailable(iSurfBufferAO->iStatus);
TInt err = iSurfUpdateSession.SubmitUpdate(1, iSurfId, 0, NULL);
GLX_LOG_INFO1(
"CGlxHdmiSurfaceUpdater::ProcessTvImage() Surfaceupdatesession error %d",
err);
}
}
// -----------------------------------------------------------------------------
// DecodeNextImageL
// -----------------------------------------------------------------------------
void CGlxHdmiSurfaceUpdater::DecodeNextImageL()
{
TRACER("CGlxHdmiSurfaceUpdater::DecodeNextImageL()");
ReleaseContent();
iImagePath = iNextImagePath->Alloc();
if (iNextImagePath)
{
delete iNextImagePath;
iNextImagePath = NULL;
}
iIsNonJpeg = EFalse;
GLX_LOG_INFO("Before - iWindow->Size()");
iTvScreenSize = iWindow->Size();
GLX_LOG_INFO("After - iWindow->Size()");
iBitmapReady = EFalse;
iLeftCornerForZoom.iX = 0;
iLeftCornerForZoom.iY = 0;
iZoom = ETrue;
//Cancel the zoom timers if any
if (iTimer && iTimer->IsActive())
{
GLX_LOG_INFO(
"CGlxHdmiSurfaceUpdater::UpdateNewImageL() - Cancel Timer");
iTimer->Cancel();
}
// Create the HDMI Decoder
CreateImageDecoderL();
// Create the Bitmap
CreateBitmapL();
if (iSurfManager)
{
// Create the surface and AO for updating the surface
CreateHdmiL( EFalse);
}
else
{
TRAP_IGNORE( CreateHdmiL(ETrue));
}
#ifdef _DEBUG
iStartTime.HomeTime();
#endif
if (iSurfManager)
{
//start decoding the image
iGlxDecoderAO->ConvertImageL(*iDecodedBitmap[EJpgDecodedBitmapIndex],
iImageDecoder);
iDecodingNext = ETrue;
iDecodingNextFailed = EFalse;
//Inform the Observer that decoding has started
iDecoderObserver.HandleHDMIDecodingEventL(EHdmiDecodingStarted);
}
}