imagingandcamerafws/imagingfws/ImageDisplay/plugins/IclWrapper/GenericIclWrapper.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent 
       
    19 */
       
    20 
       
    21 
       
    22 #include "GenericIclWrapper.h"
       
    23 #include <icl/imagedisplaypaniccodes.h>
       
    24 #include "MiscUtils.h"
       
    25 
       
    26 #include "ExifImageDisplayPanic.h"
       
    27 
       
    28 #define KZeroDelay TTimeIntervalMicroSeconds(0)
       
    29 _LIT(KGenIclWrapperPanicCategory, "GenIclWrapperImgDisplay");
       
    30 
       
    31 CGenericImageDisplayPlugin* CGenericImageDisplayPlugin::NewL()
       
    32 	{
       
    33 	CGenericImageDisplayPlugin* self = new(ELeave) CGenericImageDisplayPlugin(KGenIclWrapperPanicCategory);
       
    34 	CleanupStack::PushL(self);
       
    35 	self->ConstructL();
       
    36 	CleanupStack::Pop(self);
       
    37 	return self;
       
    38 	}
       
    39 
       
    40 void CGenericImageDisplayPlugin::ConstructL()
       
    41 	{
       
    42 	User::LeaveIfError( iFs.Connect() );
       
    43 	iPlayer		= new (ELeave) CImagePlayer(*this);
       
    44 	iDelayedCb	= CDelayedCallback::NewL(*this);
       
    45 	}
       
    46 
       
    47 CGenericImageDisplayPlugin::~CGenericImageDisplayPlugin()
       
    48 	{
       
    49 	if (iTransformer != NULL)
       
    50 		{
       
    51 		iTransformer->Cancel();
       
    52 		delete iTransformer;
       
    53 		}
       
    54 	if (iMaskTransformer != NULL)
       
    55 		{
       
    56 		iMaskTransformer->Cancel();
       
    57 		delete iMaskTransformer;
       
    58 		}
       
    59 	
       
    60 	delete iDelayedCb;
       
    61 	delete iPlayer;
       
    62 	delete iDecoder;
       
    63 	iFs.Close();
       
    64 	}
       
    65 
       
    66 CGenericImageDisplayPlugin::CGenericImageDisplayPlugin(const TDesC& aPanicCategoryStr):
       
    67 							iPanicCategory(aPanicCategoryStr),
       
    68 							iMaxReductionFactor(KMaxReductionFactor),
       
    69 							iMaxUnscaledSize(KMaxTInt,KMaxTInt),
       
    70 							iExtHandler(*this),
       
    71 							iScaleQuality(-1),
       
    72 							iPluginImgStatus(CImageDisplay::EImageTypeUnknown)
       
    73 	{
       
    74 	}
       
    75 
       
    76 void CGenericImageDisplayPlugin::Panic(TInt aPanicNumber) const
       
    77 	{
       
    78 	User::Panic(iPanicCategory, aPanicNumber);
       
    79 	}
       
    80 
       
    81 void CGenericImageDisplayPlugin::OpenL()
       
    82 	{
       
    83 	iValidBitmap = EFalse;
       
    84 	const TUint option=(Options() & (CImageDisplay::EOptionThumbnail|CImageDisplay::EOptionMainImage));
       
    85 	if (option==CImageDisplay::EOptionsUndefined || 
       
    86 			option == (CImageDisplay::EOptionThumbnail|CImageDisplay::EOptionMainImage))
       
    87 		{
       
    88 		User::Leave(KErrNotSupported);
       
    89 		}
       
    90 
       
    91 	switch ( SourceType() )
       
    92 		{
       
    93 		case CImageDisplayPlugin::EImgSrcFileName:
       
    94 			{
       
    95 			
       
    96 			TMMFileSource src(SourceFilename(), SourceDataId(), SourceDataIntent());
       
    97 			iDecoder = CImageDecoder::FileNewL(iFs, src, CImageDecoder::EAllowGeneratedMask, KNullUid, KNullUid, RequiredImageClass());
       
    98 			}
       
    99 			break;
       
   100 
       
   101 		case CImageDisplayPlugin::EImgSrcFileHandle:
       
   102 			{
       
   103 			TMMFileHandleSource src(SourceFileHandle(), SourceDataId(), SourceDataIntent());
       
   104 			iDecoder = CImageDecoder::FileNewL(iFs, src, CImageDecoder::EAllowGeneratedMask, KNullUid, KNullUid, RequiredImageClass());
       
   105 			}
       
   106 			break;
       
   107 
       
   108 		case CImageDisplayPlugin::EImgSrcDescriptor:
       
   109 			iDecoder = CImageDecoder::DataNewL(iFs, SourceData(), CImageDecoder::EAllowGeneratedMask, KNullUid, KNullUid, RequiredImageClass());
       
   110 			break;
       
   111 
       
   112 		default:
       
   113 			ASSERT(EFalse);
       
   114 			User::Leave(KErrArgument);
       
   115 		}
       
   116 	iValidBitmap		= EFalse;
       
   117 	iImageIsThumbnail	= (option==CImageDisplay::EOptionThumbnail);
       
   118 
       
   119 	if (iImageIsThumbnail)
       
   120 		{
       
   121 		iDecoder->SetImageTypeL(CImageDecoder::EImageTypeThumbnail ); // leaves if there is no thumbnail
       
   122 		}
       
   123 
       
   124 	AfterOpenL(); // allow derived plug-in to perform some initialization
       
   125 	iRotationOptions = EffectiveRotation();
       
   126 	FillRecommendedSizesL();
       
   127 	CacheImageStatus();
       
   128 	}
       
   129 
       
   130 void CGenericImageDisplayPlugin::Play()
       
   131 	{
       
   132 	iIsPaused = EFalse;
       
   133 	if (iCallBackIsPending)
       
   134 		{
       
   135 		iDelayedCb->CallAfter(KZeroDelay);
       
   136 		iCallBackIsPending = EFalse;
       
   137 		return;
       
   138 		}
       
   139 	if (IsStatusSet(EStatusNoMoreToDecode))
       
   140 		{
       
   141 		ASSERT(IsStatusSet(EStatusPaused)==EFalse);
       
   142 		if (iState < EInitCompleted)
       
   143 			{
       
   144 			Panic(EPanicNotInitialized);
       
   145 			}
       
   146 		if (iValidBitmap && iLastError==KErrNone)
       
   147 			{
       
   148 			ClearStatusFlag(EStatusPaused|EStatusBusy);
       
   149 			iDelayedCb->CallAfter(KZeroDelay);
       
   150 			return;
       
   151 			}
       
   152 		ClearStatusFlag(EStatusNoMoreToDecode);
       
   153 		iState = EInitCompleted;
       
   154 		}
       
   155 	else if (IsStatusSet(EStatusPaused)==EFalse && iState>=EInitCompleted)
       
   156 		{
       
   157 		if (iState==EInitCompleted && IsStatusSet(EStatusBusy)==EFalse)
       
   158 			{
       
   159 			iPlayer->Play(*iDecoder, EffectiveDispMode(), (iImageIsThumbnail? 1 : CImagePlayer::KNoFrameLimit) );
       
   160 			iState = EProcessing;
       
   161 			}
       
   162 		return;
       
   163 		}
       
   164 
       
   165 	ClearStatusFlag(EStatusPaused|EStatusNoMoreToDecode|EStatusBusy);
       
   166 	switch (iState)
       
   167 		{
       
   168 		case EIdle:
       
   169 			TRAPD(err,	
       
   170 						CompleteInitL();
       
   171 				);
       
   172 			iOutputRect=TRect(0,0,DestinationSizeInPixels().iWidth, DestinationSizeInPixels().iHeight);
       
   173 			if (err != KErrNone)
       
   174 				{
       
   175 				AsyncCallbackImageReady(NULL, EStatusNoMoreToDecode, iOutputRect, err);
       
   176 				iState = EInitFailed;
       
   177 				return;
       
   178 				}
       
   179 			iPlayer->Play(*iDecoder, EffectiveDispMode(), (iImageIsThumbnail? 1 : CImagePlayer::KNoFrameLimit) );
       
   180 			iState = EProcessing;
       
   181 			break;
       
   182 
       
   183 		case EInitFailed:
       
   184 			Panic(EPanicInitFailed);
       
   185 			break;
       
   186 
       
   187 		case EInitCompleted:
       
   188 		case EProcessing:
       
   189 			iPlayer->Resume();
       
   190 			iState = EProcessing;
       
   191 			break;
       
   192 
       
   193 		case ETransforming:
       
   194 			iTransformer->Restart();
       
   195 			break;
       
   196 
       
   197 		case ETransformingMask:
       
   198 			iMaskTransformer->Restart();
       
   199 			break;
       
   200 
       
   201 		default:
       
   202 			ASSERT(EFalse);
       
   203 		}
       
   204 	
       
   205 	SetStatusFlag(EStatusBusy);
       
   206 	}
       
   207 
       
   208 void CGenericImageDisplayPlugin::Pause()
       
   209 	{
       
   210 	if (iIsPaused)
       
   211 		{
       
   212 		return;
       
   213 		}
       
   214 	if ( CallbackIsRunning() )
       
   215 		{
       
   216 		CancelCallback();
       
   217 		// actually the framework may not be able to cancel the callback
       
   218 		// if the execution point has already passed to the client code and it yielded to AS somehow
       
   219 		// so we check if the callback was actually cancelled by trying it after cancel attempt
       
   220 		iCallBackIsPending = !CallbackIsRunning(); 
       
   221 		}
       
   222 	else
       
   223 		{
       
   224 		if (iTransformer != NULL && iState == ETransforming)
       
   225 			{
       
   226 			iTransformer->Cancel();
       
   227 			}
       
   228 		else if (iMaskTransformer != NULL  && iState == ETransformingMask)
       
   229 			{
       
   230 			iMaskTransformer->Cancel();
       
   231 			}
       
   232 		else
       
   233 			{
       
   234 			iPlayer->Pause();
       
   235 			}
       
   236 		if (!IsStatusSet(EStatusNoMoreToDecode))
       
   237 			{
       
   238 			SetStatusFlag(EStatusPaused);
       
   239 			iIsPaused = ETrue;
       
   240 			}			
       
   241 		}			
       
   242 	ClearStatusFlag(EStatusBusy);
       
   243 	}
       
   244 
       
   245 void CGenericImageDisplayPlugin::StopPlay()
       
   246 	{
       
   247 	CancelCallback();
       
   248 	iNextFrameDelay	= 0;
       
   249 	iIsPaused		= EFalse;
       
   250 	iValidBitmap	= EFalse;
       
   251 	iCallBackIsPending = EFalse;
       
   252 	if (iState >= EInitCompleted)
       
   253 		{
       
   254 		iState = EInitCompleted;
       
   255 		}
       
   256 	if (iTransformer != NULL)
       
   257 		{
       
   258 		iTransformer->Cancel();
       
   259 		}
       
   260 	if (iMaskTransformer != NULL)
       
   261 		{
       
   262 		iMaskTransformer->Cancel();
       
   263 		}
       
   264 	if (iPlayer != NULL)
       
   265 		{
       
   266 		iPlayer->Cancel();
       
   267 		}
       
   268 	if (iDelayedCb != NULL)
       
   269 		{
       
   270 		iDelayedCb->Cancel();
       
   271 		}
       
   272 	ClearStatusFlag(EStatusBusy|EStatusPaused);
       
   273 	}
       
   274 
       
   275 void CGenericImageDisplayPlugin::GetBitmap(const CFbsBitmap*& aBitmap, const CFbsBitmap*& aMask) const
       
   276 	{
       
   277 	if (iState < EInitCompleted)
       
   278 		{
       
   279 		Panic(EPanicNotInitialized);
       
   280 		}
       
   281 	if (ValidBitmap())
       
   282 		{
       
   283 		aBitmap = iCurrentFrame;
       
   284 		aMask	= iCurrentMask;
       
   285 		}
       
   286 	else
       
   287 		{
       
   288 		aBitmap = NULL;
       
   289 		aMask	= NULL;
       
   290 		}
       
   291 	}
       
   292 	
       
   293 const CImageDisplay::RImageSizeArray& CGenericImageDisplayPlugin::RecommendedImageSizes() const
       
   294 	{
       
   295 	return iImageSizes;
       
   296 	}
       
   297 
       
   298 TInt CGenericImageDisplayPlugin::NumFrames(TInt& aNumFrames) const
       
   299 	{
       
   300 	if (iDecoder->IsImageHeaderProcessingComplete())
       
   301 		{
       
   302 		aNumFrames = iDecoder->FrameCount();
       
   303 		return KErrNone;
       
   304 		}
       
   305 	aNumFrames = -1;
       
   306 	return KErrNotReady;
       
   307 	}
       
   308 
       
   309 TUint CGenericImageDisplayPlugin::ImageStatus() const
       
   310 	{
       
   311 	return iPluginImgStatus;
       
   312 	}
       
   313 
       
   314 TBool CGenericImageDisplayPlugin::ValidBitmap() const
       
   315 	{
       
   316 	return iValidBitmap;
       
   317 	}
       
   318 
       
   319 void CGenericImageDisplayPlugin::CacheImageStatus()
       
   320 	{
       
   321 	TInt numFrames;
       
   322 	iPluginImgStatus=(NumFrames(numFrames)==KErrNone && numFrames > 1)? CImageDisplay::EImageMultiFrame : CImageDisplay::EImageSingleFrame;
       
   323 	for (TInt i=0; i<numFrames; ++i)
       
   324 		{
       
   325 		if (iDecoder->FrameInfo(i).iDelay.Int64() != 0)
       
   326 			{
       
   327 			iPluginImgStatus|= CImageDisplay::EImageAnimated;
       
   328 			if (iImageHasFloatingSubImgs)
       
   329 				{
       
   330 				break;
       
   331 				}
       
   332 			}
       
   333 		if (iDecoder->FrameInfo(i).iFrameCoordsInPixels != iDecoder->FrameInfo(0).iFrameCoordsInPixels)
       
   334 			{
       
   335 			iImageHasFloatingSubImgs = ETrue;
       
   336 			if (iPluginImgStatus & CImageDisplay::EImageAnimated)
       
   337 				{
       
   338 				break;
       
   339 				}
       
   340 			}
       
   341 		}
       
   342 	iPluginImgStatus|=((iDecoder->FrameInfo().iFlags&TFrameInfo::ETransparencyPossible) ? CImageDisplay::EImageMasked : 0);
       
   343 	iPluginImgStatus|=(ThumbnailExists()?CImageDisplay::EImageHasThumbnail : 0);
       
   344 	iPluginImgStatus|=((iDecoder->FrameInfo().iFlags&TFrameInfo::EFullyScaleable)?CImageDisplay::EImageIsFullyScalable : 0);
       
   345 	}
       
   346 
       
   347 void CGenericImageDisplayPlugin::OnPlayEvent(TInt aErrorCode, TUint aEventFlags, CFbsBitmap* aFrame, CFbsBitmap* aMask)
       
   348 	{
       
   349 	ASSERT(IsStatusSet(EStatusPaused)==EFalse);
       
   350 	iLastError = aErrorCode;
       
   351 	if (aErrorCode == KErrNone)
       
   352 		{
       
   353 		iValidBitmap	= EFalse;
       
   354 		iPluginStatus	= aEventFlags;
       
   355 		iCurrentMask	= aMask;
       
   356 		if (iTransformer != NULL ) 
       
   357 			{
       
   358 			SetStatusFlag(EStatusBusy);
       
   359 			iState = ETransforming;
       
   360 			iTransformer->Singleton().SetTrueSrcSize( iPlayer->OriginalFrameSize() );
       
   361 			iTransformer->Transform(aFrame, MaintainAspectRatio());
       
   362 			}
       
   363 		else
       
   364 			{
       
   365 			iValidBitmap	= ETrue;
       
   366 			iCurrentFrame	= aFrame;
       
   367 			ClearStatusFlag(EStatusBusy);
       
   368 			if ((aEventFlags&EStatusNoMoreToDecode)==0)
       
   369 				{
       
   370 				SetStatusFlag(EStatusPaused);	
       
   371 				}
       
   372 			const TTimeIntervalMicroSeconds delay(iNextFrameDelay);
       
   373 			iNextFrameDelay = iPlayer->CurrentFrameInfo().iDelay;
       
   374 			iDelayedCb->CallAfter(delay);
       
   375 			}
       
   376 		}
       
   377 	else	
       
   378 		{
       
   379 		iState = EInitFailed;
       
   380 		iPluginStatus = EStatusNoMoreToDecode;
       
   381 		iCurrentFrame = NULL;
       
   382 // we've got error, so there is no need to go via delayed callback
       
   383 		AsyncCallbackImageReady(iCurrentFrame, iPluginStatus, iOutputRect, aErrorCode);
       
   384 		}
       
   385 	}
       
   386 
       
   387 void CGenericImageDisplayPlugin::OnTransformDone(TInt aError)
       
   388 	{
       
   389 	TTimeIntervalMicroSeconds delay(0);
       
   390 	if (aError == KErrNone)
       
   391 		{
       
   392 		if (iCurrentMask != NULL && iState == ETransforming)
       
   393 			{
       
   394 			iMaskTransformer->Transform(iCurrentMask, MaintainAspectRatio());
       
   395 			iState = ETransformingMask;
       
   396 			return;
       
   397 			}
       
   398 		SetStatusFlag(EStatusFrameReady);
       
   399 		if (!IsStatusSet(EStatusNoMoreToDecode))
       
   400 			{
       
   401 			SetStatusFlag(EStatusPaused);
       
   402 			}
       
   403 		iTransformer->GetBitmap(iCurrentFrame);
       
   404 		if (iCurrentMask)
       
   405 			{
       
   406 			iMaskTransformer->GetBitmap(iCurrentMask);
       
   407 			}
       
   408 		if (iCurrentFrame != NULL)
       
   409 			{
       
   410 			iValidBitmap= ETrue;
       
   411 			delay		= iNextFrameDelay;
       
   412 			}
       
   413 		iNextFrameDelay = iPlayer->CurrentFrameInfo().iDelay;
       
   414 		iState = EProcessing;
       
   415 		}
       
   416 	else
       
   417 		{
       
   418 		iState			= EInitFailed;
       
   419 		iValidBitmap	= EFalse;
       
   420 		iCurrentFrame	= NULL;
       
   421 		SetStatusFlag(EStatusNoMoreToDecode);
       
   422 		ClearStatusFlag(EStatusBusy|EStatusPaused);
       
   423 		}
       
   424 	
       
   425 	ClearStatusFlag(EStatusBusy);
       
   426 	iLastError = aError;
       
   427 	iDelayedCb->CallAfter(delay);
       
   428 	}
       
   429 
       
   430 void CGenericImageDisplayPlugin::FillRecommendedSizesL()
       
   431 	{
       
   432 	ASSERT( iDecoder->IsImageHeaderProcessingComplete() );
       
   433 	TRect clipRect;
       
   434 	const TBool clipDefined=SourceRect(clipRect);
       
   435 	const TFrameInfo& FrameInfo=iDecoder->FrameInfo();
       
   436 
       
   437 	TSize imageSize(clipDefined? clipRect.Size() : FrameInfo.iFrameCoordsInPixels.Size() );
       
   438 	RotateSize(imageSize, iRotationOptions);
       
   439 	GenRecommendedSizesL(iImageSizes, imageSize, KMaxReductionFactor);
       
   440 	}
       
   441 
       
   442 void CGenericImageDisplayPlugin::GenRecommendedSizesL(RSizeArray& aArray,const TSize& aOriginalSize,TInt aMaxReduction )
       
   443 	{
       
   444 	aArray.Reset();
       
   445 	TSize reducedSize(aOriginalSize);
       
   446 	TInt i=0;
       
   447 	do 
       
   448 		{
       
   449 		User::LeaveIfError( aArray.Append(reducedSize) );
       
   450 		if (KErrNone != iDecoder->ReducedSize(aOriginalSize, ++i, reducedSize))
       
   451 			{
       
   452 			break;
       
   453 			}
       
   454 
       
   455 		} while ( i<=aMaxReduction &&
       
   456 					reducedSize.iWidth <= MaxUnscaledSize().iWidth && reducedSize.iHeight <= MaxUnscaledSize().iHeight);
       
   457 	}
       
   458 
       
   459 TBool CGenericImageDisplayPlugin::SetupPlayerGetScalingNeeded(const TSize& aImageSize, const TSize& aTrueImgSize)
       
   460 	{
       
   461 	TSize effectiveDestSize( DestinationSizeInPixels() );
       
   462 	RotateSize(effectiveDestSize, iRotationOptions);
       
   463 
       
   464 	const TSize askSize( effectiveDestSize );
       
   465 	// in case of clipping and upscaling  - decode to original size, clip then upscale
       
   466 	// in case of clipping and downscaling- decode to downscaled, then clip
       
   467 	const TSize destSize( aImageSize == aTrueImgSize ? askSize : // no clipping so decode to dest size
       
   468 			(IsSize2Exceeds1(aTrueImgSize, askSize)?aTrueImgSize: 
       
   469 													ScaleSize(effectiveDestSize, aImageSize, aTrueImgSize) )
       
   470 						);
       
   471 	if ((iDecoder->FrameInfo().iFlags&TFrameInfo::EFullyScaleable))
       
   472 		{
       
   473 		iPlayer->Setup( destSize, KZeroReductionFactor, KZeroReductionFactor);
       
   474 		return EFalse;
       
   475 		}
       
   476 
       
   477 	TBool scalingNeeded=EFalse;
       
   478 	TInt neededReduction=iDecoder->ReductionFactor(aTrueImgSize, destSize);
       
   479 	TSize reducedSize(-1,-1);
       
   480 	// if given reduction factor is not supported we'd go using scaler
       
   481 	iDecoder->ReducedSize(aTrueImgSize, neededReduction, reducedSize);
       
   482 	// animated images suffer from "1 pixel difference" problems when they are composed of reduced parts
       
   483 	// so always use scaling for such images
       
   484 	const TBool KNoReductionAllowed=(iImageHasFloatingSubImgs && (iPluginImgStatus & CImageDisplay::EImageAnimated));
       
   485 	if (neededReduction>=0 && neededReduction<=KMaxReductionFactor && reducedSize==destSize 
       
   486 			&& !KNoReductionAllowed)
       
   487 		{
       
   488 		// destination size is achivable through reduction factor
       
   489 		TInt maxReduction=(IsSize2Exceeds1(iMaxUnscaledSize,destSize)? Max(iMaxReductionFactor,neededReduction) : neededReduction);
       
   490 		iPlayer->Setup(reducedSize, maxReduction ,neededReduction);
       
   491 		scalingNeeded=(maxReduction != neededReduction);
       
   492 		}
       
   493 	else
       
   494 		{
       
   495 		scalingNeeded=ETrue;
       
   496 		if (IsSize2Exceeds1(aTrueImgSize, destSize) || KNoReductionAllowed)// we've got upscaling, or no reduction is allowed
       
   497 			{
       
   498 			iPlayer->Setup(aTrueImgSize, KZeroReductionFactor, KZeroReductionFactor); 
       
   499 			}
       
   500 		else
       
   501 			{
       
   502 			// we do not apply reduction for sizes smaller than iMaxUnscaledSize
       
   503 			TInt reduction=iDecoder->ReductionFactor(destSize, iMaxUnscaledSize);
       
   504 			reduction=Max(0, Min(iMaxReductionFactor, reduction));
       
   505 			iPlayer->Setup(aTrueImgSize, reduction, KZeroReductionFactor); 
       
   506 			// and we have to use further downscaling to achieve final target size
       
   507 			}
       
   508 		}
       
   509 	return scalingNeeded;
       
   510 	}
       
   511 
       
   512 void CGenericImageDisplayPlugin::CompleteInitL()
       
   513 	{
       
   514 	ASSERT( iDecoder->IsImageHeaderProcessingComplete() );
       
   515 	iNumberOfFrames = iDecoder->FrameCount();
       
   516 	TBool needsMask=EFalse;
       
   517 
       
   518 	for (TInt i=0; i<iNumberOfFrames && !needsMask; ++i)
       
   519 		{
       
   520 		needsMask = ( (iDecoder->FrameInfo(i).iFlags & TFrameInfo::ETransparencyPossible) != 0 );
       
   521 		}
       
   522 	const TFrameInfo& frameInfo=iDecoder->FrameInfo();
       
   523 	TRect frameRect(frameInfo.iFrameCoordsInPixels);
       
   524 	const TSize imageSize(frameRect.Size());
       
   525 	TRect clipRect;
       
   526 	const TBool clipDefined=SourceRect(clipRect);
       
   527 	if (!clipDefined)
       
   528 		{
       
   529 		clipRect=frameRect;
       
   530 		}
       
   531 	else
       
   532 		{
       
   533 		TRect clipTest(clipRect);
       
   534 		clipTest.Intersection(frameRect);
       
   535 		if (clipTest != clipRect ) // clipping rect is outside the image rect
       
   536 			{
       
   537 			User::Leave( KErrArgument );
       
   538 			}
       
   539 		}
       
   540 	
       
   541 	TBool scalingNeeded=SetupPlayerGetScalingNeeded( clipDefined?clipRect.Size():imageSize, imageSize);
       
   542 
       
   543 	if (iRotationOptions || clipDefined || scalingNeeded )
       
   544 		{
       
   545 		CTransformerSharedData* singleton=CTransformerSharedData::NewL();
       
   546 		CleanupReleasePushL(*singleton);
       
   547 		singleton->SetTransformOptions(iRotationOptions);
       
   548 		singleton->SetTrueSrcSize(imageSize);
       
   549 		if (clipDefined)
       
   550 			{
       
   551 			singleton->SetClipRect(clipRect);
       
   552 			}
       
   553 		iTransformer= CAsyncTransformer::NewL(*this, *singleton, DestinationSizeInPixels());
       
   554 
       
   555 		if (needsMask)
       
   556 			{
       
   557 			iMaskTransformer= CAsyncTransformer::NewL(*this, *singleton, DestinationSizeInPixels());
       
   558 			}
       
   559 		CleanupStack::PopAndDestroy(singleton);
       
   560 
       
   561 		if (iScaleQuality!=-1)
       
   562 			{
       
   563 			User::LeaveIfError( iTransformer->SetScaleQuality(iScaleQuality) );
       
   564 			if (iMaskTransformer)
       
   565 				{
       
   566 				User::LeaveIfError( iMaskTransformer->SetScaleQuality(iScaleQuality) );
       
   567 				}
       
   568 			}
       
   569 		}
       
   570 	iState = EInitCompleted;
       
   571 	}
       
   572 
       
   573 TInt CGenericImageDisplayPlugin::ExtensionInterface(TUid aIFaceUid, TAny*& aIFacePtr)
       
   574 	{
       
   575 	aIFacePtr = NULL;
       
   576 	if (aIFaceUid == KUidGenIclImageDisplayPluginExtUid)
       
   577 		{
       
   578 		aIFacePtr = static_cast<MGenIclImageDisplayExtension*>(&iExtHandler);
       
   579 		return KErrNone;
       
   580 		}
       
   581 	return KErrNotSupported;
       
   582 	}
       
   583 
       
   584 TBool CGenericImageDisplayPlugin::ThumbnailExists() const
       
   585 	{
       
   586 	return EFalse;
       
   587 	}
       
   588 
       
   589 TUint CGenericImageDisplayPlugin::EffectiveRotation() const
       
   590 	{
       
   591 	return Options() & ( CImageDisplay::EOptionMirrorVertical |
       
   592 			(CImageDisplay::EOptionMirrorVertical - CImageDisplay::EOptionRotateCw90) );
       
   593 	}
       
   594 
       
   595 TInt CGenericImageDisplayPlugin::DoSetScaleQuality(TInt aQualityValue)
       
   596 	{
       
   597 	iScaleQuality = aQualityValue;
       
   598 	TInt err=KErrNone;
       
   599 	if (iTransformer != NULL)
       
   600 		{
       
   601 		err=iTransformer->SetScaleQuality(aQualityValue);
       
   602 		}
       
   603 	if (err==KErrNone && iMaskTransformer != NULL)
       
   604 		{
       
   605 		err=iMaskTransformer->SetScaleQuality(aQualityValue);
       
   606 		}
       
   607 
       
   608 	return err;
       
   609 	}
       
   610 
       
   611 TInt CGenericImageDisplayPlugin::DoSetMaximumReductionFactor(TInt aMaxReductionFactor)
       
   612 	{
       
   613 	if (aMaxReductionFactor<0 || aMaxReductionFactor>KMaxReductionFactor)
       
   614 		{
       
   615 		return KErrArgument;
       
   616 		}
       
   617 	iMaxReductionFactor = aMaxReductionFactor;
       
   618 	return KErrNone;	
       
   619 	}
       
   620 
       
   621 TInt CGenericImageDisplayPlugin::SetMaxUnscaledSize(const TSize& aSize)
       
   622 	{
       
   623 	if (aSize.iWidth < 1 || aSize.iHeight < 1)
       
   624 		{
       
   625 		return KErrArgument;
       
   626 		}
       
   627 	iMaxUnscaledSize = aSize;
       
   628 	return KErrNone;
       
   629 	}
       
   630 
       
   631 void CGenericImageDisplayPlugin::AfterOpenL()
       
   632 	{
       
   633 	}
       
   634 
       
   635 TUid CGenericImageDisplayPlugin::RequiredImageClass() const
       
   636 	{
       
   637 	return KNullUid;
       
   638 	}
       
   639 
       
   640 void CGenericImageDisplayPlugin::OnCallback()
       
   641 	{
       
   642 	if (iIsPaused)
       
   643 		{
       
   644 		iCallBackIsPending = ETrue;
       
   645 		return;
       
   646 		}
       
   647 	AsyncCallbackImageReady(iCurrentFrame, iPluginStatus, iOutputRect, iLastError);
       
   648 	}
       
   649 
       
   650 /*static*/
       
   651 CDelayedCallback* CDelayedCallback::NewL(MCallbackClient& aClient)
       
   652 	{
       
   653 	CDelayedCallback* self=new (ELeave) CDelayedCallback(aClient);
       
   654 	CleanupStack::PushL(self);
       
   655 	self->ConstructL();
       
   656 	CleanupStack::Pop(self);
       
   657 	return self;
       
   658 	}
       
   659 
       
   660 void CDelayedCallback::CallAfter(const TTimeIntervalMicroSeconds& aAfter)
       
   661 	{
       
   662 	TTime now;	
       
   663 	now.HomeTime();
       
   664 	const TInt64 KTimerTreshold	=8000; // 8 ms, we don't go trought timer for delays less than that
       
   665 	const TInt64 KDelayDelta	=4000; // 4 ms, make delay 4 ms less to account time before we reach client
       
   666 	const TInt64 requiredDelay = aAfter.Int64() - (now.Int64() - iLatestCallbackAt.Int64());
       
   667 	if ( requiredDelay <= KTimerTreshold )
       
   668 		{
       
   669 		iLatestCallbackAt = now;
       
   670 		iClient.OnCallback();
       
   671 		}
       
   672 	else
       
   673 		{
       
   674 		CTimer::After( TTimeIntervalMicroSeconds32( I64INT(requiredDelay-KDelayDelta) ) );
       
   675 		}
       
   676 	}
       
   677 
       
   678 void CDelayedCallback::Cancel()
       
   679 	{
       
   680 	CTimer::Cancel();
       
   681 	}
       
   682 
       
   683 void CDelayedCallback::RunL()
       
   684 	{
       
   685 	iLatestCallbackAt.HomeTime();
       
   686 	iClient.OnCallback();
       
   687 	}
       
   688 
       
   689 const TUid TExtTie::Uid() const
       
   690 	{
       
   691 	return KUidGenIclImageDisplayPluginExtUid;
       
   692 	}
       
   693 
       
   694 void TExtTie::Release()
       
   695 	{
       
   696 	}
       
   697 
       
   698 TInt TExtTie::SetScaleQuality(TInt aQualityLevel)
       
   699 	{
       
   700 	return iImplementor.DoSetScaleQuality(aQualityLevel);
       
   701 	}
       
   702 
       
   703 TInt TExtTie::SetMaximumReductionFactor(TInt aMaxReductionFactor)
       
   704 	{
       
   705 	return iImplementor.DoSetMaximumReductionFactor(aMaxReductionFactor);
       
   706 	}
       
   707 	
       
   708 TInt TExtTie::SetMaximumNonReducedSize(const TSize& aSize)
       
   709 	{
       
   710 	return iImplementor.SetMaxUnscaledSize(aSize);
       
   711 	}
       
   712 
       
   713 
       
   714