imagingandcamerafws/imagingfws/src/ImageConversionPriv.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2001-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 #include "ImageClientMain.h"
       
    17 #include "ImageConversionPriv.h"
       
    18 #include "icl/ImagePlugin.h"
       
    19 #include "icl/ImageConstruct.h"
       
    20 #include "ImageConversion.h"
       
    21 
       
    22 
       
    23 
       
    24 const TInt KMaxDstBufferSize = 4096;
       
    25 
       
    26 /* IMAGE DECODER PRIVATE */
       
    27 CImageDecoderPriv::CImageDecoderPriv(CImageDecodeConstruct* aConstruct, MImageDecoderPrivSupport* aSupport)
       
    28 	: CActive(CActive::EPriorityIdle), iImageType(CImageDecoder::EImageTypeMain), iConstruct(aConstruct), iSupport(aSupport), iReadOnly(EFalse), iUseBufferReadOptimization(ETrue)
       
    29 	{
       
    30 	ASSERT(aConstruct != NULL);
       
    31 	ASSERT(aSupport != NULL);
       
    32 	CActiveScheduler::Add(this);
       
    33 	}
       
    34 
       
    35 void CImageDecoderPriv::SetFileL(RFs& aFs, const TDesC& aSourceFilename, const CImageDecoder::TOptions aOptions)
       
    36 	{
       
    37 	iFs = &aFs;
       
    38 	iOptions = aOptions;
       
    39 	iImageParameterData.SetFilenamePtr(&aSourceFilename);
       
    40 	delete iContent;
       
    41 	iContent = NULL;
       
    42 	delete iData;
       
    43 	iData = NULL;
       
    44 	iReadOnly=ETrue;
       
    45 	TRAPD(err, iContent = CContent::NewL(*iImageParameterData.SourceFilenamePtr(), EContentShareReadOnly));
       
    46 	if (err!= KErrNone && err != KErrNoMemory)
       
    47 		{
       
    48 		iReadOnly=EFalse;
       
    49 		iContent = CContent::NewL(*iImageParameterData.SourceFilenamePtr(), EContentShareReadWrite);
       
    50 		}
       
    51 	User::LeaveIfNull(iContent);
       
    52 	iData = iContent->OpenContentL(iIntent, (iUniqueId) ? static_cast<TDesC&>(*iUniqueId) : KDefaultContentObject());
       
    53 	
       
    54 	//Try to find if content is DRM
       
    55     TInt value = -1;
       
    56     TInt getAttrResult =iContent->GetAttribute(EIsProtected, value);
       
    57     if(getAttrResult != KErrNone || value!=0)
       
    58         {
       
    59         //either we had an error from getAttribute or  EIsProtected is not set to 0 (false)
       
    60         //Could be DRM content, don't apply iUseBufferReadOptimization
       
    61         iUseBufferReadOptimization = EFalse;
       
    62         }   
       
    63     
       
    64 	iCachedDataSize = -1;
       
    65     }
       
    66 	
       
    67 void CImageDecoderPriv::SetFileL(RFile& aFile, const CImageDecoder::TOptions aOptions)
       
    68 	{
       
    69 	iOptions = aOptions;
       
    70 	User::LeaveIfError(aFile.Name(iFileName));
       
    71 	iImageParameterData.SetFilenamePtr(&iFileName);
       
    72 	delete iContent;
       
    73 	iContent = NULL;
       
    74 	delete iData;
       
    75 	iData = NULL;
       
    76 	iContent = CContent::NewL(aFile);
       
    77 	iData = iContent->OpenContentL(iIntent, (iUniqueId) ? static_cast<TDesC&>(*iUniqueId) : KDefaultContentObject());
       
    78 	
       
    79 	//Try to find if content is DRM
       
    80     TInt value = -1;
       
    81     TInt getAttrResult =iContent->GetAttribute(EIsProtected, value);
       
    82     if(getAttrResult != KErrNone || value!=0)
       
    83         {
       
    84         //either we had an error from getAttribute or EIsProtected is not set to 0 (false)
       
    85         //Could be DRM content, don't apply iUseBufferReadOptimization
       
    86         iUseBufferReadOptimization = EFalse;
       
    87         }   
       
    88 	
       
    89 	iCachedDataSize = -1;        
       
    90 	}
       
    91 
       
    92 void CImageDecoderPriv::SetDataL(RFs& aFs, const TDesC8& aSourceData, const CImageDecoder::TOptions aOptions)
       
    93 	{
       
    94 	iFs = &aFs;
       
    95 	iOptions = aOptions;
       
    96 	iImageParameterData.SetDataPtr(&aSourceData);
       
    97 	}
       
    98 
       
    99 CImageDecoderPriv* CImageDecoderPriv::NewL(CImageDecodeConstruct* aConstruct, MImageDecoderPrivSupport* aSupport)
       
   100 	{
       
   101 	CImageDecoderPriv* self = new (ELeave) CImageDecoderPriv(aConstruct, aSupport);
       
   102 	return self;
       
   103 	}
       
   104 
       
   105 CImageDecoderPriv::~CImageDecoderPriv()
       
   106 	{
       
   107 	ASSERT(!IsActive());
       
   108 	if (iPlugin)
       
   109 		iPlugin->Cleanup();
       
   110 	iFrameInfo.ResetAndDestroy();
       
   111 	iFrameData.ResetAndDestroy();
       
   112 	delete iImageReadCodec; // Created in ScanDataL()
       
   113 	delete iData;
       
   114 	delete iContent;
       
   115 	delete iPlugin;
       
   116 	delete iUniqueId;
       
   117 	}
       
   118 
       
   119 void CImageDecoderPriv::Cleanup()
       
   120 	{
       
   121 	delete iReadBuffer; iReadBuffer = NULL;	
       
   122 	}
       
   123 
       
   124 void CImageDecoderPriv::CreatePluginL()
       
   125 	{
       
   126 	iPlugin = iConstruct->NewPluginL();
       
   127 	iPlugin->iProperties = this;
       
   128 	}
       
   129 
       
   130 /**
       
   131 @see CImageDecoder::SetImageTypeL
       
   132 */
       
   133 void CImageDecoderPriv::SetImageTypeL(TInt aImageType)
       
   134 	{
       
   135 	if (aImageType == iImageType)
       
   136 		{
       
   137 		return;
       
   138 		}
       
   139 
       
   140 	if ( (aImageType == CImageDecoder::EImageTypeThumbnail) &&
       
   141 		 (iThumbnailData == NULL) )
       
   142 		{
       
   143 		User::Leave(KErrNotFound);
       
   144 		}
       
   145 	
       
   146 	TInt prevImageType = iImageType;	
       
   147 	iImageType = aImageType;
       
   148 	
       
   149 	// Delete the old read codec - a new one will be instantiated by the 
       
   150 	// plugin on notification of Image Type change.
       
   151 	delete iImageReadCodec;
       
   152 	iImageReadCodec = NULL;
       
   153 	iCurrentFrame = 0;
       
   154 	iPosition = 0;
       
   155 	TRAPD(err,iPlugin->NotifyImageTypeChangeL(aImageType));
       
   156 	if(err != KErrNone)
       
   157 		{
       
   158 		delete iImageReadCodec;
       
   159 		iImageReadCodec = NULL;
       
   160 		// Try to switch back to the main image
       
   161 		iImageType = prevImageType;
       
   162 		TRAPD(err2,iPlugin->NotifyImageTypeChangeL(prevImageType));
       
   163 		if (err2 != KErrNone)
       
   164 			{
       
   165 			// Switching back to the main image type shouldn't fail as corrupt as it has been done once before 
       
   166 			// when creating the decoder.
       
   167 			__ASSERT_DEBUG( (err2 != KErrCorrupt), Panic( EInvalidFunctionLeave ) );
       
   168 			User::Leave(err2);
       
   169 			}
       
   170 		// We report the thumbnail problem to the application
       
   171 		User::Leave(err);
       
   172 		}
       
   173 	}
       
   174 
       
   175 void CImageDecoderPriv::SetThumbnailData(HBufC8* aThumbnailData)
       
   176 	{
       
   177 	// The buffer containing the thumbnail data is owned by the plugin
       
   178 	iThumbnailData = aThumbnailData;
       
   179 	}
       
   180 
       
   181 /*
       
   182 Disable optimization of this function by the VC compiler.
       
   183 This function suffers from the known behaviour of setjmp()/longjmp()
       
   184 used by the TRAP() harness in that register variables can be 'stomped'
       
   185 by the longjmp/leave process. 
       
   186 */
       
   187 #ifdef __VC32__
       
   188 #pragma optimize("",off)
       
   189 #endif  // __VC32__
       
   190 void CImageDecoderPriv::Convert(RThread& aRequestThread, TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, TInt aFrameNumber)
       
   191 	{
       
   192 	if (IsActive())
       
   193 		Panic(EConvertCalledWhileBusy);
       
   194 	
       
   195 
       
   196 	iRequestThread = &aRequestThread;
       
   197 	iConvStatus = aRequestStatus;
       
   198  	*iConvStatus = KRequestPending;
       
   199 
       
   200 	iCurrentFrame = aFrameNumber;
       
   201 	if (iCurrentFrame < 0 || iCurrentFrame >= iFrameInfo.Count())
       
   202 		{
       
   203 		RequestComplete(KErrArgument);
       
   204 		return;
       
   205 		}
       
   206 	
       
   207 	if (aDestination.Handle() == 0)
       
   208 		Panic(ENoDestinationBitmap);
       
   209 	
       
   210    if(aDestination.ExtendedBitmapType()!=KNullUid)
       
   211         {
       
   212         RequestComplete(KErrNotSupported);
       
   213         return;
       
   214         }
       
   215 	
       
   216 	iDestination = &aDestination;
       
   217 	iDestinationHandle = iDestination->Handle();
       
   218 	iDestinationSize = iDestination->SizeInPixels();
       
   219 	iDestinationMask = NULL;
       
   220 	TRAPD(error, iPlugin->InitConvertL());
       
   221 
       
   222 	if (error!=KErrNone)
       
   223 		RequestComplete(error);
       
   224 	else
       
   225 		SelfComplete(KErrNone);
       
   226 	}
       
   227 #ifdef __VC32__
       
   228 #pragma optimize("",on)
       
   229 #endif  // __VC32__
       
   230 
       
   231 void CImageDecoderPriv::Convert(RThread& aRequestThread, TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, CFbsBitmap& aDestinationMask, TInt aFrameNumber)
       
   232 	{	
       
   233 	if (IsActive())
       
   234 		Panic(EConvertCalledWhileBusy);
       
   235 
       
   236 	iRequestThread = &aRequestThread;
       
   237 	iConvStatus = aRequestStatus;
       
   238 	*iConvStatus = KRequestPending;
       
   239 
       
   240 	iCurrentFrame = aFrameNumber;
       
   241 	if (iCurrentFrame < 0 || iCurrentFrame >= iFrameInfo.Count())
       
   242 		{
       
   243 		RequestComplete(KErrArgument);
       
   244 		return;
       
   245 		}
       
   246 	
       
   247 	if (aDestination.Handle() == 0)
       
   248 		Panic(ENoDestinationBitmap);
       
   249 	
       
   250    if(aDestination.ExtendedBitmapType()!=KNullUid || (aDestinationMask.Handle()!=0 && aDestinationMask.ExtendedBitmapType()!=KNullUid))
       
   251         {
       
   252         RequestComplete(KErrNotSupported);
       
   253         return;
       
   254         }
       
   255 
       
   256 	iDestination = &aDestination;
       
   257 	iDestinationHandle = iDestination->Handle();
       
   258 	iDestinationSize = iDestination->SizeInPixels();
       
   259 
       
   260 	if (aDestinationMask.Handle() == 0)
       
   261 		Panic(ENoBitmapMask);
       
   262 	else
       
   263 		{
       
   264 		// if we have an alpha channel mask, insist an EGray256 mask bitmap
       
   265 		// else allow either an EGray2 or an EGray256 one
       
   266 		// ie. for compatability allow an EGray256 mask bitmap, even if we only have binary data
       
   267 		TDisplayMode maskDisplayMode = aDestinationMask.DisplayMode();
       
   268 		const TFrameInfo& frameInfo = FrameInfo(iCurrentFrame);
       
   269 		if (!(maskDisplayMode==EGray256 || 
       
   270 			(maskDisplayMode==EGray2 && !(frameInfo.iFlags & TFrameInfo::EAlphaChannel))))
       
   271 			{
       
   272 			RequestComplete(KErrArgument);
       
   273 			return;
       
   274 			}
       
   275 		// furthermore, if we have a mask, enforce is same size as destination
       
   276 		if (iDestinationSize != aDestinationMask.SizeInPixels())
       
   277 			{
       
   278 			RequestComplete(KErrArgument);
       
   279 			return;
       
   280 			}
       
   281 		}
       
   282 
       
   283 	iDestinationMask = &aDestinationMask;
       
   284 	iDestinationMaskHandle = iDestinationMask->Handle();
       
   285 	
       
   286 	TRAPD(error, iPlugin->InitConvertL());
       
   287 
       
   288 	if (error!=KErrNone)
       
   289 		RequestComplete(error);
       
   290 	else
       
   291 		SelfComplete(KErrNone);
       
   292 	}
       
   293 
       
   294 void CImageDecoderPriv::ContinueConvert(RThread& aRequestThread, TRequestStatus* aRequestStatus)
       
   295 	{
       
   296 	// NB Not busy and iCurrentProcessingData==true -> we previously stopped on an underflow
       
   297 	// if not true we must have stopped for some other reason and ContinueConvert is illegal
       
   298 
       
   299 	if (IsActive())
       
   300 		Panic(EConvertCalledWhileBusy);
       
   301 
       
   302 	if (!iCurrentlyProcessingData)
       
   303 		Panic(EIllegalContinueConvert);
       
   304 
       
   305 	ASSERT(iPlugin->ValidDestination()); // if legal we should have an iDestination. Whether iMask depends.
       
   306 
       
   307 	if (iDestination->Handle() != iDestinationHandle)
       
   308 		Panic(EDifferentDestinationBitmap);
       
   309 
       
   310 	if (iDestinationMask && (iDestinationMask->Handle() != iDestinationMaskHandle))
       
   311 		Panic(EDifferentDestinationMask);
       
   312 
       
   313 	if (iDestination->SizeInPixels() != iDestinationSize)
       
   314 		Panic(EModifiedDestination);
       
   315 
       
   316 	iRequestThread = &aRequestThread;
       
   317 	iConvStatus = aRequestStatus;
       
   318 	*iConvStatus = KRequestPending;
       
   319 
       
   320 	SelfComplete(KErrNone);
       
   321 	return;
       
   322 	}
       
   323 
       
   324 
       
   325 TInt CImageDecoderPriv::DataSizeL()
       
   326     {
       
   327     TInt dataSize = iCachedDataSize;
       
   328     if (dataSize == -1)
       
   329         {
       
   330         iData->DataSizeL(dataSize);
       
   331         if(iReadOnly)
       
   332              iCachedDataSize = dataSize;
       
   333         }
       
   334     
       
   335     return dataSize;
       
   336     }
       
   337 
       
   338 void CImageDecoderPriv::PrepareForProcessFrameL()
       
   339 	{
       
   340 	TInt localSrcLength;
       
   341 	TBool srcHasGrown = EFalse;
       
   342 
       
   343 	if (iImageParameterData.IsFilename())
       
   344 		{
       
   345 		ASSERT(iData);
       
   346 		
       
   347         if(iUseBufferReadOptimization)
       
   348             {
       
   349             localSrcLength = DataSizeL();
       
   350             }
       
   351         else
       
   352             {
       
   353             iData->DataSizeL(localSrcLength);
       
   354             }
       
   355 		}
       
   356 	else
       
   357 		{
       
   358 		localSrcLength = iImageParameterData.SourceDataPtr()->Length();
       
   359 		}
       
   360 
       
   361 	if (localSrcLength > iSrcLength)
       
   362 		srcHasGrown = ETrue;
       
   363 
       
   364 	iSrcLength = localSrcLength;
       
   365 	if ((iSrcDes.Length() == 0) || srcHasGrown)
       
   366 		{
       
   367 		// Fetch next buffer.
       
   368 		// Get next block size.
       
   369 		iCurrentBlockLength = iBlockLength;
       
   370 		if ((iCurrentBlockLength + iPosition) > iDataLength)
       
   371 			{
       
   372 			// If current position + read buffer length > Data length then
       
   373 			// iCurrentBlockLength = what ever's left in iDataLength
       
   374 			iCurrentBlockLength = Max(0, iDataLength - iPosition);
       
   375 			}
       
   376 
       
   377 		// Get the next block of data
       
   378 		TPtrC8 ptr;
       
   379 		ReadDataL((iPosition + iStartPosition), ptr, iCurrentBlockLength);
       
   380 
       
   381 		// Set iSrcDes to point at next block in the source data.
       
   382 		iSrcDes.Set(ptr);
       
   383 		iCurrentBlockLength = iSrcDes.Length();
       
   384 		}
       
   385 
       
   386 	iOldSrcDesLength = iSrcDes.Length();
       
   387 	}
       
   388 
       
   389 
       
   390  
       
   391 /**
       
   392 * Issues a read operation by sending the start position
       
   393 * along with the destination descriptor and size.
       
   394 *
       
   395 * When this function is used to read data from a file, it
       
   396 * can send the start position and length in one IPC operation,
       
   397 * and so avoid having to issue a seek first.
       
   398 *
       
   399 * Because ContentAccess::CData does not support a synchronous
       
   400 * version of this API, this function takes care of waiting for
       
   401 * the operation to complete, and leaves with any error code.
       
   402 * This simplifies the calling code.
       
   403 *
       
   404 * @param   aPosition       Position in source data to read from.
       
   405 * @param   aDest           The data is written into this descriptor.
       
   406 * @param   aSize           Amount of data to read in bytes.
       
   407 * @leave                   Any Symbian OS error code.
       
   408 */
       
   409 void CImageDecoderPriv::SeekReadL(TInt aPosition, TDes8& aDest, TInt aSize)
       
   410     {
       
   411     #ifdef __WINS__
       
   412         RDebug::Printf("sr,%d,%d", aPosition, aSize);
       
   413     #endif
       
   414         
       
   415     TRequestStatus rs;
       
   416     TInt result=iData->Read(aPosition, aDest, aSize, rs);
       
   417     User::LeaveIfError(result);
       
   418     User::WaitForRequest(rs);
       
   419     User::LeaveIfError(rs.Int());
       
   420     }
       
   421 
       
   422 
       
   423 void CImageDecoderPriv::DoConvert()
       
   424 	{
       
   425 	TRAPD(errCode, PrepareForProcessFrameL());
       
   426 
       
   427 	if (errCode!=KErrNone)
       
   428 		{
       
   429 		RequestComplete(errCode);
       
   430 		return;
       
   431 		}
       
   432 
       
   433 	TFrameState codecState = EFrameIncomplete; 
       
   434 	if (iCurrentBlockLength)
       
   435 		TRAP(errCode, codecState = iImageReadCodec->ProcessFrameL(iSrcDes));
       
   436 	
       
   437 	HandleProcessFrameResult(errCode, codecState);
       
   438 	}
       
   439 
       
   440 void CImageDecoderPriv::HandleProcessFrameResult(TInt aErrCode, TFrameState aCodecState)
       
   441 	{
       
   442 	if (aErrCode!=KErrNone)
       
   443 		{
       
   444 		ASSERT(aErrCode != KErrUnderflow);
       
   445 		iCurrentlyProcessingData = EFalse;
       
   446 		RequestComplete(aErrCode);
       
   447 		return;
       
   448 		}
       
   449 
       
   450 	TInt newSrcDesLength = iSrcDes.Length();
       
   451 	iPosition += iOldSrcDesLength - newSrcDesLength;
       
   452 
       
   453 	if (aCodecState == EFrameIncompleteRepositionRequest)
       
   454 		{
       
   455 		TInt length   = iBlockLength;
       
   456 		TInt position = iPosition + iStartPosition;
       
   457 		iImageReadCodec->GetNewDataPosition(position, length);
       
   458 		if (position<0)
       
   459 			{
       
   460 			iCurrentlyProcessingData = EFalse;
       
   461 			RequestComplete(KErrCorrupt);
       
   462 			return;
       
   463 			}
       
   464 
       
   465 		iPosition = position-iStartPosition;
       
   466 		}
       
   467 	
       
   468 	if (aCodecState == EBlockComplete)	// Block decoded successfully
       
   469 		{
       
   470 		iCurrentlyProcessingData = EFalse; // To avoid call of ContinueConvert()
       
   471 		RequestComplete(KErrNone);
       
   472 		return;
       
   473 		}
       
   474 	
       
   475 	if (aCodecState == EFrameComplete)	// Frame decoded successfully
       
   476 		{
       
   477 		iImageReadCodec->Complete();
       
   478 		iCurrentlyProcessingData = EFalse;
       
   479 
       
   480 		RequestComplete(KErrNone);
       
   481 		return;
       
   482 		}
       
   483 	else if (newSrcDesLength == iOldSrcDesLength && iCurrentlyProcessingData) // Needs more data than is currently present in the buffer to make progress
       
   484 		{
       
   485 		//call of ContinueConvert() only
       
   486 		 //The following method call is required so that codecs can get the data already decoded can be displayed
       
   487 		iImageReadCodec->Complete();
       
   488 		RequestComplete(KErrUnderflow);
       
   489 		return;
       
   490 		}
       
   491 
       
   492 	// Each Plug-in has to trigger the active object as it needs RunL called again.
       
   493 	iSrcDes.SetLength(0);
       
   494 	SelfComplete(KErrNone);
       
   495 	}
       
   496 
       
   497 TBufPtr8& CImageDecoderPriv::SourceData()
       
   498 	{
       
   499 	return iSrcDes;
       
   500 	}
       
   501 
       
   502 
       
   503 void CImageDecoderPriv::RunL()
       
   504 	{
       
   505 	ASSERT(iStatus==KErrNone); // we don't handle errors at this point. Should only get here on KErrNone
       
   506 	iPlugin->DoConvert();
       
   507 	}
       
   508 
       
   509 void CImageDecoderPriv::RequestComplete(TInt aReason)
       
   510 	{
       
   511 	ASSERT(iPlugin);
       
   512 	iPlugin->NotifyComplete();
       
   513 	ASSERT(iRequestThread);
       
   514 
       
   515 	if (iData && aReason == KErrNone && !iIntentHasBeenExecuted)
       
   516 		{
       
   517 		TInt err = iData->ExecuteIntent(iIntent);
       
   518 		if(err == KErrNone)
       
   519 			{
       
   520 			//Intent has been executed. Ensure it is not executed again for this image.
       
   521 			iIntentHasBeenExecuted = ETrue;
       
   522 			}
       
   523 		else
       
   524 			{
       
   525 			aReason = err;
       
   526 			}
       
   527 		}
       
   528 
       
   529 	if (iConvStatus && (*iConvStatus == KRequestPending) )
       
   530 		{
       
   531 		iRequestThread->RequestComplete(iConvStatus, aReason);
       
   532 		}
       
   533 	}
       
   534 
       
   535 void CImageDecoderPriv::DoCancel()
       
   536 	{
       
   537 	iPlugin->Cleanup();
       
   538 
       
   539 	// if SetSelfPending() has been called but not SelfComplete()
       
   540 	// (i.e. the AO is active but there's still an outstanding request)
       
   541 	// then we need to complete the request
       
   542 	if (IsActive() && iStatus == KRequestPending)
       
   543 		SelfComplete(KErrCancel);
       
   544 
       
   545 	RequestComplete(KErrCancel);
       
   546 	}
       
   547 
       
   548 void CImageDecoderPriv::SelfComplete(TInt aReason)
       
   549 	{
       
   550 	if (!IsActive())	// may already be active if SetSelfPending() called
       
   551 		SetActive();
       
   552 	TRequestStatus* status = &iStatus;
       
   553 	User::RequestComplete(status, aReason);
       
   554 	}
       
   555 
       
   556 void CImageDecoderPriv::SetSelfPending()
       
   557 	{
       
   558 	iStatus = KRequestPending;
       
   559 	SetActive();
       
   560 	}
       
   561 
       
   562 void CImageDecoderPriv::ContinueProcessingHeaderL()
       
   563 	{
       
   564 	iCurrentFrame = iFrameInfo.Count();
       
   565 	iProcessingFrameInfo = EFalse;
       
   566 
       
   567 	if (iCurrentFrame)
       
   568 		{
       
   569 		TInt previousFrame = iCurrentFrame-1;
       
   570 		iPosition = iFrameInfo[previousFrame]->iCurrentDataOffset;
       
   571 		if (iFrameInfo[previousFrame]->iCurrentFrameState == TFrameInfo::EFrameInfoProcessingFrame)
       
   572 			{
       
   573 			iCurrentFrame--;
       
   574 			iProcessingFrameInfo = ETrue;
       
   575 			}
       
   576 		}
       
   577 		else
       
   578 			iPosition = 0;
       
   579 
       
   580 	TInt error;
       
   581 	if (iImageReadCodec)
       
   582 		{
       
   583 		TRAP(error,iPlugin->ReadFrameHeadersL());
       
   584 		}
       
   585 	else
       
   586 		{
       
   587 		TRAP(error,iPlugin->ScanDataL());
       
   588 		}
       
   589 
       
   590 	if (error!=KErrNone && error!=KErrUnderflow) // ignore underflow at this point
       
   591 		User::Leave(error);
       
   592 	}
       
   593 
       
   594 void CImageDecoderPriv::CreateFrameInfoL()
       
   595 	{
       
   596 	// Create a new instance of TFrameInfo and initialise it.
       
   597 	// Insert it into the frame info array and store the frame offset.
       
   598 	// Mark the frame as being processed.
       
   599 	TFrameInfo* newFrameInfo = new(ELeave) TFrameInfo(iImageInfo);
       
   600 
       
   601 	CleanupStack::PushL(newFrameInfo); // push in case insert fails
       
   602 	User::LeaveIfError(iFrameInfo.Insert(newFrameInfo, iCurrentFrame));
       
   603 	CleanupStack::Pop(); // newFrameInfo
       
   604 				
       
   605 	iFrameInfo[iCurrentFrame]->iFrameDataOffset = iNextFrameOffset;
       
   606 	iProcessingFrameInfo = EFalse;
       
   607 
       
   608 	CFrameImageData* newFrameData = CFrameImageData::NewL(iImageData);
       
   609 	CleanupStack::PushL(newFrameData);
       
   610 				
       
   611 	User::LeaveIfError(iFrameData.Insert(newFrameData, iCurrentFrame));
       
   612 	CleanupStack::Pop(); // newFrameData
       
   613 
       
   614 	iImageReadCodec->SetCurrentFrame(iCurrentFrame);
       
   615 	iImageReadCodec->InitFrameHeader(*iFrameInfo[iCurrentFrame], *iFrameData[iCurrentFrame]);
       
   616 	}
       
   617 
       
   618 void CImageDecoderPriv::DeleteFrameInfoL()
       
   619 	{
       
   620 	// If process data needs another block but we don't have one because
       
   621 	// this block is incomplete.
       
   622 	if (iFrameInfo.Count()>1)
       
   623 		{
       
   624 		// Delete the new frame as it is incomplete.
       
   625 		iSupport->Lock();
       
   626 		delete iFrameInfo[iCurrentFrame];
       
   627 		iFrameInfo.Remove(iCurrentFrame);
       
   628 
       
   629 		delete iFrameData[iCurrentFrame];
       
   630 		iFrameData.Remove(iCurrentFrame);
       
   631 
       
   632 		iHaveCompleteImageHeaders = EFalse;
       
   633 		iSupport->Unlock();
       
   634 		iSupport->SaveFrameCount(FrameCount());
       
   635 		return;
       
   636 		}
       
   637 	else //may need to do some more clean-up
       
   638 		{
       
   639 		// No headers at all, so just leave.
       
   640 		iSupport->Lock();
       
   641 		iFrameInfo.ResetAndDestroy();
       
   642 		iFrameData.ResetAndDestroy();
       
   643 		iSupport->Unlock();
       
   644 		iSupport->SaveFrameCount(FrameCount());
       
   645 		User::Leave(KErrUnderflow);
       
   646 		}
       
   647 	}
       
   648 
       
   649 void CImageDecoderPriv::ReadFrameHeadersL()
       
   650 	{
       
   651 	ASSERT(iImageReadCodec); // further down, assumes we can call ProcessHeaderL on the codec
       
   652 
       
   653 	TFrameState codecState;
       
   654 	TFrameInfo::TFrameInfoState frameState;
       
   655 
       
   656 	iNextFrameOffset = iPosition;
       
   657 	iCurrentlyProcessingData = EFalse;
       
   658 	iBlockLength = iPlugin->FrameHeaderBlockSize(iCurrentFrame);
       
   659 
       
   660 	do
       
   661 		{ 
       
   662 		iSrcLength = iBlockLength;
       
   663 		if ((iSrcLength + iPosition) > iDataLength)
       
   664 			{
       
   665 			// If current position + read buffer length > Data length then
       
   666 			// srcLength = what ever's left in iDataLength
       
   667 			iSrcLength = Max(0, iDataLength - iPosition);
       
   668 			}
       
   669 
       
   670 		TPtrC8 ptr;
       
   671 		ReadDataL((iPosition + iStartPosition), ptr, iSrcLength);
       
   672 		iSrcDes.Set(ptr);
       
   673 		iSrcLength = iSrcDes.Length();
       
   674 
       
   675 		TInt err;
       
   676 		if (!iProcessingFrameInfo)
       
   677 			{
       
   678 			iSupport->Lock();
       
   679 
       
   680 			//Do not leave between lock and unlock
       
   681 			TRAP(err, CreateFrameInfoL());
       
   682 
       
   683 			iSupport->Unlock();
       
   684 			if (err != KErrNone)
       
   685 				{	// In case of leave, we need to reset the pointer arrays
       
   686 				iSupport->Lock();
       
   687 				iFrameInfo.ResetAndDestroy();
       
   688 				iFrameData.ResetAndDestroy();
       
   689 				iSupport->Unlock();
       
   690 				iSupport->SaveFrameCount(FrameCount());
       
   691 				User::Leave(err);
       
   692 				}
       
   693 
       
   694 			iSupport->SaveFrameCount(FrameCount());
       
   695 			}
       
   696 
       
   697 		// Process Header for one frame.
       
   698 		codecState = EFrameIncomplete;
       
   699 		err = KErrUnderflow;
       
   700 		if (iSrcLength)
       
   701 			TRAP(err, codecState = iImageReadCodec->ProcessFrameHeaderL(iSrcDes));
       
   702 
       
   703 		if ((err != KErrNone) && (err != KErrUnderflow))
       
   704 			User::Leave(err);
       
   705 		
       
   706 		TInt newSrcLength = iSrcDes.Length();
       
   707 		frameState = iFrameInfo[iCurrentFrame]->iCurrentFrameState;
       
   708 		if ((err == KErrUnderflow) || ((codecState == EFrameIncomplete) && (iSrcLength == newSrcLength)))
       
   709 			{
       
   710 			if ((frameState == TFrameInfo::EFrameInfoUninitialised) || (frameState == TFrameInfo::EFrameInfoProcessingFrameHeader))
       
   711 				DeleteFrameInfoL();
       
   712 			return;
       
   713 			}
       
   714 
       
   715 		if (codecState == EFrameIncompleteRepositionRequest)
       
   716 			{
       
   717 			TInt length   = iBlockLength;
       
   718 			TInt position = iPosition+iStartPosition;
       
   719 			iImageReadCodec->GetNewDataPosition(position, length);
       
   720 			if (position<0)
       
   721 				User::Leave(KErrCorrupt);
       
   722 
       
   723 			iPosition = position-iStartPosition;
       
   724 			}
       
   725 		else
       
   726 			iPosition += iSrcLength - newSrcLength;
       
   727 
       
   728 		iNextFrameOffset = iPosition; // Store next frame header offset.
       
   729 		iProcessingFrameInfo = (frameState == TFrameInfo::EFrameInfoProcessingFrameHeader) || (frameState == TFrameInfo::EFrameInfoProcessingFrame);
       
   730 		if ((frameState == TFrameInfo::EFrameInfoProcessingFrame) || (frameState == TFrameInfo::EFrameInfoProcessingComplete))
       
   731 			{
       
   732 			iFrameInfo[iCurrentFrame]->iCurrentDataOffset = iPosition;
       
   733 
       
   734 			if (frameState == TFrameInfo::EFrameInfoProcessingComplete)
       
   735 				iCurrentFrame++;
       
   736 			}
       
   737 		}
       
   738 	while ((codecState == EFrameIncomplete) || (codecState == EFrameIncompleteRepositionRequest));
       
   739 
       
   740 	// Frame header read complete
       
   741 	if(frameState == TFrameInfo::EFrameInfoProcessingFrameHeader)
       
   742 		DeleteFrameInfoL();
       
   743 
       
   744 	iHaveCompleteImageHeaders = ETrue;
       
   745 	}
       
   746 
       
   747 void CImageDecoderPriv::InitConvertL()
       
   748 	{
       
   749 	ASSERT((iCurrentFrame >= 0) && (iCurrentFrame < iFrameInfo.Count()));
       
   750 
       
   751 	// Set position to start of frame.
       
   752 	iPosition = iFrameInfo[iCurrentFrame]->iFrameDataOffset;
       
   753 
       
   754 	// Re-set conversion variables.
       
   755 	iSrcLength = 0;
       
   756 
       
   757 	// Set flag to say that we are now converting an image.
       
   758 	iCurrentlyProcessingData = ETrue;
       
   759 
       
   760 	// Re-initialise block length and codec
       
   761 	iBlockLength = iPlugin->FrameBlockSize(iCurrentFrame);
       
   762 
       
   763 	TBool disableErrorDiffusion = (iOptions & CImageDecoder::EOptionNoDither);
       
   764 	iImageReadCodec->SetCurrentFrame(iCurrentFrame);
       
   765 	iImageReadCodec->InitFrameL(*iFrameInfo[iCurrentFrame], *iFrameData[iCurrentFrame], disableErrorDiffusion,  *iDestination, iDestinationMask);
       
   766 
       
   767 	}
       
   768 
       
   769 void CImageDecoderPriv::RequestInitL(TInt aFrameNumber)
       
   770 	{
       
   771 	__ASSERT_ALWAYS(!IsActive(), Panic(EConvertCalledWhileBusy));
       
   772 	__ASSERT_ALWAYS((aFrameNumber >= 0) && (aFrameNumber < iFrameInfo.Count()), User::Leave(KErrArgument));
       
   773 
       
   774 	// Set current frame.
       
   775 	iCurrentFrame = aFrameNumber;
       
   776 	iImageReadCodec->SetCurrentFrame(iCurrentFrame);
       
   777 
       
   778 	// Set position to start of frame.
       
   779 	iPosition = iFrameInfo[iCurrentFrame]->iFrameDataOffset;
       
   780 
       
   781 	// Re-set conversion variables.
       
   782 	iSrcLength = 0;
       
   783 
       
   784 	// Set flag to say that we are now converting an image.
       
   785 	iCurrentlyProcessingData = ETrue;
       
   786 
       
   787 	// Re-initialise block length and codec
       
   788 	iBlockLength = iPlugin->FrameBlockSize(iCurrentFrame);
       
   789 	}
       
   790 	
       
   791 const TFrameInfo& CImageDecoderPriv::FrameInfo(TInt aFrameNumber) const
       
   792 	{
       
   793 	// Return the frame info for a particular frame
       
   794 	__ASSERT_ALWAYS((aFrameNumber >= 0) && (aFrameNumber < iFrameInfo.Count()), Panic(EFrameNumberOutOfRange));
       
   795 	return *iFrameInfo[aFrameNumber];
       
   796 	}
       
   797 
       
   798 CFrameInfoStrings* CImageDecoderPriv::FrameInfoStringsLC(TInt aFrameNumber)
       
   799 	{
       
   800 	CFrameInfoStrings* frameInfoStrings;
       
   801 	if (iFs == NULL)
       
   802 		{
       
   803 		RFs localRFs;
       
   804 		CleanupClosePushL(localRFs);
       
   805 
       
   806 		User::LeaveIfError(localRFs.Connect());
       
   807 		frameInfoStrings = iPlugin->FrameInfoStringsL(localRFs, aFrameNumber);
       
   808 		CleanupStack::PopAndDestroy(); // localRFs
       
   809 		}
       
   810 	else
       
   811 		frameInfoStrings = iPlugin->FrameInfoStringsL(*iFs, aFrameNumber);
       
   812 
       
   813 	CleanupStack::PushL(frameInfoStrings);
       
   814 	return frameInfoStrings;
       
   815 	}
       
   816 
       
   817 void CImageDecoderPriv::ReadDataL(TInt aPosition, TPtrC8& aReadBuffer, TInt aLength)
       
   818 	{
       
   819 	ASSERT(aPosition >= 0); 
       
   820  	ASSERT(aLength >= 0);	
       
   821 
       
   822 	TBool srcIsFile = ETrue;
       
   823 	TInt  srcSize = 0;
       
   824 	TInt  size = aLength;
       
   825 
       
   826 	if (iImageType == CImageDecoder::EImageTypeThumbnail) 
       
   827 		{
       
   828 		ASSERT(iThumbnailData!=NULL);
       
   829 		
       
   830 		srcSize = iThumbnailData->Length();
       
   831 		
       
   832 		// if trying to start reading past end of file do nothing
       
   833 		if(aPosition >= srcSize)
       
   834 			{
       
   835 			aReadBuffer.Set(KNullDesC8);
       
   836 			return;
       
   837 			}
       
   838 
       
   839 		if((aPosition + size) > srcSize)
       
   840 			{
       
   841 			// there is not enough data left read what is left.
       
   842 			size = srcSize - aPosition;
       
   843 			}
       
   844 
       
   845 		const TDesC8* srcDes = iThumbnailData;
       
   846 		ASSERT(srcDes != NULL);			
       
   847 		aReadBuffer.Set(srcDes->Mid(aPosition, size));
       
   848 		iSrcDes.Set(aReadBuffer);		
       
   849 		}
       
   850 	else
       
   851 		{
       
   852 		
       
   853 		if(iImageParameterData.IsFilename())
       
   854 			{ // The source if a file
       
   855 			ASSERT(iData); // The file has to be open
       
   856 			if (iUseBufferReadOptimization)
       
   857                 {
       
   858 				srcSize = DataSizeL();
       
   859                 }
       
   860 			else
       
   861                 {
       
   862 				iData->DataSizeL(srcSize);
       
   863                 }
       
   864 			
       
   865 
       
   866 			srcIsFile = ETrue;
       
   867 			}
       
   868 		else
       
   869 			{ // The source is a descriptor
       
   870 			srcSize = iImageParameterData.SourceDataPtr()->Length();
       
   871 			srcIsFile = EFalse;
       
   872 			}
       
   873 
       
   874 		// if trying to start reading past end of file do nothing
       
   875 		if(aPosition >= srcSize)
       
   876 			{
       
   877 			aReadBuffer.Set(KNullDesC8);
       
   878 			return;
       
   879 			}
       
   880 
       
   881 		if((aPosition + size) > srcSize)
       
   882 			{
       
   883 			// there is not enough data left read what is left.
       
   884 			size = srcSize - aPosition;
       
   885 			}
       
   886 
       
   887 		TBool bufferedRead = srcIsFile || MustUseBufferWithDescriptor();
       
   888 
       
   889 		if(bufferedRead)
       
   890 			{
       
   891 			TBool allocNewBuf = EFalse;
       
   892          
       
   893 			// read source into local buffer
       
   894 			if(iReadBuffer == NULL)
       
   895 				{
       
   896 				iReadBuffer = HBufC8::NewMaxL(size);
       
   897 				allocNewBuf = ETrue;
       
   898 				}
       
   899 
       
   900 			TPtr8 ptr(iReadBuffer->Des());
       
   901 			//Grow iReadBuffer if necessary
       
   902 			if(ptr.MaxLength() < size)
       
   903 				{
       
   904 				delete iReadBuffer; iReadBuffer = NULL;
       
   905 				iReadBuffer = HBufC8::NewMaxL(size);
       
   906 				ptr.Set(iReadBuffer->Des());
       
   907 				allocNewBuf = ETrue;				     
       
   908 				}
       
   909 
       
   910 			if (srcIsFile)
       
   911 				{
       
   912                 if (iUseBufferReadOptimization)
       
   913                     {
       
   914                     // See if the end of the last read overlaps the start of the next read.
       
   915                     TInt extent = aPosition + size;
       
   916                     TBool overlaps =
       
   917                     // not newly-created buffer
       
   918                         ! allocNewBuf
       
   919                     // start position at or before start of last read
       
   920                         &&  iLastPos <= aPosition
       
   921                     // extent (end position) currently in buffer
       
   922                         &&  iLastExtent > aPosition && iLastExtent <= extent;
       
   923 	               
       
   924                     if (overlaps)
       
   925                         {
       
   926                         // copy the overlap portion to the start of the read buffer
       
   927                         TInt overlapOffset = aPosition - iLastPos;
       
   928                         TInt overlapAmount = iLastExtent - aPosition;
       
   929                         ptr.Copy(ptr.Mid(overlapOffset, overlapAmount));
       
   930                                    
       
   931                         // read the excess from the file
       
   932                         // expand ptr, else MidTPtr will only use the current data
       
   933                         // after the overlap amount for its maximum length
       
   934                         ptr.SetMax();
       
   935                         TPtr8 excess(ptr.MidTPtr(overlapAmount));
       
   936                         SeekReadL(aPosition + overlapAmount, excess, size - overlapAmount);
       
   937                                    
       
   938                         ptr.SetLength(overlapAmount + excess.Length());
       
   939                         }
       
   940 
       
   941                     else
       
   942                         {
       
   943                         SeekReadL(aPosition, ptr, size);
       
   944                         }
       
   945    
       
   946                     iLastPos = aPosition;
       
   947                     iLastExtent = extent;
       
   948                     }
       
   949                 else
       
   950                     {
       
   951                     User::LeaveIfError(iData->Seek(ESeekStart, aPosition));
       
   952                     User::LeaveIfError(iData->Read(ptr, size));
       
   953                     }
       
   954                 
       
   955 				}
       
   956 			else
       
   957 				{
       
   958 				ASSERT(!srcIsFile && MustUseBufferWithDescriptor());
       
   959 				const TDesC8* srcDes = iImageParameterData.SourceDataPtr();
       
   960 				ASSERT(srcDes != NULL);			
       
   961 				CopyBufferToDescriptor(ptr, *srcDes, aPosition, size); 
       
   962 				}
       
   963 			aReadBuffer.Set(iReadBuffer->Des());
       
   964 			}
       
   965 		else
       
   966 			{//Read block from descriptor
       
   967 			const TDesC8* srcDes = iImageParameterData.SourceDataPtr();
       
   968 			ASSERT(srcDes != NULL);			
       
   969 			aReadBuffer.Set(srcDes->Mid(aPosition, size));
       
   970 			}
       
   971 		iSrcDes.Set(aReadBuffer);
       
   972 		}
       
   973 	}
       
   974  
       
   975 void CImageDecoderPriv::HandleNewlyOpenedImageL()
       
   976 	{
       
   977 	// Tell the plugin that the user wants mask generation.
       
   978 	if (iOptions & CImageDecoder::EAllowGeneratedMask)
       
   979 		iPlugin->EnableMaskGeneration();
       
   980 
       
   981 	// call ScanDataL to read in the first header, at least.
       
   982 	TRAPD(error,iPlugin->ScanDataL());
       
   983 
       
   984 	// ignore underflow at this point only if the user has set the EOptionAllowZeroFrameOpen flag
       
   985 	if (error == KErrUnderflow)
       
   986 		if (iOptions & CImageDecoder::EOptionAllowZeroFrameOpen)
       
   987 			return;
       
   988 		else
       
   989 			User::Leave(error);
       
   990 		
       
   991 
       
   992 	if (error!=KErrNone) 
       
   993 		User::Leave(error);
       
   994 	}
       
   995 
       
   996 TUid CImageDecoderPriv::ImplementationUid() const
       
   997 	{
       
   998 	return iConstruct->ImplementationUid();
       
   999 	}
       
  1000 
       
  1001 /**
       
  1002  * Passes on CustomSyncL to plugin
       
  1003  *
       
  1004  */
       
  1005 
       
  1006 void CImageDecoderPriv::CustomSyncL(TInt aParam)
       
  1007 	{
       
  1008 	iPlugin->HandleCustomSyncL(aParam);
       
  1009 	}
       
  1010 
       
  1011 /**
       
  1012  * Plugin is interrogated with InitCustomAsyncL. If this works, then set internal Convert() cycle going
       
  1013  *
       
  1014  */
       
  1015 
       
  1016 void CImageDecoderPriv::CustomAsync(RThread& aRequestThread, TRequestStatus* aRequestStatus, TInt aParam)
       
  1017 	{
       
  1018 	__ASSERT_ALWAYS(!IsActive(), Panic(EConvertCalledWhileBusy));
       
  1019 
       
  1020 	TRAPD(error, iPlugin->InitCustomAsyncL(aParam));
       
  1021 
       
  1022 	iRequestThread = &aRequestThread;
       
  1023 	iConvStatus = aRequestStatus;
       
  1024 	*iConvStatus = KRequestPending;
       
  1025 
       
  1026 	if (error==KErrNone)
       
  1027 		SelfComplete(KErrNone);
       
  1028 	else
       
  1029 		RequestComplete(error);
       
  1030 	}
       
  1031 
       
  1032 /**
       
  1033  *  Indicate if running in a separate thread
       
  1034  * 
       
  1035  */
       
  1036 
       
  1037 TBool CImageDecoderPriv::AmInThread() const
       
  1038 	{
       
  1039 	return iSupport->AmInThread();
       
  1040 	}
       
  1041 
       
  1042 /**
       
  1043  *  Indicate if a decode should abort early (ie. following a Cancel). Always false unless in a thread.
       
  1044  * 
       
  1045  */
       
  1046 
       
  1047 TBool CImageDecoderPriv::ShouldAbort() const
       
  1048 	{
       
  1049 	return iSupport->ShouldAbort();
       
  1050 	}
       
  1051 
       
  1052 void CImageDecoderPriv::SetIntent(ContentAccess::TIntent aIntent)
       
  1053 	{
       
  1054 	iIntent = aIntent;
       
  1055 	}
       
  1056 
       
  1057 void CImageDecoderPriv::SetUniqueIdL(const TDesC& aUniqueId)
       
  1058 	{
       
  1059 	delete iUniqueId;
       
  1060 	iUniqueId = NULL;
       
  1061 	iUniqueId = aUniqueId.AllocL();
       
  1062 	}
       
  1063 
       
  1064 TInt CImageDecoderPriv::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
       
  1065 	{
       
  1066 	return iContent->SetProperty(aProperty, aValue);
       
  1067 	}
       
  1068 	
       
  1069 TInt CImageDecoderPriv::ReductionFactor(const TSize& aOriginalSize, const TSize& aReducedSize) const
       
  1070 	{
       
  1071 	return iImageReadCodec->ReductionFactor(aOriginalSize, aReducedSize);
       
  1072 	}
       
  1073 
       
  1074 TInt CImageDecoderPriv::ReducedSize(const TSize& aOriginalSize, TInt aReductionFactor, TSize& aReducedSize) const	
       
  1075 	{
       
  1076 	return iImageReadCodec->ReducedSize(aOriginalSize, aReductionFactor, aReducedSize);
       
  1077 	}
       
  1078 	
       
  1079 void CImageDecoderPriv::GetExtensionL(TUid aExtUid, MImageConvExtension*& aExtPtr)
       
  1080 	{
       
  1081 	iPlugin->GetExtensionL(aExtUid, aExtPtr);
       
  1082 	}
       
  1083 	
       
  1084 void CImageDecoderPriv::SetClippingRectL(const TRect* aClipRect)
       
  1085 	{
       
  1086 	iPlugin->SetClippingRectL(aClipRect);
       
  1087 	}
       
  1088 	
       
  1089 TInt CImageDecoderPriv::GetDestinationSize(TSize& aSize, TInt aFrameNumber)
       
  1090 	{
       
  1091 	return iPlugin->GetDestinationSize(aSize, aFrameNumber);
       
  1092 	}
       
  1093 
       
  1094 void CImageDecoderPriv::RegisterClientRequestStatus(RThread& aRequestThread, TRequestStatus* aRequestStatus)
       
  1095 	{
       
  1096 	__ASSERT_ALWAYS(!IsActive(), Panic(EFwExtensionBusy));
       
  1097 
       
  1098 	iRequestThread = &aRequestThread;
       
  1099 	iConvStatus = aRequestStatus;
       
  1100 	*iConvStatus = KRequestPending;
       
  1101 	}
       
  1102 	
       
  1103 void CImageDecoderPriv::StartActivity()
       
  1104 	{
       
  1105 	SetSelfPending();
       
  1106 	SelfComplete(KErrNone);
       
  1107 	}
       
  1108 
       
  1109 /* IMAGE ENCODER PRIVATE*/
       
  1110 CImageEncoderPriv* CImageEncoderPriv::NewL(CImageEncodeConstruct* aConstruct, MImageEncoderPrivSupport* aSupport)
       
  1111 	{
       
  1112 	CImageEncoderPriv* self = new (ELeave) CImageEncoderPriv(aConstruct, aSupport);
       
  1113 	return self;
       
  1114 	}
       
  1115 
       
  1116 void CImageEncoderPriv::SetFileL(RFs& aFs, const TDesC& aDestinationFilename, const CImageEncoder::TOptions aOptions)
       
  1117 	{
       
  1118 	iFs = &aFs;
       
  1119 	User::LeaveIfError(iFile.Replace(*iFs, aDestinationFilename, EFileWrite | EFileShareAny));
       
  1120 	iImageParameterData.SetFilenamePtr(&aDestinationFilename);
       
  1121 	iOptions = aOptions;
       
  1122 	
       
  1123 #if defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1124 	ASSERT( iAsyncFileWriter == NULL );
       
  1125 	iAsyncFileWriter = CAsyncFileWriter::NewL(*this,iFile, KMaxDstBufferSize );
       
  1126 	iAsyncFileWriter->CheckBufferOut( iDstDes );
       
  1127 #endif // defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1128 	}
       
  1129 
       
  1130 void CImageEncoderPriv::SetFileL(RFile& aFile, const CImageEncoder::TOptions aOptions)
       
  1131 	{
       
  1132 	User::LeaveIfError(iFile.Duplicate(aFile));
       
  1133 	TInt pos = 0;
       
  1134 	User::LeaveIfError(iFile.Seek(ESeekStart, pos));
       
  1135 	User::LeaveIfError(iFile.Name(iFileName));
       
  1136 	iImageParameterData.SetFilenamePtr(&iFileName);
       
  1137 	iOptions = aOptions;
       
  1138 	
       
  1139 #if defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1140 	ASSERT( iAsyncFileWriter == NULL );
       
  1141 	iAsyncFileWriter = CAsyncFileWriter::NewL(*this, iFile, KMaxDstBufferSize );
       
  1142 	iAsyncFileWriter->CheckBufferOut( iDstDes );
       
  1143 #endif // defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1144 	}
       
  1145 
       
  1146 
       
  1147 void CImageEncoderPriv::SetThumbnail(TBool aDoGenerateThumbnail)
       
  1148 	{
       
  1149 	iPlugin->SetThumbnail(aDoGenerateThumbnail);
       
  1150 	}
       
  1151 
       
  1152 void CImageEncoderPriv::SetDataL(HBufC8*& aDestinationData, const CImageEncoder::TOptions aOptions)
       
  1153 	{
       
  1154 	iDestination = &aDestinationData;
       
  1155 	iImageParameterData.SetDataPtr(aDestinationData);
       
  1156 	iOptions = aOptions;
       
  1157 	}
       
  1158 
       
  1159 CImageEncoderPriv::CImageEncoderPriv(CImageEncodeConstruct* aConstruct, MImageEncoderPrivSupport* aSupport)
       
  1160 	: CActive(CActive::EPriorityIdle), iConstruct(aConstruct), iSupport(aSupport)
       
  1161 	{
       
  1162 	ASSERT(aConstruct);
       
  1163 	CActiveScheduler::Add(this);
       
  1164 	}
       
  1165 
       
  1166 CImageEncoderPriv::~CImageEncoderPriv()
       
  1167 	{
       
  1168 	ASSERT(!IsActive());
       
  1169 	if (iPlugin)
       
  1170 		iPlugin->Cleanup();
       
  1171 	iFile.Close();
       
  1172 	delete iFinalDstBuffer;
       
  1173 	delete iPlugin;
       
  1174 #if defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1175 	delete iAsyncFileWriter;
       
  1176 #endif // defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1177 	}
       
  1178 
       
  1179 void CImageEncoderPriv::CreatePluginL()
       
  1180 	{
       
  1181 	iPlugin = iConstruct->NewPluginL();
       
  1182 	iPlugin->iProperties = this;
       
  1183 	}
       
  1184 
       
  1185 TInt CImageEncoderPriv::CurrentImageSizeL() const
       
  1186 	{
       
  1187 	TInt size;
       
  1188 	if( iImageParameterData.IsFilename())
       
  1189 		{
       
  1190 		ASSERT(iFile.SubSessionHandle() != 0);
       
  1191 		User::LeaveIfError(iFile.Size(size));
       
  1192 		}
       
  1193 	else
       
  1194 		{
       
  1195 		ASSERT(iFinalDstBuffer != NULL);
       
  1196 		size = iFinalDstBuffer->Length();
       
  1197 		}
       
  1198 	return size;
       
  1199 	}
       
  1200 
       
  1201 void CImageEncoderPriv::Cleanup()
       
  1202 	{
       
  1203 	if(iImageParameterData.IsDataTypeDefined())
       
  1204 		{
       
  1205 		if (iImageParameterData.IsFilename() && (iFile.SubSessionHandle() != 0))
       
  1206 			{
       
  1207 			if(iFs != NULL)
       
  1208 				{
       
  1209 				// Delete file
       
  1210 				TFileName fileName;
       
  1211 				iFile.FullName(fileName);
       
  1212 				iFile.Close();
       
  1213 				iFs->Delete(fileName);
       
  1214 				}
       
  1215 			else
       
  1216 				{
       
  1217 				// Set file length zero
       
  1218 				iFile.SetSize(0);
       
  1219 				iFile.Close();
       
  1220 				}
       
  1221 			}
       
  1222 		}
       
  1223 
       
  1224 	// Delete any objects we should get rid of
       
  1225 	delete iImageWriteCodec; iImageWriteCodec = NULL; // Created in Convert()
       
  1226 	delete iDstBuffer; iDstBuffer = NULL; // Created in Convert()
       
  1227 	
       
  1228 #if defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1229 	delete iAsyncFileWriter; iAsyncFileWriter = NULL;
       
  1230 #endif // defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)	
       
  1231 	}
       
  1232 
       
  1233 void CImageEncoderPriv::InitConvertL()
       
  1234 	{
       
  1235 	ASSERT(iSource != NULL);
       
  1236 	iImageWriteCodec->InitFrameL(iDstDes, *iSource);
       
  1237 	}
       
  1238 
       
  1239 void CImageEncoderPriv::RequestInitL()
       
  1240 	{
       
  1241 	__ASSERT_ALWAYS(!IsActive(), Panic(EConvertCalledWhileBusy));
       
  1242 	__ASSERT_ALWAYS(!iConvertStarted, Panic(EIllegalEncoderRestart));
       
  1243 				
       
  1244 	// once encoding starts, the encoder must not be reused
       
  1245 	iConvertStarted = ETrue;
       
  1246 	
       
  1247 #if defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)    
       
  1248     if(!iImageParameterData.IsFilename())
       
  1249 #endif    
       
  1250         {
       
  1251         if (!iDstBuffer)
       
  1252 		    {
       
  1253 		    iDstBuffer = HBufC8::NewMaxL(KMaxDstBufferSize);
       
  1254 		    }        
       
  1255         iDstDes.Set(iDstBuffer->Des());
       
  1256         }
       
  1257 
       
  1258 	iHeaderWritten=EFalse;
       
  1259 	}
       
  1260 	
       
  1261 void CImageEncoderPriv::Convert(RThread& aRequestThread, TRequestStatus* aRequestStatus, const CFbsBitmap& aSource, const CFrameImageData* aFrameImageData)
       
  1262 	{
       
  1263 	if (iConvertStarted)
       
  1264 		Panic(EIllegalEncoderRestart);
       
  1265 	
       
  1266 	if (IsActive())
       
  1267 		Panic(EConvertCalledWhileBusy);
       
  1268 
       
  1269 	// once encoding starts, the encoder must not be reused
       
  1270 	iConvertStarted = ETrue;
       
  1271 	
       
  1272 	iRequestThread = &aRequestThread;
       
  1273 	iConvStatus = aRequestStatus;
       
  1274 	*iConvStatus = KRequestPending;
       
  1275 	iSource = &aSource;
       
  1276 
       
  1277 	iFrameInfo.iOverallSizeInPixels = iSource->SizeInPixels();
       
  1278 	iFrameInfo.iFrameSizeInTwips = iSource->SizeInTwips();
       
  1279 	
       
  1280 	if(aSource.Handle()!=0 && aSource.ExtendedBitmapType()!=KNullUid)
       
  1281         {
       
  1282         RequestComplete(KErrNotSupported);
       
  1283         return;
       
  1284         }
       
  1285 	
       
  1286 	TRAPD(leaveErr, iPlugin->PrepareEncoderL(aFrameImageData));
       
  1287 	if (leaveErr != KErrNone)
       
  1288 		{
       
  1289 		RequestComplete(leaveErr);
       
  1290 		return;
       
  1291 		}
       
  1292 		
       
  1293 #if defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)		
       
  1294     if (! iImageParameterData.IsFilename() )
       
  1295 #endif 
       
  1296         {
       
  1297         
       
  1298     	if (!iDstBuffer)
       
  1299     		{
       
  1300     		TRAP(leaveErr, iDstBuffer = HBufC8::NewMaxL(KMaxDstBufferSize));
       
  1301     		if (leaveErr != KErrNone)
       
  1302     			{
       
  1303     			RequestComplete(leaveErr);
       
  1304     			return;
       
  1305     			}
       
  1306     		}
       
  1307 
       
  1308     	iDstDes.Set(iDstBuffer->Des());
       
  1309         }
       
  1310         
       
  1311 	TRAP(leaveErr, iPlugin->InitConvertL());
       
  1312 	if(leaveErr != KErrNone)
       
  1313 		{
       
  1314 		RequestComplete(leaveErr);
       
  1315 		return;
       
  1316 		}
       
  1317 
       
  1318 	// we generate the exif data and write it
       
  1319 	// this method is asynchronous: it also starts generating the thumbnail
       
  1320 	TRequestStatus* status=&iStatus;
       
  1321 	SetSelfPending();
       
  1322 	TRAP(leaveErr, iPlugin->WriteExifDataL(status));
       
  1323 	if(leaveErr != KErrNone)
       
  1324 		{
       
  1325 		RequestComplete(leaveErr);
       
  1326 		return;
       
  1327 		}
       
  1328 	iHeaderWritten=EFalse;
       
  1329 
       
  1330 	// the wating for the request to complete is initiated in the Image plugin
       
  1331 	}
       
  1332 
       
  1333 void CImageEncoderPriv::RunL()
       
  1334 	{
       
  1335 	if(!iHeaderWritten)
       
  1336 		{
       
  1337 		if(iStatus.Int()!=KErrNone)
       
  1338 			{
       
  1339 			RequestComplete( iStatus.Int() );
       
  1340 			}
       
  1341 		else
       
  1342 			{
       
  1343 			// the thumbnail image has been created, we can now write it in the file
       
  1344 			TRAPD(leaveErr, iPlugin->WriteThumbnailL());
       
  1345 			if(leaveErr != KErrNone)
       
  1346 				{
       
  1347 				RequestComplete(leaveErr);
       
  1348 				return;
       
  1349 				}
       
  1350 
       
  1351 			// Write the JFIF header
       
  1352 			TRAP(leaveErr,WriteDataPositionIncL(iStartPosition,iDstDes));
       
  1353 			if (leaveErr != KErrNone)
       
  1354 				{
       
  1355 				RequestComplete(leaveErr);
       
  1356 				return;
       
  1357 				}
       
  1358 
       
  1359 			iHeaderWritten=ETrue;
       
  1360 			SelfComplete(KErrNone);
       
  1361 			}
       
  1362 		}
       
  1363 	else
       
  1364 		{
       
  1365 		iPlugin->DoConvert();
       
  1366 		}
       
  1367 	}
       
  1368 
       
  1369 void CImageEncoderPriv::DoCancel()
       
  1370 	{
       
  1371 	iPlugin->Cleanup();
       
  1372 			
       
  1373 	// if SetSelfPending() has been called but not SelfComplete()
       
  1374 	// (i.e. the AO is active but there's still an outstanding request)
       
  1375 	// then we need to complete the request
       
  1376 	if (IsActive() && iStatus == KRequestPending)
       
  1377 		SelfComplete(KErrCancel);
       
  1378 
       
  1379 	RequestComplete(KErrCancel);
       
  1380 	}
       
  1381 
       
  1382 void CImageEncoderPriv::RequestComplete(TInt aReason)
       
  1383 	{
       
  1384 	ASSERT(iPlugin);
       
  1385 	iPlugin->NotifyComplete();
       
  1386 	ASSERT(iRequestThread);
       
  1387 	if (iConvStatus && (*iConvStatus == KRequestPending) )
       
  1388 		{
       
  1389 		iRequestThread->RequestComplete(iConvStatus, aReason);
       
  1390 		}
       
  1391 	}
       
  1392 	
       
  1393 void CImageEncoderPriv::WriteDataL(TInt aPosition,const TDesC8& aDes)
       
  1394 	{
       
  1395 	ASSERT(aPosition >= 0); 
       
  1396 	ASSERT(aDes.Length() >= 0);
       
  1397 
       
  1398 	TInt  destSize = 0;
       
  1399 	
       
  1400 	if(iImageParameterData.IsFilename())
       
  1401 		{ // The source if a file
       
  1402 		ASSERT(iFile.SubSessionHandle() != 0); // The file has to be open
       
  1403 		User::LeaveIfError(iFile.Size(destSize));
       
  1404 
       
  1405 		//If we start writing past EOF
       
  1406 		if (aPosition > destSize)
       
  1407 			{
       
  1408 			User::LeaveIfError(iFile.SetSize(aPosition));
       
  1409 			}
       
  1410 		User::LeaveIfError(iFile.Write(aPosition,aDes));
       
  1411 		// if the data has been appended to the file, we need to update the current position in the text
       
  1412 		}
       
  1413 	else
       
  1414 		{ // The source is a descriptor
       
  1415 		const TInt  totalSize = aPosition + aDes.Length();
       
  1416 		// totalSize is equal to the minimum length that the
       
  1417 		// destination descriptor has to be.  It is NOT the total
       
  1418 		// length of the destination descriptor - NJ
       
  1419 
       
  1420 		if (iFinalDstBuffer == NULL)
       
  1421 			{
       
  1422 			iFinalDstBuffer = HBufC8::NewMaxL(totalSize);
       
  1423 			}
       
  1424 		destSize = iFinalDstBuffer->Length();
       
  1425 
       
  1426 		//The buffer is too small
       
  1427 		if (destSize < totalSize)
       
  1428 			{
       
  1429 			iFinalDstBuffer = iFinalDstBuffer->ReAllocL(totalSize);
       
  1430 			}
       
  1431 
       
  1432 		// check to see if we are extending the descriptor (eg. append)
       
  1433 		if (totalSize > destSize)
       
  1434 			{
       
  1435 			iFinalDstBuffer->Des().SetLength(totalSize);
       
  1436 			}
       
  1437 
       
  1438 		// replace the current descriptor contents with the new data
       
  1439 		iFinalDstBuffer->Des().Replace(aPosition,aDes.Length(),aDes);
       
  1440 		}
       
  1441 	}
       
  1442 
       
  1443 void CImageEncoderPriv::WriteDataPositionIncL(TInt aPosition,const TDesC8& aDes)
       
  1444 	{
       
  1445 	WriteDataL(aPosition, aDes);
       
  1446 	if(aPosition+aDes.Length() > iPosition)
       
  1447 		{
       
  1448     	iPosition+=aDes.Length();
       
  1449     	}
       
  1450 	}
       
  1451 
       
  1452 void CImageEncoderPriv::SelfComplete(TInt aReason)
       
  1453 	{
       
  1454 	if (!IsActive())	// may already be active if SetSelfPending() called
       
  1455 		SetActive();
       
  1456 	TRequestStatus* status = &iStatus;
       
  1457 	User::RequestComplete(status, aReason);
       
  1458 	}
       
  1459 
       
  1460 void CImageEncoderPriv::SetSelfPending()
       
  1461 	{
       
  1462 	iStatus = KRequestPending;
       
  1463 	SetActive();
       
  1464 	}
       
  1465 
       
  1466 void CImageEncoderPriv::DoConvert()
       
  1467 	{
       
  1468 	TFrameState codecState = EFrameIncomplete;
       
  1469 	TRAPD(errCode, codecState = iImageWriteCodec->ProcessFrameL(iDstDes));
       
  1470 
       
  1471 	HandleProcessFrameResult(errCode, codecState);
       
  1472 	}
       
  1473 	
       
  1474 #if defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)
       
  1475 
       
  1476 /*virtual*/
       
  1477 void CImageEncoderPriv::BufferWritten(const TPtrC8& aWritten, TInt aErrorCode)
       
  1478     {
       
  1479     if (aErrorCode == KErrNone)
       
  1480         {
       
  1481         iAsyncFileWriter->CheckBufferIn(aWritten);
       
  1482         }
       
  1483     
       
  1484     if (aErrorCode != KErrNone)
       
  1485         {
       
  1486         iWriterError = aErrorCode;
       
  1487         RequestComplete( iWriterError );
       
  1488         return;
       
  1489         }
       
  1490     }
       
  1491 
       
  1492 void CImageEncoderPriv::HandleProcessFrameResult(TInt aErrCode, TFrameState aCodecState)	
       
  1493     {
       
  1494 	if (aErrCode == KErrNone)
       
  1495 		{
       
  1496 		TRAP(aErrCode, DoHandleProcessFrameResultL(aCodecState) );
       
  1497 		}
       
  1498 
       
  1499 	if (aErrCode != KErrNone)
       
  1500 	    {
       
  1501 	    RequestComplete(aErrCode);
       
  1502 	    }	
       
  1503     }
       
  1504     
       
  1505 void CImageEncoderPriv::DoHandleProcessFrameResultL(TFrameState aCodecState)
       
  1506 	{
       
  1507 	User::LeaveIfError( iWriterError );
       
  1508 	
       
  1509     const TBool lastBuffer = (aCodecState == EFrameComplete || (aCodecState != EBlockComplete && iDstDes.Length() == 0));
       
  1510 
       
  1511 	if(iImageParameterData.IsFilename())
       
  1512 		{ // The source if a file
       
  1513 		ASSERT(iFile.SubSessionHandle() != 0); // The file has to be open
       
  1514 		
       
  1515 		if (lastBuffer)
       
  1516 		    {
       
  1517 		    User::LeaveIfError( iAsyncFileWriter->FlushBuffers() );
       
  1518 		    }
       
  1519 
       
  1520 		TPtr8 newBuffer(NULL, 0);
       
  1521         iAsyncFileWriter->WriteBufferL(iDstDes, iStartPosition + iPosition);
       
  1522 
       
  1523         iAsyncFileWriter->CheckBufferOut( newBuffer );
       
  1524 
       
  1525     	if(iStartPosition + iPosition + iDstDes.Length() > iPosition)
       
  1526     		{
       
  1527         	iPosition+=iDstDes.Length();
       
  1528         	}
       
  1529         iDstDes.Set( newBuffer );
       
  1530 		}
       
  1531 	else
       
  1532 	    {
       
  1533 	    WriteDataPositionIncL(iStartPosition + iPosition, iDstDes);
       
  1534 	    }
       
  1535 	    
       
  1536 	if (lastBuffer || aCodecState == EBlockComplete)
       
  1537 		{
       
  1538 		if(lastBuffer)
       
  1539 			{
       
  1540 			FinishConvertL();
       
  1541 			}
       
  1542 		RequestComplete(KErrNone);
       
  1543 		}
       
  1544 	else	    
       
  1545     	{
       
  1546     	SelfComplete(KErrNone);
       
  1547     	}
       
  1548 	}
       
  1549 	
       
  1550 #else
       
  1551 
       
  1552 void CImageEncoderPriv::HandleProcessFrameResult(TInt aErrCode, TFrameState aCodecState)
       
  1553 	{
       
  1554 	if (aErrCode != KErrNone)
       
  1555 		{
       
  1556 		RequestComplete(aErrCode);
       
  1557 		return;
       
  1558 		}
       
  1559 
       
  1560 	if (aCodecState == EFrameComplete || iDstDes.Length() == 0)
       
  1561 		iLastBuffer = ETrue;
       
  1562 
       
  1563 	TRAPD(leaveErr,WriteDataPositionIncL(iStartPosition + iPosition, iDstDes));
       
  1564 	if (leaveErr != KErrNone)
       
  1565 		{
       
  1566 		RequestComplete(leaveErr);
       
  1567 		return;
       
  1568 		}
       
  1569 
       
  1570 	if (iLastBuffer || aCodecState == EBlockComplete)
       
  1571 		{
       
  1572 		if(iLastBuffer)
       
  1573 			{
       
  1574 			TRAP(leaveErr, FinishConvertL());
       
  1575 			}
       
  1576 		iLastBuffer = EFalse;
       
  1577 		RequestComplete(leaveErr);
       
  1578 		}
       
  1579 	else
       
  1580 		{
       
  1581 		SelfComplete(KErrNone);
       
  1582 		}
       
  1583 	}
       
  1584 #endif // defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES)
       
  1585 
       
  1586 TBufPtr8& CImageEncoderPriv::DestinationData()
       
  1587 	{
       
  1588 	return iDstDes;
       
  1589 	}
       
  1590 
       
  1591 void CImageEncoderPriv::FinishConvertL()
       
  1592 	{
       
  1593 	iPlugin->UpdateHeaderL();
       
  1594 	if (!iImageParameterData.IsFilename())
       
  1595 		{
       
  1596 		*iDestination = iFinalDstBuffer;
       
  1597 		iFinalDstBuffer = NULL;
       
  1598 		}
       
  1599 	else
       
  1600 		{
       
  1601 		iFile.Close(); // close the file
       
  1602 		}
       
  1603 	}
       
  1604 
       
  1605 TUid CImageEncoderPriv::ImplementationUid() const
       
  1606 	{
       
  1607 	return iConstruct->ImplementationUid();
       
  1608 	}
       
  1609 
       
  1610 const CFrameImageData& CImageDecoderPriv::FrameData(TInt aFrameNumber) const
       
  1611 	{
       
  1612 	// Return the frame image data for a particular frame.
       
  1613 	__ASSERT_ALWAYS((aFrameNumber >= 0) && (aFrameNumber < iFrameInfo.Count()), Panic(EFrameNumberOutOfRange));
       
  1614 	return *iFrameData[aFrameNumber];
       
  1615 	}
       
  1616 
       
  1617 
       
  1618 /**
       
  1619  * Passes on CustomSyncL to plugin
       
  1620  *
       
  1621  */
       
  1622 
       
  1623 void CImageEncoderPriv::CustomSyncL(TInt aParam)
       
  1624 	{
       
  1625 #if ( defined(WRITER_EMULATE_SLOW_MEDIA) && defined(SYMBIAN_ENABLE_ENCODER_ASYNC_WRITES) )
       
  1626 // that's for testing/debugging only !
       
  1627     if ( aParam == KUidIclTestEmulateSlowMedia.iUid && iAsyncFileWriter != NULL )
       
  1628         {
       
  1629         iAsyncFileWriter->iEmulateSlowMedia = ETrue;
       
  1630         return;
       
  1631         }
       
  1632 #endif 
       
  1633 	
       
  1634 	iPlugin->HandleCustomSyncL(aParam);
       
  1635 	}
       
  1636 
       
  1637 /**
       
  1638  * Plugin is interrogated with InitCustomAsyncL. If this works, then set internal Convert() cycle going
       
  1639  *
       
  1640  */
       
  1641 
       
  1642 void CImageEncoderPriv::CustomAsync(RThread& aRequestThread, TRequestStatus* aRequestStatus, TInt aParam)
       
  1643 	{
       
  1644 	__ASSERT_ALWAYS(!IsActive(), Panic(EConvertCalledWhileBusy));
       
  1645 	
       
  1646 	TRAPD(error, iPlugin->InitCustomAsyncL(aParam));
       
  1647 
       
  1648 	iRequestThread = &aRequestThread;
       
  1649 	iConvStatus = aRequestStatus;
       
  1650 	*iConvStatus = KRequestPending;
       
  1651 
       
  1652 	if (error==KErrNone)
       
  1653 		SelfComplete(KErrNone);
       
  1654 	else
       
  1655 		RequestComplete(error);	
       
  1656 	}
       
  1657 
       
  1658 /**
       
  1659  *  Indicate if running in a separate thread
       
  1660  * 
       
  1661  */
       
  1662 
       
  1663 TBool CImageEncoderPriv::AmInThread() const
       
  1664 	{
       
  1665 	return iSupport->AmInThread();
       
  1666 	}
       
  1667 
       
  1668 /**
       
  1669  *  Indicate if a decode should abort early (ie. following a Cancel). Always false unless in a thread.
       
  1670  * 
       
  1671  */
       
  1672 
       
  1673 TBool CImageEncoderPriv::ShouldAbort() const
       
  1674 	{
       
  1675 	return iSupport->ShouldAbort();
       
  1676 	}
       
  1677 	
       
  1678 void CImageEncoderPriv::GetExtensionL(TUid aExtUid, MImageConvExtension*& aExtPtr)
       
  1679 	{
       
  1680 	iPlugin->GetExtensionL(aExtUid, aExtPtr);
       
  1681 	}
       
  1682 	
       
  1683 void CImageEncoderPriv::RegisterClientRequestStatus(RThread& aRequestThread, TRequestStatus* aRequestStatus)
       
  1684 	{
       
  1685 	__ASSERT_ALWAYS(!IsActive(), Panic(EConvertCalledWhileBusy));
       
  1686 
       
  1687 	iRequestThread = &aRequestThread;
       
  1688 	iConvStatus = aRequestStatus;
       
  1689 	*iConvStatus = KRequestPending;
       
  1690 	}
       
  1691 	
       
  1692 void CImageEncoderPriv::StartActivity()
       
  1693 	{
       
  1694 	SetSelfPending();
       
  1695 	SelfComplete(KErrNone);
       
  1696 	}
       
  1697 
       
  1698 // CImageDataArray
       
  1699 CImageDataArray::~CImageDataArray()
       
  1700 	{
       
  1701 	iImageData.ResetAndDestroy();
       
  1702 	iImageBuffers.ResetAndDestroy();
       
  1703 	}
       
  1704 
       
  1705 // Inline these.
       
  1706 TInt CImageDataArray::InsertImageData(const TImageDataBlock* aEntry, TInt aPos)
       
  1707 	{
       
  1708 	ASSERT(aEntry != NULL);
       
  1709 	return iImageData.Insert(aEntry, aPos);
       
  1710 	}
       
  1711 
       
  1712 TInt CImageDataArray::AppendImageData(const TImageDataBlock* aEntry)
       
  1713 	{
       
  1714 	ASSERT(aEntry != NULL);
       
  1715 	return iImageData.Append(aEntry);
       
  1716 	}
       
  1717 
       
  1718 void CImageDataArray::RemoveImageData(TInt aIndex)
       
  1719 	{
       
  1720 	iImageData.Remove(aIndex);
       
  1721 	}
       
  1722 
       
  1723 // Get image data/local image data.
       
  1724 const TImageDataBlock* CImageDataArray::GetImageData(TInt aIndex) const
       
  1725 	{
       
  1726 	return iImageData[aIndex];
       
  1727 	}
       
  1728 
       
  1729 TImageDataBlock* CImageDataArray::GetImageData(TInt aIndex)
       
  1730 	{
       
  1731 	return iImageData[aIndex];
       
  1732 	}
       
  1733 
       
  1734 // Get num entries.
       
  1735 TInt CImageDataArray::ImageDataCount() const
       
  1736 	{
       
  1737 	return iImageData.Count();
       
  1738 	}
       
  1739 
       
  1740 // Append image buffer.
       
  1741 TInt CImageDataArray::AppendImageBuffer(const HBufC8* aImageBuffer)
       
  1742 	{
       
  1743 	return iImageBuffers.Append(aImageBuffer);
       
  1744 	}
       
  1745