imaging/imagingfws/src/ThreadRelay.cpp
changeset 0 5752a19fdefe
equal deleted inserted replaced
-1:000000000000 0:5752a19fdefe
       
     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 <caf/caf.h>
       
    17 using namespace ContentAccess;
       
    18 #include "ThreadRelay.h"
       
    19 #include "icl/ImageConstruct.h"
       
    20 #include "icl/ImagePlugin.h"
       
    21 #include "ImageClientMain.h"
       
    22 #include "icl/ICL_UIDS.hrh"
       
    23 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    24 #include <icl/icl_uids_const.hrh>
       
    25 #include <icl/icl_uids_def.hrh>
       
    26 #endif
       
    27 #include "fwextconstants.h"
       
    28 #include "iclextproxystubutil.h"
       
    29 
       
    30 //
       
    31 // CBufferCopyListener
       
    32 //
       
    33 /**
       
    34  * Factory function for this class.
       
    35  *
       
    36  * @param	"const RThread* aSubThread"
       
    37  *			Thread to signal when buffer copy has been completed
       
    38  */
       
    39 CBufferCopyListener* CBufferCopyListener::NewL(const RThread* aSubThread)
       
    40 	{
       
    41 	CBufferCopyListener* self;
       
    42 	self = new (ELeave) CBufferCopyListener(aSubThread);
       
    43 	return self;
       
    44 	}
       
    45 
       
    46 /**
       
    47  * Constructor for this class.
       
    48  *
       
    49  * @param	"const RThread* aSubThread"
       
    50  *			Thread to signal when buffer copy has been completed
       
    51  */
       
    52 CBufferCopyListener::CBufferCopyListener(const RThread* aSubThread) :
       
    53 	CActive(EPriorityIdle)
       
    54 	{
       
    55 	iSubThread = aSubThread;
       
    56 	CActiveScheduler::Add(this);
       
    57 	}
       
    58 /**
       
    59  * Activate the buffer copy listener to listen for copy requests.
       
    60  *
       
    61  */
       
    62 void CBufferCopyListener::Prime()
       
    63 	{
       
    64 	ASSERT(IsActive() == EFalse);
       
    65 	iStatus = KRequestPending;
       
    66 	SetActive();
       
    67 	}
       
    68 
       
    69 /**
       
    70  * Initilise the listener for a buffer copy.
       
    71  *
       
    72  * @param	"TRequestStatus& aCallerStatus"
       
    73  *			Request to signal when copy has been comlpeted. Signalled in thread
       
    74  *			passed to the listener at construction.
       
    75  * @param	"TDes8& aBuffer"
       
    76  *			Destination buffer for copy.
       
    77  * @param	"const TDesC8& aSource"
       
    78  *			Source descriptor for copy.
       
    79  * @param	"TInt aPosition"
       
    80  *			Position in buffer to start copy.
       
    81  * @param	"TInt aSize"
       
    82  *			Number of elements to copy.
       
    83  */
       
    84 void CBufferCopyListener::CopyBufferToDescriptor(TRequestStatus& aCallerStatus, TDes8& aBuffer, const TDesC8& aSource, TInt aPosition, TInt aSize)
       
    85 	{
       
    86 	Prime();
       
    87 	iCallerStatus = &aCallerStatus;
       
    88 	iBuffer = &aBuffer;
       
    89 	iSource = &aSource;
       
    90 	iPosition = aPosition;
       
    91 	iSize = aSize;
       
    92 	}
       
    93 
       
    94 /**
       
    95  *
       
    96  * Perform the buffer copy.
       
    97  *
       
    98  */
       
    99 void CBufferCopyListener::RunL()
       
   100 	{
       
   101 	ASSERT(iStatus==KErrNone);
       
   102 	DoBufferCopy();
       
   103 	}
       
   104 
       
   105 /**
       
   106  *
       
   107  * Perform the buffer copy and signal the requesting thread when the copy has completed.
       
   108  *
       
   109  */
       
   110 void CBufferCopyListener::DoBufferCopy()
       
   111 	{
       
   112 	ASSERT(iStatus == KErrNone);
       
   113 	ASSERT(iSource != NULL);
       
   114 	ASSERT(iBuffer != NULL);
       
   115 	ASSERT(iSubThread != NULL);
       
   116 
       
   117 	*iBuffer = iSource->Mid(iPosition, iSize);
       
   118 
       
   119 	TRequestStatus *status = iCallerStatus;
       
   120 	iSubThread->RequestComplete(status,KErrNone);
       
   121 	}
       
   122 
       
   123 /**
       
   124  *
       
   125  * Cancel an outstanding copy request.
       
   126  *
       
   127  */
       
   128 void CBufferCopyListener::DoCancel()
       
   129 	{
       
   130 	}
       
   131 /**
       
   132  *
       
   133  * Destructor for this class.
       
   134  *
       
   135  */
       
   136 CBufferCopyListener::~CBufferCopyListener()
       
   137 	{
       
   138 	}
       
   139 
       
   140 //
       
   141 // CThreadDecoderRelay
       
   142 //
       
   143 /**
       
   144  * Actual factory function for this class
       
   145  *
       
   146  * @param	"CImageDecodeConstruct* aConstruct"
       
   147  *			A object to construct a decoder.
       
   148  * @return	"CThreadDecoderRelay*"
       
   149  *			A pointer to the constructed object
       
   150  */
       
   151 CThreadDecoderRelay* CThreadDecoderRelay::NewL(CImageDecodeConstruct* aConstruct)
       
   152 	{
       
   153 	CThreadDecoderRelay* self;
       
   154 	self = new (ELeave) CThreadDecoderRelay(aConstruct);
       
   155 	CleanupStack::PushL(self);
       
   156 	self->ConstructL();
       
   157 	CleanupStack::Pop(self);
       
   158 	return self;
       
   159 	}
       
   160 
       
   161 /**
       
   162  * Second phase constructor for this class.
       
   163  * Create a buffer copy listener and send it and a factory function
       
   164  * to create a decoder as parameters to the thread.
       
   165  *
       
   166  */
       
   167 void CThreadDecoderRelay::ConstructL()
       
   168 	{
       
   169 	//Start a buffer copy listener and prime it to listen for requests
       
   170 	iBufferCopyListener = CBufferCopyListener::NewL(SubThread());
       
   171 
       
   172 	//Package the parameters to create a CSubThreadDecoderRelay
       
   173 	TThreadDecoderRelayParam params;
       
   174 
       
   175 	//Send the status of the buffer copy AO to the sub thread
       
   176 	params.iBufferCopyListener = iBufferCopyListener;
       
   177 
       
   178 	//Add the CImageDecodeConstruct object that will create the decoder
       
   179 	params.iConstruct = iConstruct;
       
   180 
       
   181 	CThreadRelay::ConstructL(CSubThreadDecoderRelay::NewL, &params);
       
   182 
       
   183 	iSubThreadDecoderRelay = STATIC_CAST(CSubThreadDecoderRelay*, SubThreadRelay());
       
   184 	iBody = iSubThreadDecoderRelay->iBody;
       
   185 	iExtensionCache = CImageConvExtensionCache::NewL();
       
   186 	}
       
   187 
       
   188 /**
       
   189  * Constructor for this class.
       
   190  *
       
   191  */
       
   192 CThreadDecoderRelay::CThreadDecoderRelay(CImageDecodeConstruct* aConstruct) :
       
   193 	iConstruct(aConstruct)
       
   194 	{
       
   195 	}
       
   196 
       
   197 /**
       
   198  * Destructor for this class.
       
   199  * If a buffer copy listener was created cancel and delete it.
       
   200  * If ownership for the construct object was passed, delete it.
       
   201  *
       
   202  */
       
   203 CThreadDecoderRelay::~CThreadDecoderRelay()
       
   204 	{
       
   205 	delete iExtensionCache;
       
   206 	if(iBufferCopyListener)
       
   207 		{
       
   208 		iBufferCopyListener->Cancel();
       
   209 		delete iBufferCopyListener;
       
   210 		}
       
   211 
       
   212 	if(iOwnConstruct)
       
   213 		delete iConstruct;
       
   214 	}
       
   215 
       
   216 /**
       
   217  * Run a function that should not leave in the codec thread.
       
   218  * Let the thread know a function call will follow (to allow the thread to do 
       
   219  * local buffer copies) and request the function to run. If the function does leave
       
   220  * panic the current thread.
       
   221  * 
       
   222  * @param	"TInt aFunctionCode"
       
   223  *			The function to run in the codec thread.
       
   224  * @param	"TAny* aParameters"
       
   225  *			The parameters to the function.
       
   226  * @panic	"KInvalidFunctionLeave"
       
   227  *			If the function in the codec thread leaves.
       
   228  */
       
   229 void CThreadDecoderRelay::RunFunction(TInt aFunctionCode, TAny* aParameters)
       
   230 	{
       
   231 	ASSERT(iSubThreadDecoderRelay!=NULL);
       
   232 	iSubThreadDecoderRelay->SetFunctionInProgress();
       
   233 	TInt error = CThreadRelay::RunFunction(aFunctionCode, aParameters);
       
   234 	iSubThreadDecoderRelay->ResetFunctionInProgress();
       
   235 
       
   236 	if(error!=KErrNone)
       
   237 		Panic(EInvalidFunctionLeave);
       
   238 	}
       
   239 
       
   240 /**
       
   241  * Run a function that can leave in the codec thread.
       
   242  * Let the thread know a function call will follow (to allow the thread to do 
       
   243  * local buffer copies) and request the function ro run. If the function do leave
       
   244  * leave in this thread with the same error code.
       
   245  * 
       
   246  * @param	"TInt aFunctionCode"
       
   247  *			The function to run in the codec thread.
       
   248  * @param	"TAny* aParameters"
       
   249  *			The parameters to the function.
       
   250  */
       
   251 void CThreadDecoderRelay::RunFunctionL(TInt aFunctionCode, TAny* aParameters)
       
   252 	{
       
   253 	ASSERT(iSubThreadDecoderRelay!=NULL);
       
   254 	iSubThreadDecoderRelay->SetFunctionInProgress();
       
   255 	TInt error = CThreadRelay::RunFunction(aFunctionCode, aParameters);
       
   256 	iSubThreadDecoderRelay->ResetFunctionInProgress();
       
   257 
       
   258 	if(error!=KErrNone)
       
   259 		User::Leave(error);
       
   260 	}
       
   261 /**
       
   262  * Cancel the threaded decoding in progress.
       
   263  * Use a straight call to request plugins that do not use AO functionallity
       
   264  * to abort and then request a normal decoding cancel in the codec thread.
       
   265  */
       
   266 void CThreadDecoderRelay::Cancel()
       
   267 	{
       
   268 	//Use straight call to inform decoder to cancel
       
   269 	iSubThreadDecoderRelay->AbortDecode();
       
   270 	//Up the decoding thread's priority for increased Cancel() response
       
   271 	SetPriority(RThread().Priority());
       
   272 	//Cancel need no parameters
       
   273 	RunFunction(CSubThreadDecoderRelay::EFunctionCancel, NULL);
       
   274 	//Restore the priority
       
   275 	SetPriority(KSubThreadPriority);
       
   276 	}
       
   277 
       
   278 void CThreadDecoderRelay::SetFileL(RFs& /*aFs*/, const TDesC& aSourceFilename, const CImageDecoder::TOptions aOptions)
       
   279 	{
       
   280 	TDecodeSetFileParams params;
       
   281 	params.iSourceFilename = &aSourceFilename;
       
   282 	params.iOptions = aOptions;
       
   283 
       
   284 	RunFunctionL(CSubThreadDecoderRelay::EFunctionSetFile, &params);
       
   285 	}
       
   286 	
       
   287 void CThreadDecoderRelay::SetFileL(RFile& aFile, const CImageDecoder::TOptions aOptions)
       
   288 	{
       
   289 	TDecodeSetFileHandleParams params;
       
   290 	params.iFile = &aFile;
       
   291 	params.iOptions = aOptions;
       
   292 
       
   293 	RunFunctionL(CSubThreadDecoderRelay::EFunctionSetFileHandle, &params);
       
   294 	}
       
   295 
       
   296 
       
   297 void CThreadDecoderRelay::SetDataL(RFs& /*aFs*/, const TDesC8& aSourceData, const CImageDecoder::TOptions aOptions)
       
   298 	{
       
   299 	TDecodeSetDataParams params;
       
   300 	params.iSourceData = &aSourceData;
       
   301 	params.iOptions = aOptions;
       
   302 
       
   303 	RunFunctionL(CSubThreadDecoderRelay::EFunctionSetData, &params);
       
   304 	}
       
   305 
       
   306 CImageDecoderPlugin* CThreadDecoderRelay::Plugin() const
       
   307 	{
       
   308 	return iBody->Plugin();
       
   309 	}
       
   310 
       
   311 void CThreadDecoderRelay::HandleNewlyOpenedImageL()
       
   312 	{
       
   313 	RunFunctionL(CSubThreadDecoderRelay::EFunctionHandleNewImage, NULL);
       
   314 	}
       
   315 
       
   316 void CThreadDecoderRelay::Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, TInt aFrameNumber)
       
   317 	{
       
   318 	*aRequestStatus = KRequestPending;
       
   319 	TDecodeConvertParams params;	
       
   320 	params.iRequestStatus = aRequestStatus;
       
   321 	params.iDestinationHandle = aDestination.Handle();
       
   322 	params.iFrameNumber = aFrameNumber;
       
   323 
       
   324 	RunFunction(CSubThreadDecoderRelay::EFunctionConvert, &params);
       
   325 	}
       
   326 
       
   327 void CThreadDecoderRelay::Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, CFbsBitmap& aDestinationMask, TInt aFrameNumber)
       
   328 	{
       
   329 	*aRequestStatus = KRequestPending;
       
   330 	TDecodeConvertParams params;
       
   331 	params.iRequestStatus = aRequestStatus;
       
   332 	params.iDestinationHandle = aDestination.Handle();
       
   333 	params.iDestinationMaskHandle = aDestinationMask.Handle();
       
   334 	params.iFrameNumber = aFrameNumber;
       
   335 
       
   336 	RunFunction(CSubThreadDecoderRelay::EFunctionConvertMask, &params);
       
   337 	}
       
   338 
       
   339 void CThreadDecoderRelay::ContinueConvert(TRequestStatus* aRequestStatus)
       
   340 	{
       
   341 	*aRequestStatus = KRequestPending;
       
   342 	TDecodeConvertParams params;
       
   343 	params.iRequestStatus = aRequestStatus;
       
   344 
       
   345 	RunFunction(CSubThreadDecoderRelay::EFunctionContinueConvert, &params);
       
   346 	}
       
   347 
       
   348 void CThreadDecoderRelay::ContinueProcessingHeaderL()
       
   349 	{
       
   350 	RunFunctionL(CSubThreadDecoderRelay::EFunctionContinueHeader, NULL);
       
   351 	}
       
   352 
       
   353 void CThreadDecoderRelay::SetImageTypeL(TInt aImageType)
       
   354 	{
       
   355 	iBody->SetImageTypeL(aImageType);
       
   356 	}
       
   357 
       
   358 const TFrameInfo& CThreadDecoderRelay::FrameInfo(TInt aFrameNumber) const
       
   359 	{
       
   360 	iSubThreadDecoderRelay->Lock();
       
   361 	const TFrameInfo& frameInfo = iBody->FrameInfo(aFrameNumber);
       
   362 	iSubThreadDecoderRelay->Unlock();
       
   363 	return frameInfo;
       
   364 	}
       
   365 
       
   366 const CFrameImageData& CThreadDecoderRelay::FrameData(TInt aFrameNumber) const
       
   367 	{
       
   368 	iSubThreadDecoderRelay->Lock();
       
   369 	const CFrameImageData& frameData = iBody->FrameData(aFrameNumber);
       
   370 	iSubThreadDecoderRelay->Unlock();
       
   371 	return frameData;
       
   372 	}
       
   373 
       
   374 TInt CThreadDecoderRelay::NumberOfImageComments() const
       
   375 	{
       
   376 	iSubThreadDecoderRelay->Lock();
       
   377 	TInt noOfImageComments = iBody->Plugin()->NumberOfImageComments();
       
   378 	iSubThreadDecoderRelay->Unlock();
       
   379 	return noOfImageComments;
       
   380 	}
       
   381 
       
   382 HBufC* CThreadDecoderRelay::ImageCommentL(TInt aCommentNumber) const
       
   383 	{
       
   384 	iSubThreadDecoderRelay->Lock();
       
   385 	HBufC* imageComment = iBody->Plugin()->ImageCommentL(aCommentNumber);
       
   386 	iSubThreadDecoderRelay->Unlock();
       
   387 	return imageComment;
       
   388 	}
       
   389 
       
   390 TInt CThreadDecoderRelay::NumberOfFrameComments(TInt aFrameNumber) const
       
   391 	{
       
   392 	iSubThreadDecoderRelay->Lock();
       
   393 	TInt noOfFrameComments = iBody->Plugin()->NumberOfFrameComments(aFrameNumber);
       
   394 	iSubThreadDecoderRelay->Unlock();
       
   395 	return noOfFrameComments;
       
   396 	}
       
   397 
       
   398 HBufC* CThreadDecoderRelay::FrameCommentL(TInt aFrameNumber, TInt aCommentNumber) const
       
   399 	{
       
   400 	iSubThreadDecoderRelay->Lock();
       
   401 	HBufC* frameComment =  iBody->Plugin()->FrameCommentL(aFrameNumber, aCommentNumber);
       
   402 	iSubThreadDecoderRelay->Unlock();
       
   403 	return frameComment;
       
   404 	}
       
   405 
       
   406 CFrameInfoStrings* CThreadDecoderRelay::FrameInfoStringsLC(TInt aFrameNumber)
       
   407 	{
       
   408 	return iBody->FrameInfoStringsLC(aFrameNumber);
       
   409 	}
       
   410 
       
   411 TUid CThreadDecoderRelay::ImplementationUid() const
       
   412 	{
       
   413 	return iBody->ImplementationUid();
       
   414 	}
       
   415 
       
   416 TInt CThreadDecoderRelay::FrameCount() const
       
   417 	{
       
   418 	return iSubThreadDecoderRelay->FrameCount();
       
   419 	}
       
   420 
       
   421 TBool CThreadDecoderRelay::IsImageHeaderProcessingComplete() const
       
   422 	{
       
   423 	return iBody->IsImageHeaderProcessingComplete();
       
   424 	}
       
   425 
       
   426 void CThreadDecoderRelay::CustomSyncL(TInt aParam)
       
   427 	{
       
   428 	TCustomSyncParams params;
       
   429 	params.iParam = aParam;
       
   430 
       
   431 	RunFunctionL(CSubThreadDecoderRelay::EFunctionCustomSync, &params);
       
   432 	}
       
   433 
       
   434 void CThreadDecoderRelay::CustomAsync(TRequestStatus* aRequestStatus, TInt aParam)
       
   435 	{
       
   436 	*aRequestStatus = KRequestPending;
       
   437 	TCustomSyncParams params;
       
   438 	params.iRequestStatus = aRequestStatus;
       
   439 	params.iParam = aParam;
       
   440 
       
   441 	RunFunction(CSubThreadDecoderRelay::EFunctionCustomAsync, &params);
       
   442 	}
       
   443 
       
   444 void CThreadDecoderRelay::TransferConstructOwnership()
       
   445 	{
       
   446 	iOwnConstruct = ETrue;
       
   447 	}
       
   448 
       
   449 void CThreadDecoderRelay::SetIntent(TIntent aIntent)
       
   450 	{
       
   451 	iBody->SetIntent(aIntent);
       
   452 	}
       
   453 
       
   454 void CThreadDecoderRelay::SetUniqueIdL(const TDesC& aUniqueId)
       
   455 	{
       
   456 	iBody->SetUniqueIdL(aUniqueId);
       
   457 	}
       
   458 
       
   459 TInt CThreadDecoderRelay::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
       
   460 	{
       
   461 	return iBody->SetAgentProperty(aProperty, aValue);
       
   462 	}
       
   463 
       
   464 TInt CThreadDecoderRelay::ReductionFactor(const TSize& aOriginalSize, const TSize& aReducedSize) const
       
   465 	{
       
   466 	return iBody->ReductionFactor(aOriginalSize, aReducedSize);
       
   467 	}
       
   468 	
       
   469 TInt CThreadDecoderRelay::ReducedSize(const TSize& aOriginalSize, TInt aReductionFactor, TSize& aReducedSize) const
       
   470 	{
       
   471 	return iBody->ReducedSize(aOriginalSize, aReductionFactor, aReducedSize);
       
   472 	}
       
   473 	
       
   474 TInt CThreadDecoderRelay::SetDecoderThreadPriority(TThreadPriority aPriority)
       
   475 	{
       
   476 	SetPriority(aPriority);
       
   477 	return KErrNone;
       
   478 	}
       
   479 	
       
   480 void CThreadDecoderRelay::GetExtensionL(TUid aExtUid, MImageConvExtension*& aExtPtr)
       
   481 	{
       
   482 	__ASSERT_ALWAYS(aExtPtr == NULL, Panic(ENonNullImageConvExtension));
       
   483 	
       
   484 	CImageConvProxyBase* proxy = ProxyStubUtility::GetNewProxyL(aExtUid, this);
       
   485 	CleanupStack::PushL(proxy);
       
   486 	
       
   487 	TGetExtensionParams params;
       
   488 	params.iUid = aExtUid;
       
   489 	params.iExtension = &aExtPtr;
       
   490 	RunFunctionL(CSubThreadDecoderRelay::EFunctionGetExtension, &params);
       
   491 	proxy->SetupExtension(aExtPtr);
       
   492 	iExtensionCache->SetProxyL(proxy);
       
   493 	CleanupStack::Pop(proxy);
       
   494 	//aExtPtr contains pointer to the proxy
       
   495 	}
       
   496 
       
   497 void CThreadDecoderRelay::SetClippingRectL(const TRect* aClipRect)
       
   498 	{
       
   499 	iBody->SetClippingRectL(aClipRect);
       
   500 	}
       
   501 
       
   502 TInt CThreadDecoderRelay::GetDestinationSize(TSize& aSize, TInt aFrameNumber)
       
   503 	{
       
   504 	return iBody->Plugin()->GetDestinationSize(aSize, aFrameNumber);
       
   505 	}
       
   506 
       
   507 CImageConvExtensionCache& CThreadDecoderRelay::ExtensionCache()
       
   508 	{
       
   509 	return *iExtensionCache;
       
   510 	}
       
   511 	
       
   512 void CThreadDecoderRelay::ExecuteCommand(TExecuteCommandParamsBase& aExecuteCommandBase)
       
   513 	{
       
   514 	RunFunction(CSubThreadDecoderRelay::EFunctionExecuteCommandL, &aExecuteCommandBase);
       
   515 	}	
       
   516 
       
   517 void CThreadDecoderRelay::ExecuteCommandL(TExecuteCommandParamsBase& aExecuteCommandBase)
       
   518 	{
       
   519 	RunFunctionL(CSubThreadDecoderRelay::EFunctionExecuteCommandL, &aExecuteCommandBase);
       
   520 	}
       
   521 
       
   522 void CThreadDecoderRelay::ExecuteAsyncCommand(TExecuteCommandParamsBase& aExecuteCommandBase)
       
   523 	{
       
   524 	RunFunction(CSubThreadDecoderRelay::EFunctionExecuteAsyncCommand, &aExecuteCommandBase);
       
   525 	}
       
   526 	
       
   527 //
       
   528 // CThreadEncoderRelay
       
   529 //
       
   530 /**
       
   531  * Actual factory function for this class
       
   532  *
       
   533  * @param	"CImageEncodeConstruct* aConstruct"
       
   534  *			A object to construct an encoder.
       
   535  * @return	"CThreadEncoderRelay*"
       
   536  *			A pointer to the constructed object
       
   537  */
       
   538 CThreadEncoderRelay* CThreadEncoderRelay::NewL(CImageEncodeConstruct* aConstruct)
       
   539 	{
       
   540 	CThreadEncoderRelay* self;
       
   541 	self = new (ELeave) CThreadEncoderRelay(aConstruct);
       
   542 	CleanupStack::PushL(self);
       
   543 	self->ConstructL();
       
   544 	CleanupStack::Pop(self);
       
   545 	return self;
       
   546 	}
       
   547 
       
   548 /**
       
   549  * Constructor for this class.
       
   550  *
       
   551  */
       
   552 CThreadEncoderRelay::CThreadEncoderRelay(CImageEncodeConstruct* aConstruct) :
       
   553 	iConstruct(aConstruct)
       
   554 	{
       
   555 	}
       
   556 
       
   557 /**
       
   558  * Second phase constructor for this class.
       
   559  * Send a factory function to create an encoder is as a parameter to the thread.
       
   560  *
       
   561  */
       
   562 void CThreadEncoderRelay::ConstructL()
       
   563 	{
       
   564 	//Package the parameters to create a CSubThreadDecoderRelay
       
   565 	TThreadEncoderRelayParam params;
       
   566 
       
   567 	//Add the CImageEncodeConstruct object that will create the encoder
       
   568 	params.iConstruct = iConstruct;
       
   569 
       
   570 	CThreadRelay::ConstructL(CSubThreadEncoderRelay::NewL, &params);
       
   571 
       
   572 	iSubThreadEncoderRelay = STATIC_CAST(CSubThreadEncoderRelay*, SubThreadRelay());
       
   573 	iBody = iSubThreadEncoderRelay->iBody;
       
   574 	iExtensionCache = CImageConvExtensionCache::NewL();
       
   575 	}
       
   576 
       
   577 void CThreadEncoderRelay::Cancel()
       
   578 	{
       
   579 	//Use straight call to inform encoder to cancel
       
   580 	iSubThreadEncoderRelay->AbortEncode();
       
   581 	//Up the encoding thread's priority for increased Cancel() response
       
   582 	SetPriority(RThread().Priority());
       
   583 	//Cancel needs no parameters
       
   584 	RunFunction(CSubThreadEncoderRelay::EFunctionCancel, NULL);
       
   585 	//Restore the priority
       
   586 	SetPriority(KSubThreadPriority);
       
   587 	}
       
   588 
       
   589 void CThreadEncoderRelay::SetFileL(RFs& /*aFs*/, const TDesC& aDestinationFilename, const CImageEncoder::TOptions aOptions)
       
   590 	{
       
   591 	TEncodeSetFileParams params;
       
   592 	params.iDestinationFilename = &aDestinationFilename;
       
   593 	params.iOptions = aOptions;
       
   594 
       
   595 	RunFunctionL(CSubThreadEncoderRelay::EFunctionSetFile, &params);
       
   596 	}
       
   597 
       
   598 void CThreadEncoderRelay::SetFileL(RFile& aFile, const CImageEncoder::TOptions aOptions)
       
   599 	{
       
   600 	TEncodeSetFileHandleParams params;
       
   601 	params.iFile = &aFile;
       
   602 	params.iOptions = aOptions;
       
   603 	RunFunctionL(CSubThreadEncoderRelay::EFunctionSetFileHandle, &params);
       
   604 	}
       
   605 
       
   606 void CThreadEncoderRelay::SetDataL(HBufC8*& aDestinationData, const CImageEncoder::TOptions aOptions)
       
   607 	{
       
   608 	TEncodeSetDataParams params;
       
   609 	params.iDestinationData = &aDestinationData;
       
   610 	params.iOptions = aOptions;
       
   611 
       
   612 	RunFunctionL(CSubThreadEncoderRelay::EFunctionSetData, &params);
       
   613 	}
       
   614 
       
   615 CImageEncoderPlugin* CThreadEncoderRelay::Plugin() const
       
   616 	{
       
   617 	return iBody->Plugin();
       
   618 	}
       
   619 
       
   620 void CThreadEncoderRelay::Convert(TRequestStatus* aRequestStatus, const CFbsBitmap& aSource, const CFrameImageData* aFrameImageData)
       
   621 	{
       
   622 	*aRequestStatus = KRequestPending;
       
   623 	TEncodeConvertParams params;
       
   624 	params.iRequestStatus = aRequestStatus;
       
   625 	params.iSourceHandle = aSource.Handle();
       
   626 	params.iFrameImageData = aFrameImageData;
       
   627 
       
   628 	RunFunction(CSubThreadEncoderRelay::EFunctionConvert, &params);
       
   629 	}
       
   630 
       
   631 TUid CThreadEncoderRelay::ImplementationUid() const
       
   632 	{
       
   633 	return iBody->ImplementationUid();
       
   634 	}
       
   635 
       
   636 void CThreadEncoderRelay::CustomSyncL(TInt aParam)
       
   637 	{
       
   638 	TCustomSyncParams params;
       
   639 	params.iParam = aParam;
       
   640 
       
   641 	RunFunctionL(CSubThreadEncoderRelay::EFunctionCustomSync, &params);
       
   642 	}
       
   643 
       
   644 void CThreadEncoderRelay::CustomAsync(TRequestStatus* aRequestStatus, TInt aParam)
       
   645 	{
       
   646 	*aRequestStatus = KRequestPending;
       
   647 	TCustomSyncParams params;
       
   648 	params.iRequestStatus = aRequestStatus;
       
   649 	params.iParam = aParam;
       
   650 
       
   651 	RunFunction(CSubThreadEncoderRelay::EFunctionCustomAsync, &params);
       
   652 	}
       
   653 
       
   654 void CThreadEncoderRelay::TransferConstructOwnership()
       
   655 	{
       
   656 	iOwnConstruct = ETrue;
       
   657 	}
       
   658 
       
   659 void CThreadEncoderRelay::RunFunction(TInt aFunctionCode, TAny* aParameters)
       
   660 	{
       
   661 	ASSERT(iSubThreadEncoderRelay!=NULL);
       
   662 	TInt error = CThreadRelay::RunFunction(aFunctionCode, aParameters);
       
   663 	if(error!=KErrNone)
       
   664 		Panic(EInvalidFunctionLeave);
       
   665 	}
       
   666 
       
   667 void CThreadEncoderRelay::RunFunctionL(TInt aFunctionCode, TAny* aParameters)
       
   668 	{
       
   669 	ASSERT(iSubThreadEncoderRelay!=NULL);
       
   670 	TInt error = CThreadRelay::RunFunction(aFunctionCode, aParameters);
       
   671 	if(error!=KErrNone)
       
   672 		User::Leave(error);
       
   673 	}
       
   674 
       
   675 CThreadEncoderRelay::~CThreadEncoderRelay()
       
   676 	{
       
   677 	delete iExtensionCache;
       
   678 	if(iOwnConstruct)
       
   679 		delete iConstruct;
       
   680 	}
       
   681 void CThreadEncoderRelay::SetThumbnail(TBool aDoGenerateThumbnail)
       
   682 	{
       
   683 	iBody->SetThumbnail(aDoGenerateThumbnail);
       
   684 	}
       
   685 
       
   686 TInt CThreadEncoderRelay::SetEncoderThreadPriority(TThreadPriority aPriority)
       
   687 	{
       
   688 	SetPriority( aPriority );
       
   689 	return KErrNone;
       
   690 	}
       
   691 
       
   692 void CThreadEncoderRelay::GetExtensionL(TUid aExtUid, MImageConvExtension*& aExtPtr)
       
   693 	{
       
   694 	__ASSERT_ALWAYS(aExtPtr == NULL, Panic(ENonNullImageConvExtension));
       
   695 	
       
   696 	CImageConvProxyBase* proxy = ProxyStubUtility::GetNewProxyL(aExtUid, this);
       
   697 	CleanupStack::PushL(proxy);
       
   698 	
       
   699 	TGetExtensionParams params;
       
   700 	params.iUid = aExtUid;
       
   701 	params.iExtension = &aExtPtr;
       
   702 	RunFunctionL(CSubThreadEncoderRelay::EFunctionGetExtension, &params);
       
   703 	proxy->SetupExtension(aExtPtr);
       
   704 	iExtensionCache->SetProxyL(proxy);
       
   705 	CleanupStack::Pop(proxy);
       
   706 	//aExtPtr contains pointer to the proxy
       
   707 	}
       
   708 
       
   709 CImageConvExtensionCache& CThreadEncoderRelay::ExtensionCache()
       
   710 	{
       
   711 	return *iExtensionCache;
       
   712 	}
       
   713 
       
   714 void CThreadEncoderRelay::ExecuteCommand(TExecuteCommandParamsBase& aExecuteCommandBase)
       
   715 	{
       
   716 	RunFunction(CSubThreadEncoderRelay::EFunctionExecuteCommandL, &aExecuteCommandBase);
       
   717 	}	
       
   718 
       
   719 void CThreadEncoderRelay::ExecuteCommandL(TExecuteCommandParamsBase& aExecuteCommandBase)
       
   720 	{
       
   721 	RunFunctionL(CSubThreadEncoderRelay::EFunctionExecuteCommandL, &aExecuteCommandBase);
       
   722 	}
       
   723 
       
   724 void CThreadEncoderRelay::ExecuteAsyncCommand(TExecuteCommandParamsBase& aExecuteCommandBase)
       
   725 	{
       
   726 	RunFunction(CSubThreadEncoderRelay::EFunctionExecuteAsyncCommand, &aExecuteCommandBase);
       
   727 	}
       
   728 
       
   729 //
       
   730 // CSubThreadDecoderRelay
       
   731 //
       
   732 /**
       
   733  * Actual factory function for this class
       
   734  * Decode the parameters and call the constructors.
       
   735  *
       
   736  */
       
   737 CSubThreadRelay* CSubThreadDecoderRelay::NewL(TThreadId aMainThreadId, TAny* aDecoderParam)
       
   738 	{
       
   739 	CSubThreadDecoderRelay* self;
       
   740 	TThreadDecoderRelayParam* decoderParam;
       
   741 
       
   742 	decoderParam = STATIC_CAST(TThreadDecoderRelayParam*, aDecoderParam);
       
   743 
       
   744 	self = new (ELeave) CSubThreadDecoderRelay(decoderParam->iBufferCopyListener);
       
   745 	CleanupStack::PushL(self);
       
   746 	self->ConstructL(aMainThreadId, decoderParam->iConstruct);
       
   747 
       
   748 	CleanupStack::Pop(self);
       
   749 	return self;
       
   750 	}
       
   751 
       
   752 /**
       
   753  * Constructor for this class.
       
   754  *
       
   755  */
       
   756 CSubThreadDecoderRelay::CSubThreadDecoderRelay(CBufferCopyListener* aBufferCopyListener) :
       
   757 	iBufferCopyListener(aBufferCopyListener)
       
   758 	{
       
   759 	}
       
   760 
       
   761 /**
       
   762  * Second phase constructor for this class.
       
   763  * Create a local file server session (shareable between threads) and mutexes
       
   764  * to lock the frame tables and buffer copies.
       
   765  *
       
   766  * @param	"TThreadId aMainThreadId"
       
   767  *			The id of the main thread. Open a local connection to the main thread.
       
   768  * @param	"CImageDecodeConstruct* aConstruct"
       
   769  *			A construct object to create the decoder.
       
   770  */
       
   771 void CSubThreadDecoderRelay::ConstructL(TThreadId aMainThreadId, CImageDecodeConstruct* aConstruct)
       
   772 	{
       
   773 	CSubThreadRelay::ConstructL(aMainThreadId);
       
   774 
       
   775 	//Open a file server session
       
   776 	User::LeaveIfError(iFileSession.Connect());
       
   777 	//Make the session shareable for all threads
       
   778 #ifdef __IPC_V2_PRESENT__
       
   779 	User::LeaveIfError(iFileSession.ShareAuto());
       
   780 #else
       
   781 	User::LeaveIfError(iFileSession.Share(RSessionBase::EAutoAttach));
       
   782 #endif
       
   783 
       
   784 	//Create a mutex for the frame tables
       
   785 	User::LeaveIfError(iFrameTableMutex.CreateLocal());
       
   786 	//Create a mutex for buffer copies in main thread
       
   787 	User::LeaveIfError(iBufferCopyMutex.CreateLocal());
       
   788 
       
   789 	iBody = CImageDecoderPriv::NewL(aConstruct, this);
       
   790 	iBody->CreatePluginL();
       
   791 	}
       
   792 
       
   793 /**
       
   794  * Destructor for this class.
       
   795  *
       
   796  */
       
   797 CSubThreadDecoderRelay::~CSubThreadDecoderRelay()
       
   798 	{
       
   799 	Cancel();
       
   800 	iStubs.ResetAndDestroy();
       
   801 	if(iBody)
       
   802 		{
       
   803 		CancelBody();
       
   804 		delete iBody;
       
   805 		}
       
   806 	iFrameTableMutex.Close();
       
   807 	iBufferCopyMutex.Close();
       
   808 	delete iDestination;
       
   809 	delete iDestinationMask;
       
   810 	iFileSession.Close();
       
   811 	}
       
   812 
       
   813 /**
       
   814  * Wait on buffer copy mutex for buffer copy in main thread
       
   815  * to finish and change the state to a function call in progress.
       
   816  * The codec subthread will use local buffer copies until ResetFunctionInProgress()
       
   817  * is called.
       
   818  *
       
   819  */
       
   820 void CSubThreadDecoderRelay::SetFunctionInProgress()
       
   821 	{
       
   822 	//Note: assumes that this executes in the main thread.
       
   823 	ASSERT(RThread().Id() == iMainThread.Id());
       
   824 
       
   825 	//this will block until codec subthread has primed the buffer copy AO
       
   826 	iBufferCopyMutex.Wait();
       
   827 	if (iBufferCopyListener->IsActive())
       
   828 		{
       
   829 		iBufferCopyListener->Cancel();
       
   830 
       
   831 		//Do copy now
       
   832 		*iBuffer = iSource->Mid(iPosition, iSize);
       
   833 
       
   834 		//Signal codec subthread that the copy is complete
       
   835 		TRequestStatus* status = iCallerStatus;
       
   836 		iSubThread->RequestComplete(status, KErrNone);
       
   837 		}
       
   838 	iFunctionCallInProgress = ETrue;
       
   839 	iBufferCopyMutex.Signal();
       
   840 	}
       
   841 
       
   842 /**
       
   843  * Wait on buffer copy mutex while the codec thread check in which thread to
       
   844  * do the buffer copy and cancel the function call state.
       
   845  * The thread will do buffer copies in the main thread, using the buffer copy
       
   846  * listener after this call.
       
   847  *
       
   848  */
       
   849 void CSubThreadDecoderRelay::ResetFunctionInProgress()
       
   850 	{
       
   851 	iBufferCopyMutex.Wait();
       
   852 	iFunctionCallInProgress = EFalse;
       
   853 	iBufferCopyMutex.Signal();
       
   854 	}
       
   855 
       
   856 /**
       
   857  * Run a function in the decoder thread.
       
   858  *
       
   859  * @param	"TInt aFunctionCode"
       
   860  *			The function to execute.
       
   861  * @param	"TAny* aParameters"
       
   862  *			Parameters to the function.
       
   863  * @leave	"KErrArgument"
       
   864  *			Invalid function requested.
       
   865  */
       
   866 void CSubThreadDecoderRelay::RunFunctionL(TInt aFunctionCode, TAny* aParameters)
       
   867 	{
       
   868 
       
   869 	union
       
   870 	{
       
   871 	TAny* iFunctionParams;
       
   872 	TDecodeSetFileParams* iSetFile;
       
   873 	TDecodeSetFileHandleParams* iSetFileHandle;
       
   874 	TDecodeSetDataParams* iSetData;
       
   875 	TDecodeConvertParams* iConvert;
       
   876 	TCustomSyncParams* iCustomSync;
       
   877 	TGetExtensionParams* iGetExtension;
       
   878 	TExecuteCommandParamsBase* iExecuteCommandBase;
       
   879 	TExecuteCommandParamsAsyncBase* iExecuteCommandAsyncBase;
       
   880 	} functionParams;
       
   881 
       
   882 	functionParams.iFunctionParams = aParameters;
       
   883 
       
   884 	switch(aFunctionCode)
       
   885 		{
       
   886 		case EFunctionSetFile:
       
   887 			{
       
   888 			ASSERT(functionParams.iFunctionParams != NULL);
       
   889 			SetFileL(*functionParams.iSetFile->iSourceFilename,
       
   890 					 functionParams.iSetFile->iOptions);
       
   891 			break;
       
   892 			}
       
   893 
       
   894 		case EFunctionSetData:
       
   895 			{
       
   896 			ASSERT(functionParams.iFunctionParams != NULL);
       
   897 			SetDataL(*functionParams.iSetData->iSourceData,
       
   898 					 functionParams.iSetData->iOptions);
       
   899 			break;
       
   900 			}
       
   901 
       
   902 		case EFunctionContinueHeader:
       
   903 			{
       
   904 			ContinueProcessingHeaderL();
       
   905 			break;
       
   906 			}
       
   907 
       
   908 		case EFunctionConvert:
       
   909 			{
       
   910 			ASSERT(functionParams.iFunctionParams != NULL);
       
   911 			Convert(functionParams.iConvert->iRequestStatus,
       
   912 					functionParams.iConvert->iDestinationHandle,
       
   913 					functionParams.iConvert->iFrameNumber);
       
   914 			break;
       
   915 			}
       
   916 
       
   917 		case EFunctionConvertMask:
       
   918 			{
       
   919 			ASSERT(functionParams.iFunctionParams != NULL);
       
   920 			Convert(functionParams.iConvert->iRequestStatus,
       
   921 					functionParams.iConvert->iDestinationHandle,
       
   922 					functionParams.iConvert->iDestinationMaskHandle,
       
   923 					functionParams.iConvert->iFrameNumber);
       
   924 			break;
       
   925 			}
       
   926 
       
   927 		case EFunctionContinueConvert:
       
   928 			{
       
   929 			ASSERT(functionParams.iFunctionParams != NULL);
       
   930 			ContinueConvert(functionParams.iConvert->iRequestStatus);
       
   931 			break;
       
   932 			}
       
   933 
       
   934 		case EFunctionHandleNewImage:
       
   935 			{
       
   936 			HandleNewlyOpenedImageL();
       
   937 			break;
       
   938 			}
       
   939 
       
   940 		case EFunctionCustomSync:
       
   941 			{
       
   942 			ASSERT(functionParams.iFunctionParams != NULL);
       
   943 			CustomSyncL(functionParams.iCustomSync->iParam);
       
   944 			break;
       
   945 			}
       
   946 
       
   947 		case EFunctionCustomAsync:
       
   948 			{
       
   949 			ASSERT(functionParams.iFunctionParams != NULL);
       
   950 			CustomAsync(functionParams.iCustomSync->iRequestStatus,
       
   951 						functionParams.iCustomSync->iParam);
       
   952 			break;
       
   953 			}
       
   954 
       
   955 		case EFunctionCancel:
       
   956 			{
       
   957 			CancelBody();
       
   958 			break;
       
   959 			}
       
   960 		case EFunctionSetFileHandle:
       
   961 			{
       
   962 			ASSERT(functionParams.iFunctionParams != NULL);
       
   963 			SetFileL(*functionParams.iSetFileHandle->iFile,
       
   964 					 functionParams.iSetFileHandle->iOptions);
       
   965 			break;
       
   966 			}
       
   967 		case EFunctionGetExtension:
       
   968 			{
       
   969 			ASSERT(functionParams.iFunctionParams != NULL);
       
   970 			GetExtensionL(functionParams.iGetExtension->iUid,
       
   971 						  *functionParams.iGetExtension->iExtension);
       
   972 			break;
       
   973 			}
       
   974 		case EFunctionExecuteCommandL:
       
   975 			{
       
   976 			ASSERT(functionParams.iFunctionParams != NULL);
       
   977 			HandleExecuteCommandL(*functionParams.iExecuteCommandBase);
       
   978 			break;
       
   979 			}
       
   980 		case EFunctionExecuteAsyncCommand:
       
   981 			{
       
   982 			ASSERT(functionParams.iFunctionParams != NULL);
       
   983 			HandleExecuteAsyncCommand(*functionParams.iExecuteCommandAsyncBase);
       
   984 			break;
       
   985 			}
       
   986 
       
   987 		default:
       
   988 			{
       
   989 			User::Leave(KErrArgument);
       
   990 			}
       
   991 		}
       
   992 	}
       
   993 
       
   994 /**
       
   995  * Always use a buffer for copies in thread.
       
   996  *
       
   997  */
       
   998 TBool CSubThreadDecoderRelay::MustUseBufferWithDescriptor() const
       
   999 	{
       
  1000 	return ETrue;
       
  1001 	}
       
  1002 
       
  1003 /**
       
  1004  * Do a buffer copy. If the main thread is busy with a function call to this
       
  1005  * thread, do a local copy, else request a copy from the buffer copy listener
       
  1006  * in the main thread. The call will wait on the buffer copy mutex if the main thread
       
  1007  * is busy to change the state to a function call in progress.
       
  1008  *
       
  1009  * @param	"TDes8& aBuffer"
       
  1010  *			The destination buffer for the copy.
       
  1011  * @param	"const TDesC8& aSource"
       
  1012  *			The source descriptor for the copy.
       
  1013  * @param	"TInt aPosition"
       
  1014  *			Position to start copy.
       
  1015  * @param	"TInt aSize"
       
  1016  *			Number of elements to copy.
       
  1017  */
       
  1018 void CSubThreadDecoderRelay::CopyBufferToDescriptor(TDes8& aBuffer, const TDesC8& aSource, TInt aPosition, TInt aSize)
       
  1019 	{
       
  1020 	//Note: assumes that this executes in the codec subthread.
       
  1021 	ASSERT(RThread().Id() == iSubThread->Id());
       
  1022 
       
  1023 	//Wait for iFunctionCallInProgress change to complete with 
       
  1024 	//SetFunctionInProgress() or ResetFunctionInProgress()
       
  1025 	iBufferCopyMutex.Wait(); 
       
  1026 	if(iFunctionCallInProgress)
       
  1027 		{//Do copy in this thread
       
  1028 		//We do not need to keep the mutex if copy is done locally
       
  1029 		iBufferCopyMutex.Signal();
       
  1030 		//Do a local copy
       
  1031 		aBuffer = aSource.Mid(aPosition, aSize);
       
  1032 		}
       
  1033 	else
       
  1034 		{
       
  1035 		//Do a copy in the main thread
       
  1036 		ASSERT(iBufferCopyListener != NULL);
       
  1037 		TRequestStatus status = KRequestPending;
       
  1038 
       
  1039 		//Prime AO in the main thread to do a buffer copy
       
  1040 		iBufferCopyListener->CopyBufferToDescriptor(status, aBuffer, aSource, aPosition, aSize);
       
  1041 
       
  1042 		//Remember parameters in case we need to bypass the copy in main thread's AO
       
  1043 		iCallerStatus = &status;
       
  1044 		iBuffer = &aBuffer;
       
  1045 		iSource = &aSource;
       
  1046 		iPosition = aPosition;
       
  1047 		iSize = aSize;
       
  1048 
       
  1049 		// Force main thread AO to be eligible for RunL() next time control is returned to it's AS
       
  1050 		TRequestStatus *bufferCopyStatus = &iBufferCopyListener->iStatus; 
       
  1051 		iMainThread.RequestComplete(bufferCopyStatus, KErrNone);
       
  1052 
       
  1053 		//If a function call is made (in the main thread) before the CBufferCopyListener AO completes
       
  1054 		//then, SetFunctionInProgress() waits for this signal in the main thread because we don't
       
  1055 		//want to run a function while a buffer copy is in progess.
       
  1056 		//
       
  1057 		//We MUST now release the mutex BEFORE we suspend (this codec subthread) to allow the buffer copy
       
  1058 		//to progress in the main thread - either via CBufferCopyListener AO or in SetFunctionInProgress().
       
  1059 		iBufferCopyMutex.Signal();
       
  1060 
       
  1061 		//Wait until main thread signals that buffer copy is complete
       
  1062 		User::WaitForRequest(status);
       
  1063 		}
       
  1064 	}
       
  1065 
       
  1066 /**
       
  1067  * @return	"TBool"
       
  1068  *			Always ETrue since we are in a thread.
       
  1069  */
       
  1070 TBool CSubThreadDecoderRelay::AmInThread() const
       
  1071 	{
       
  1072 	return ETrue;
       
  1073 	}
       
  1074 
       
  1075 /**
       
  1076  * Inform the decoder to cancel decoding if it does not use
       
  1077  * ActiveObject functionallity. The decoder should constantly 
       
  1078  * check ShouldAbort() and cancel decoding as quickly possible
       
  1079  * if the flag is set.
       
  1080  *
       
  1081  */
       
  1082 void CSubThreadDecoderRelay::AbortDecode()
       
  1083 	{
       
  1084 	iAbortDecode = ETrue;
       
  1085 	}
       
  1086 
       
  1087 /**
       
  1088  * Cancel the decoding operation if one is in progress
       
  1089  *
       
  1090  */
       
  1091 void CSubThreadDecoderRelay::CancelBody()
       
  1092 	{
       
  1093 	if(iBody)
       
  1094 		iBody->Cancel();
       
  1095 	}
       
  1096 
       
  1097 /**
       
  1098  * Indicate to the plugin that the client requested a decode to terminate.
       
  1099  *
       
  1100  * @return	"TBool"
       
  1101  *			ETrue if the plugin must terminate the decode process.
       
  1102  */
       
  1103 TBool CSubThreadDecoderRelay::ShouldAbort() const
       
  1104 	{
       
  1105 	return iAbortDecode;
       
  1106 	}
       
  1107 
       
  1108 void CSubThreadDecoderRelay::Lock()
       
  1109 	{
       
  1110 	iFrameTableMutex.Wait();
       
  1111 	}
       
  1112 
       
  1113 void CSubThreadDecoderRelay::Unlock()
       
  1114 	{
       
  1115 	iFrameTableMutex.Signal();
       
  1116 	}
       
  1117 
       
  1118 TInt CSubThreadDecoderRelay::FrameCount() const
       
  1119 	{
       
  1120 	return iFrameCount;
       
  1121 	}
       
  1122 
       
  1123 void CSubThreadDecoderRelay::SaveFrameCount(TInt aFrameCount)
       
  1124 	{
       
  1125 	iFrameCount = aFrameCount;
       
  1126 	}
       
  1127 /**
       
  1128  * Run CImageDecoderPriv::SetFileL() in the decoder thread,
       
  1129  * using the thread's local file server session.
       
  1130  *
       
  1131  */
       
  1132 void CSubThreadDecoderRelay::SetFileL(const TDesC& aSourceFilename, const CImageDecoder::TOptions aOptions)
       
  1133 	{
       
  1134 	//Use sub thread RFs
       
  1135 	iBody->SetFileL(iFileSession, aSourceFilename, aOptions);
       
  1136 	}
       
  1137 void CSubThreadDecoderRelay::SetFileL(RFile& aFile, const CImageDecoder::TOptions aOptions)
       
  1138 	{
       
  1139 	iBody->SetFileL(aFile, aOptions);
       
  1140 	}
       
  1141 
       
  1142 /**
       
  1143  * Run CImageDecoderPriv::SetDataL() in the decoder thread,
       
  1144  * using the thread's local file server session.
       
  1145  *
       
  1146  */
       
  1147 void CSubThreadDecoderRelay::SetDataL(const TDesC8& aSourceData, const CImageDecoder::TOptions aOptions)
       
  1148 	{
       
  1149 	//Use sub thread RFs
       
  1150 	iBody->SetDataL(iFileSession, aSourceData, aOptions);
       
  1151 	}
       
  1152 
       
  1153 /**
       
  1154  * Run CImageDecoderPriv::Convert() in the decoder thread,
       
  1155  * duplicating the client's image bitmap.
       
  1156  *
       
  1157  */
       
  1158 void CSubThreadDecoderRelay::Convert(TRequestStatus* aRequestStatus, TInt aDestinationHandle, TInt aFrameNumber)
       
  1159 	{
       
  1160 	iAbortDecode = EFalse;
       
  1161 
       
  1162 	//Create a bitmap in the sub thread
       
  1163 	delete iDestination; iDestination = NULL;
       
  1164 	iDestination = new CFbsBitmap;
       
  1165 	if(iDestination == NULL)
       
  1166 		{
       
  1167 		iMainThread.RequestComplete(aRequestStatus, KErrNoMemory);
       
  1168 		return;
       
  1169 		}
       
  1170 
       
  1171 	//Duplicate the client bitmap
       
  1172 	TInt error = iDestination->Duplicate(aDestinationHandle);
       
  1173 	if(error != KErrNone)
       
  1174 		{
       
  1175 		iMainThread.RequestComplete(aRequestStatus, error);
       
  1176 		return;
       
  1177 		}
       
  1178 
       
  1179 	iBody->Convert(iMainThread, aRequestStatus, *iDestination, aFrameNumber);
       
  1180 
       
  1181 	}
       
  1182 
       
  1183 /**
       
  1184  * Run CImageDecoderPriv::Convert() in the decoder thread,
       
  1185  * duplicating the client's image and mask bitmap.
       
  1186  *
       
  1187  */
       
  1188 void CSubThreadDecoderRelay::Convert(TRequestStatus* aRequestStatus, TInt aDestinationHandle, TInt aDestinationMaskHandle, TInt aFrameNumber)
       
  1189 	{
       
  1190 	iAbortDecode = EFalse;
       
  1191 	
       
  1192 	//Create a bitmap in the sub thread
       
  1193 	delete iDestination; iDestination = NULL;
       
  1194 	iDestination = new CFbsBitmap;
       
  1195 	if(iDestination == NULL)
       
  1196 		{
       
  1197 		iMainThread.RequestComplete(aRequestStatus, KErrNoMemory);
       
  1198 		return;
       
  1199 		}
       
  1200 
       
  1201 	//Duplicate the client bitmap
       
  1202 	TInt error = iDestination->Duplicate(aDestinationHandle);
       
  1203 	if(error != KErrNone)
       
  1204 		{
       
  1205 		iMainThread.RequestComplete(aRequestStatus, error);
       
  1206 		return;
       
  1207 		}
       
  1208 
       
  1209 	//Create a mask bitmap in the sub thread
       
  1210 	delete iDestinationMask; iDestinationMask = NULL;
       
  1211 	iDestinationMask = new CFbsBitmap;
       
  1212 	if(iDestinationMask == NULL)
       
  1213 		{
       
  1214 		iMainThread.RequestComplete(aRequestStatus, KErrNoMemory);
       
  1215 		return;
       
  1216 		}
       
  1217 
       
  1218 	//Duplicate the mask client bitmap
       
  1219 	error = iDestinationMask->Duplicate(aDestinationMaskHandle);
       
  1220 	if(error != KErrNone)
       
  1221 		{
       
  1222 		iMainThread.RequestComplete(aRequestStatus, error);
       
  1223 		return;
       
  1224 		}
       
  1225 
       
  1226 	iBody->Convert(iMainThread, aRequestStatus, *iDestination, *iDestinationMask, aFrameNumber);
       
  1227 	}
       
  1228 
       
  1229 void CSubThreadDecoderRelay::ContinueConvert(TRequestStatus* aRequestStatus)
       
  1230 	{
       
  1231 	iAbortDecode = EFalse;
       
  1232 	iBody->ContinueConvert(iMainThread, aRequestStatus);
       
  1233 	}
       
  1234 
       
  1235 void CSubThreadDecoderRelay::HandleNewlyOpenedImageL()
       
  1236 	{
       
  1237 	iBody->HandleNewlyOpenedImageL();
       
  1238 	}
       
  1239 
       
  1240 void CSubThreadDecoderRelay::ContinueProcessingHeaderL()
       
  1241 	{
       
  1242 	iBody->ContinueProcessingHeaderL();
       
  1243 	}
       
  1244 
       
  1245 void CSubThreadDecoderRelay::CustomSyncL(TInt aParam)
       
  1246 	{
       
  1247 	iBody->CustomSyncL(aParam);
       
  1248 	}
       
  1249 
       
  1250 void CSubThreadDecoderRelay::CustomAsync(TRequestStatus* aRequestStatus, TInt aParam)
       
  1251 	{
       
  1252 	iBody->CustomAsync(iMainThread, aRequestStatus, aParam);
       
  1253 	}
       
  1254 
       
  1255 void CSubThreadDecoderRelay::GetExtensionL(TUid aExtUid, MImageConvExtension*& aExtPtr)
       
  1256 	{
       
  1257 	// Get the actual extension
       
  1258 	iBody->GetExtensionL(aExtUid, aExtPtr);
       
  1259 	CImageConvStubBase* stub = NULL;
       
  1260 	TRAPD(err, stub = ProxyStubUtility::NewStubL(aExtUid, aExtPtr, iBody, iMainThread));
       
  1261 	if(err != KErrNone)
       
  1262 		{
       
  1263 		delete stub;
       
  1264 		aExtPtr->Release();
       
  1265 		aExtPtr = NULL;
       
  1266 		User::Leave(err);
       
  1267 		}
       
  1268 	CleanupStack::PushL(stub);
       
  1269 	iStubs.AppendL(stub);
       
  1270 	CleanupStack::Pop(stub);
       
  1271 	aExtPtr = NULL;
       
  1272 	}
       
  1273 	
       
  1274 void CSubThreadDecoderRelay::HandleExecuteCommandL(TExecuteCommandParamsBase& aExecuteCommandBase)
       
  1275 	{
       
  1276 	for(TInt i = 0; i < iStubs.Count(); i++)
       
  1277 		{
       
  1278 		if((iStubs[i])->Uid() == aExecuteCommandBase.iUid)
       
  1279 			{
       
  1280 			(iStubs[i])->HandleExecuteCommandL(aExecuteCommandBase);
       
  1281 			return;
       
  1282 			}
       
  1283 		}
       
  1284 	ASSERT(EFalse);
       
  1285 	}
       
  1286 	
       
  1287 void CSubThreadDecoderRelay::HandleExecuteAsyncCommand(TExecuteCommandParamsAsyncBase& aExecuteCommandBase)
       
  1288 	{
       
  1289 	for(TInt i = 0; i < iStubs.Count(); i++)
       
  1290 		{
       
  1291 		if((iStubs[i])->Uid() == aExecuteCommandBase.iUid)
       
  1292 			{
       
  1293 			(iStubs[i])->HandleExecuteAsyncCommand(aExecuteCommandBase);
       
  1294 			return;
       
  1295 			}
       
  1296 		}
       
  1297 	ASSERT(EFalse);
       
  1298 	}
       
  1299 
       
  1300 //
       
  1301 //CSubThreadEncoderRelay
       
  1302 //
       
  1303 CSubThreadRelay* CSubThreadEncoderRelay::NewL(TThreadId aMainThreadId, TAny* aEncoderParam)
       
  1304 	{
       
  1305 	CSubThreadEncoderRelay* self;
       
  1306 	TThreadEncoderRelayParam* encoderParam;
       
  1307 
       
  1308 	encoderParam = STATIC_CAST(TThreadEncoderRelayParam*, aEncoderParam);
       
  1309 
       
  1310 	self = new (ELeave) CSubThreadEncoderRelay();
       
  1311 	CleanupStack::PushL(self);
       
  1312 	self->ConstructL(aMainThreadId, encoderParam->iConstruct);
       
  1313 
       
  1314 	CleanupStack::Pop(self);
       
  1315 	return self;
       
  1316 
       
  1317 	}
       
  1318 
       
  1319 CSubThreadEncoderRelay::CSubThreadEncoderRelay()
       
  1320 	{
       
  1321 	}
       
  1322 
       
  1323 void CSubThreadEncoderRelay::ConstructL(TThreadId aMainThreadId, CImageEncodeConstruct* aConstruct)
       
  1324 	{
       
  1325 	CSubThreadRelay::ConstructL(aMainThreadId);
       
  1326 
       
  1327 	//Open a file server session
       
  1328 	User::LeaveIfError(iFileSession.Connect());
       
  1329 	//Make the session shareable for all threads
       
  1330 #ifdef __IPC_V2_PRESENT__
       
  1331 	User::LeaveIfError(iFileSession.ShareAuto());
       
  1332 #else
       
  1333 	User::LeaveIfError(iFileSession.Share(RSessionBase::EAutoAttach));
       
  1334 #endif
       
  1335 	iBody = CImageEncoderPriv::NewL(aConstruct, this);
       
  1336 	iBody->CreatePluginL();
       
  1337 	}
       
  1338 
       
  1339 /**
       
  1340  * Inform the encoder to cancel encoding if it does not use
       
  1341  * ActiveObject functionallity. The encoder should constantly 
       
  1342  * check ShouldAbort() and cancel encoding as quickly possible
       
  1343  * if the flag is set.
       
  1344  *
       
  1345  */
       
  1346 void CSubThreadEncoderRelay::AbortEncode()
       
  1347 	{
       
  1348 	iAbortEncode = ETrue;
       
  1349 	}
       
  1350 
       
  1351 void CSubThreadEncoderRelay::CancelBody()
       
  1352 	{
       
  1353 	if(iBody)
       
  1354 		iBody->Cancel();
       
  1355 	}
       
  1356 
       
  1357 CSubThreadEncoderRelay::~CSubThreadEncoderRelay()
       
  1358 	{
       
  1359 	iStubs.ResetAndDestroy();
       
  1360 	if(iBody)
       
  1361 		{
       
  1362 		CancelBody();
       
  1363 		delete iBody;
       
  1364 		}
       
  1365 	delete iSource;
       
  1366 	iFileSession.Close();
       
  1367 	}
       
  1368 
       
  1369 TBool CSubThreadEncoderRelay::AmInThread() const
       
  1370 	{
       
  1371 	return ETrue;
       
  1372 	}
       
  1373 
       
  1374 TBool CSubThreadEncoderRelay::ShouldAbort() const
       
  1375 	{
       
  1376 	return iAbortEncode;
       
  1377 	}
       
  1378 
       
  1379 void CSubThreadEncoderRelay::RunFunctionL(TInt aFunctionCode, TAny* aParameters)
       
  1380 	{
       
  1381 	union
       
  1382 	{
       
  1383 	TAny* iFunctionParams;
       
  1384 	TEncodeSetFileParams* iSetFile;
       
  1385 	TEncodeSetFileHandleParams* iSetFileHandle;
       
  1386 	TEncodeSetDataParams* iSetData;
       
  1387 	TEncodeConvertParams* iConvert;
       
  1388 	TCustomSyncParams* iCustomSync;
       
  1389 	TGetExtensionParams* iGetExtension;
       
  1390 	TExecuteCommandParamsBase* iExecuteCommandBase;
       
  1391 	TExecuteCommandParamsAsyncBase* iExecuteCommandAsyncBase;
       
  1392 	} functionParams;
       
  1393 
       
  1394 	functionParams.iFunctionParams = aParameters;
       
  1395 
       
  1396 	switch(aFunctionCode)
       
  1397 		{
       
  1398 		case EFunctionSetFile:
       
  1399 			{
       
  1400 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1401 			SetFileL(*functionParams.iSetFile->iDestinationFilename,
       
  1402 					 functionParams.iSetFile->iOptions);
       
  1403 			break;
       
  1404 			}
       
  1405 
       
  1406 		case EFunctionSetData:
       
  1407 			{
       
  1408 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1409 			SetDataL(*functionParams.iSetData->iDestinationData,
       
  1410 					 functionParams.iSetData->iOptions);
       
  1411 			break;
       
  1412 			}
       
  1413 
       
  1414 		case EFunctionConvert:
       
  1415 			{
       
  1416 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1417 			Convert(functionParams.iConvert->iRequestStatus,
       
  1418 					functionParams.iConvert->iSourceHandle,
       
  1419 					functionParams.iConvert->iFrameImageData);
       
  1420 			break;
       
  1421 			}
       
  1422 
       
  1423 		case EFunctionCustomSync:
       
  1424 			{
       
  1425 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1426 			CustomSyncL(functionParams.iCustomSync->iParam);
       
  1427 			break;
       
  1428 			}
       
  1429 
       
  1430 		case EFunctionCustomAsync:
       
  1431 			{
       
  1432 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1433 			CustomAsync(functionParams.iCustomSync->iRequestStatus,
       
  1434 						functionParams.iCustomSync->iParam);
       
  1435 			break;
       
  1436 			}
       
  1437 
       
  1438 		case EFunctionCancel:
       
  1439 			{
       
  1440 			CancelBody();
       
  1441 			break;
       
  1442 			}
       
  1443 		case EFunctionSetFileHandle:
       
  1444 			{
       
  1445 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1446 			SetFileL(*functionParams.iSetFileHandle->iFile,
       
  1447 					 functionParams.iSetFile->iOptions);
       
  1448 			break;
       
  1449 			}
       
  1450 		case EFunctionGetExtension:
       
  1451 			{
       
  1452 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1453 			GetExtensionL(functionParams.iGetExtension->iUid,
       
  1454 						  *functionParams.iGetExtension->iExtension);
       
  1455 			break;
       
  1456 			}
       
  1457 		case EFunctionExecuteCommandL:
       
  1458 			{
       
  1459 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1460 			HandleExecuteCommandL(*functionParams.iExecuteCommandBase);
       
  1461 			break;
       
  1462 			}
       
  1463 		case EFunctionExecuteAsyncCommand:
       
  1464 			{
       
  1465 			ASSERT(functionParams.iFunctionParams != NULL);
       
  1466 			HandleExecuteAsyncCommand(*functionParams.iExecuteCommandAsyncBase);
       
  1467 			break;
       
  1468 			}
       
  1469 		default:
       
  1470 			{
       
  1471 			User::Leave(KErrArgument);
       
  1472 			}
       
  1473 		}
       
  1474 	}
       
  1475 
       
  1476 void CSubThreadEncoderRelay::SetFileL(const TDesC& aDestinationFilename, const CImageEncoder::TOptions aOptions)
       
  1477 	{
       
  1478 	//Use sub thread RFs
       
  1479 	iBody->SetFileL(iFileSession, aDestinationFilename, aOptions);
       
  1480 	}
       
  1481 	
       
  1482 void CSubThreadEncoderRelay::SetFileL(RFile& aFile, const CImageEncoder::TOptions aOptions)
       
  1483 	{
       
  1484 	iBody->SetFileL(aFile, aOptions);
       
  1485 	}
       
  1486 
       
  1487 void CSubThreadEncoderRelay::SetDataL(HBufC8*& aDestinationData, const CImageEncoder::TOptions aOptions)
       
  1488 	{
       
  1489 	iBody->SetDataL(aDestinationData, aOptions);
       
  1490 	}
       
  1491 
       
  1492 void CSubThreadEncoderRelay::Convert(TRequestStatus* aRequestStatus, TInt aSourceHandle, const CFrameImageData* aFrameImageData)
       
  1493 	{
       
  1494 	TInt error = KErrNone;
       
  1495 
       
  1496 	iAbortEncode = EFalse;
       
  1497 
       
  1498 	//Create a bitmap in the sub thread
       
  1499 	delete iSource; iSource = NULL;
       
  1500 	TRAP(error,iSource = new (ELeave) CFbsBitmap);
       
  1501 	if(error != KErrNone)
       
  1502 		{
       
  1503 		iMainThread.RequestComplete(aRequestStatus, error);
       
  1504 		return;
       
  1505 		}
       
  1506 
       
  1507 	//Duplicate the client bitmap
       
  1508 	error = iSource->Duplicate(aSourceHandle);
       
  1509 	if(error != KErrNone)
       
  1510 		{
       
  1511 		iMainThread.RequestComplete(aRequestStatus, error);
       
  1512 		return;
       
  1513 		}
       
  1514 
       
  1515 	iBody->Convert(iMainThread, aRequestStatus, *iSource, aFrameImageData);
       
  1516 	}
       
  1517 
       
  1518 void CSubThreadEncoderRelay::CustomSyncL(TInt aParam)
       
  1519 	{
       
  1520 	iBody->CustomSyncL(aParam);
       
  1521 	}
       
  1522 
       
  1523 void CSubThreadEncoderRelay::CustomAsync(TRequestStatus* aRequestStatus, TInt aParam)
       
  1524 	{
       
  1525 	iBody->CustomAsync(iMainThread, aRequestStatus, aParam);
       
  1526 	}
       
  1527 
       
  1528 void CSubThreadEncoderRelay::GetExtensionL(TUid aExtUid, MImageConvExtension*& aExtPtr)
       
  1529 	{
       
  1530 	// Get the actual extension
       
  1531 	iBody->GetExtensionL(aExtUid, aExtPtr);
       
  1532 	CImageConvStubBase* stub = NULL;
       
  1533 	TRAPD(err,  stub = ProxyStubUtility::NewStubL(aExtUid, aExtPtr, iBody, iMainThread));
       
  1534 	if(err != KErrNone)
       
  1535 		{
       
  1536 		delete stub;
       
  1537 		aExtPtr->Release();
       
  1538 		aExtPtr = NULL;
       
  1539 		User::Leave(err);
       
  1540 		}
       
  1541 	CleanupStack::PushL(stub);
       
  1542 	iStubs.AppendL(stub);
       
  1543 	CleanupStack::Pop(stub);
       
  1544 	aExtPtr = NULL;
       
  1545 	}
       
  1546 	
       
  1547 void CSubThreadEncoderRelay::HandleExecuteCommandL(TExecuteCommandParamsBase& aExecuteCommandBase)
       
  1548 	{
       
  1549 	for(TInt i = 0; i < iStubs.Count(); i++)
       
  1550 		{
       
  1551 		if((iStubs[i])->Uid() == aExecuteCommandBase.iUid)
       
  1552 			{
       
  1553 			(iStubs[i])->HandleExecuteCommandL(aExecuteCommandBase);
       
  1554 			return;
       
  1555 			}
       
  1556 		}
       
  1557 	ASSERT(EFalse);
       
  1558 	}
       
  1559 	
       
  1560 void CSubThreadEncoderRelay::HandleExecuteAsyncCommand(TExecuteCommandParamsAsyncBase& aExecuteCommandBase)
       
  1561 	{
       
  1562 	for(TInt i = 0; i < iStubs.Count(); i++)
       
  1563 		{
       
  1564 		if((iStubs[i])->Uid() == aExecuteCommandBase.iUid)
       
  1565 			{
       
  1566 			(iStubs[i])->HandleExecuteAsyncCommand(aExecuteCommandBase);
       
  1567 			return;
       
  1568 			}
       
  1569 		}
       
  1570 	ASSERT(EFalse);
       
  1571 	}
       
  1572 
       
  1573