omxil/video/omxilgraphicsink/src/omxilgraphicsinkprocessingfunction.cpp
branchOpenMAX-IL_SHAI
changeset 16 eedf2dcd43c6
equal deleted inserted replaced
15:c1e808730d6c 16:eedf2dcd43c6
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include "log.h"
       
    24 
       
    25 #include "omxilgraphicsinkprocessingfunction.h"
       
    26 #include "omxilgraphicsinktrace.h"
       
    27 #include "omxilgraphicsinkpanics.h"
       
    28 #include "omxilgraphicsinkvpb0port.h"
       
    29 #include "omxilcallbackmanager.h"
       
    30 #include <hal.h>
       
    31 #include <graphics/suerror.h>
       
    32 #include "omxilgraphicsinkextensionsindexes.h"
       
    33 #include <platform/openmax/il/shai/OMX_Symbian_ComponentExt.h>
       
    34 
       
    35 // Constant numbers
       
    36 #ifndef __WINSCW__
       
    37 const TInt KRefGfxAlignment = RSurfaceManager::EPageAligned;
       
    38 #else
       
    39 const TInt KRefGfxAlignment = 2;
       
    40 #endif
       
    41 static const TBool KRefGfxContiguous = ETrue;
       
    42 static const TInt KSurfaceUpdateNumOfMessageSlots = 4;
       
    43 static const TUint32 KNullTickCount = 0xFFFFFFFF;
       
    44 
       
    45 
       
    46 /**
       
    47 Create a new processing function object.
       
    48 
       
    49 @param 	aCallbacks The callback manager interface for processing function.
       
    50 
       
    51 @return A pointer to the processing function object to be created.
       
    52 */
       
    53 COmxILGraphicSinkProcessingFunction*
       
    54 COmxILGraphicSinkProcessingFunction::NewL(MOmxILCallbackNotificationIf& aCallbacks)
       
    55 	{
       
    56 	COmxILGraphicSinkProcessingFunction* self =
       
    57 		new (ELeave)COmxILGraphicSinkProcessingFunction(aCallbacks);
       
    58 	CleanupStack::PushL(self);
       
    59 	self->ConstructL();
       
    60 	CleanupStack::Pop(self);
       
    61 	return self;
       
    62 	}
       
    63 
       
    64 /**
       
    65 Second phase construction for the processing function. Loads the device driver for surface manager and initializes the surface attributes.
       
    66 */
       
    67 void
       
    68 COmxILGraphicSinkProcessingFunction::ConstructL()
       
    69 	{	
       
    70     iTransitionToPauseWait = new(ELeave) CActiveSchedulerWait();
       
    71     User::LeaveIfError(iTransitionToPauseWaitSemaphore.CreateLocal(0));
       
    72 
       
    73     //record the ID of the creator thread for later use
       
    74     iOwnerThreadId = RThread().Id();
       
    75 
       
    76 	iGraphicSurfaceAccess = CGraphicSurfaceAccess::NewL(*this);	        
       
    77 	iPFHelper = CPFHelper::NewL(*this, *iGraphicSurfaceAccess);
       
    78 	
       
    79 	User::LeaveIfError(iBufferMutex.CreateLocal());
       
    80 	InitSurfaceAttributes();
       
    81     iState = OMX_StateLoaded;
       
    82 	}
       
    83 
       
    84 /**
       
    85 Constructor of the class.
       
    86 
       
    87 @param 	aCallbacks The callback manager interface for processing function.
       
    88 */
       
    89 COmxILGraphicSinkProcessingFunction::COmxILGraphicSinkProcessingFunction(
       
    90 		MOmxILCallbackNotificationIf& aCallbacks)
       
    91 	:
       
    92 	COmxILProcessingFunction(aCallbacks)
       
    93 	{
       
    94 	HAL::Get(HALData::EFastCounterFrequency,iFastCounterFrequency);
       
    95 	}
       
    96 
       
    97 /**
       
    98 Destructor of the class.
       
    99 */
       
   100 COmxILGraphicSinkProcessingFunction::~COmxILGraphicSinkProcessingFunction()
       
   101 	{
       
   102     delete iTransitionToPauseWait;
       
   103     iTransitionToPauseWaitSemaphore.Close();
       
   104     
       
   105 	// Check in case the driver has not been closed. That would happen in
       
   106 	// an scenario where the component is deleted while being in
       
   107 	// OMX_StateExecuting state.
       
   108 	if(iPFHelper &&
       
   109 	   (iState == OMX_StateInvalid  ||
       
   110 	    iState == OMX_StateExecuting ||
       
   111 	    iState == OMX_StatePause))
       
   112 		{
       
   113 		// Ignore error if the following call fails
       
   114 		iPFHelper->StopSync();
       
   115 		}
       
   116 
       
   117 	delete iPFHelper;
       
   118 	delete iGraphicSurfaceAccess;
       
   119 	
       
   120 	iSurfaceManager.Close();
       
   121 	
       
   122 	// Buffer headers are not owned by the processing function
       
   123 	iBuffersToEmpty.Close();
       
   124 	
       
   125 	iBufferMutex.Close();
       
   126 	}
       
   127 
       
   128 /**
       
   129 This method provides the state change information within the processing function so that appropriate action can be taken. 
       
   130 This state change information is provided by the FSM on behalf of the IL Client.
       
   131 
       
   132 @param 	aNewState The new state of FSM.
       
   133 
       
   134 @return  OMX_ErrorNone if successful
       
   135          OMX_ErrorInsufficientResources if fail to start GraphicSink frame acceptor
       
   136          OMX_ErrorIncorrectStateTransition if unsupported state
       
   137          Any other OpenMAX IL wide error code
       
   138 */
       
   139 OMX_ERRORTYPE
       
   140 COmxILGraphicSinkProcessingFunction::StateTransitionIndication(COmxILFsm::TStateIndex aNewState)
       
   141 	{
       
   142 	switch(aNewState)
       
   143 		{
       
   144 	case COmxILFsm::EStateExecuting:
       
   145 		{
       
   146 		return iPFHelper->ExecuteAsync();
       
   147 		}
       
   148 	case COmxILFsm::EStateInvalid:
       
   149 		{
       
   150 		return iPFHelper->StopAsync();
       
   151 		}
       
   152 	case COmxILFsm::EStatePause:
       
   153 		{
       
   154 		// must be done immediately
       
   155 		OMX_ERRORTYPE omxErr = iPFHelper->Pause();
       
   156 		if(omxErr == OMX_ErrorNone)
       
   157 			{
       
   158 			WaitForTransitionToPauseToFinish();
       
   159 			}
       
   160 	    return omxErr;
       
   161 		}
       
   162 	case COmxILFsm::EStateIdle:
       
   163 		{
       
   164 		iBufferMutex.Wait();
       
   165 		iBuffersToEmpty.Reset();
       
   166 		iBufferMutex.Signal();
       
   167 		iState = OMX_StateIdle;
       
   168 		return OMX_ErrorNone;
       
   169 		}
       
   170 	case COmxILFsm::EStateLoaded:
       
   171 	case COmxILFsm::EStateWaitForResources:
       
   172 		{
       
   173 		return iPFHelper->StopAsync();
       
   174 		}
       
   175 	case COmxILFsm::ESubStateLoadedToIdle:
       
   176 		{
       
   177 	    // Open a channel to the surface manager logical device driver. 
       
   178 	    TInt err = iSurfaceManager.Open();
       
   179 	    if ( err != KErrNone)
       
   180 	        {
       
   181 	        return OMX_ErrorHardware;
       
   182 	        }
       
   183 	    
       
   184 	    if (iPFHelper->OpenDevice() != KErrNone)
       
   185 	        {
       
   186             return OMX_ErrorInsufficientResources;
       
   187 	        }
       
   188 	    /*
       
   189 	    if (iGraphicSinkPort->ValidateStride() != OMX_ErrorNone)
       
   190 	        {
       
   191             return OMX_ErrorUnsupportedSetting;
       
   192 	        }
       
   193 	    return OMX_ErrorNone;
       
   194 	    */
       
   195 	    return iGraphicSinkPort->ValidateStride();
       
   196 		}
       
   197 	case COmxILFsm::ESubStateIdleToLoaded:
       
   198 		{
       
   199 		return iPFHelper->CloseDevice();
       
   200 		}
       
   201 	case COmxILFsm::ESubStateExecutingToIdle:
       
   202 		{
       
   203 		// must be done immediately
       
   204 		return iPFHelper->StopAsync();
       
   205 		}
       
   206 	case COmxILFsm::ESubStatePauseToIdle:
       
   207 		{
       
   208 		// Ignore these transitions...
       
   209 		return OMX_ErrorNone;
       
   210 		}
       
   211 	default:
       
   212 		{
       
   213 		return OMX_ErrorIncorrectStateTransition;
       
   214 		}
       
   215 		};
       
   216 	}
       
   217 
       
   218 /**
       
   219 Flushes all the buffers retained by the processing function and sends it to either IL Client or the Tunelled component, as the case may be.
       
   220 
       
   221 @param 	aPortIndex Port index used to flush buffers from a given port of the component.
       
   222 @param  aDirection This describes the direction of the port.
       
   223 		
       
   224 @return OMX_ErrorNone if successful;
       
   225 		Any other OpenMAX IL wide error code;
       
   226 */
       
   227 OMX_ERRORTYPE
       
   228 COmxILGraphicSinkProcessingFunction::BufferFlushingIndication(
       
   229 	TUint32 aPortIndex,
       
   230 	OMX_DIRTYPE aDirection)
       
   231 	{
       
   232 	iBufferMutex.Wait();
       
   233     if ((aPortIndex == OMX_ALL && aDirection == OMX_DirMax) ||
       
   234 		(aPortIndex == 0 && aDirection == OMX_DirInput))
       
   235 	{
       
   236 	    // Send BufferDone notifications for each buffer...
       
   237 		if(iBufferOnScreen != NULL)
       
   238 			{
       
   239 			// TODO error handling
       
   240 			iCallbacks.BufferDoneNotification(iBufferOnScreen, 0, OMX_DirInput);
       
   241 			iBufferOnScreen = NULL;
       
   242 			}
       
   243 		const TUint bufferCount = iBuffersToEmpty.Count();
       
   244 		OMX_BUFFERHEADERTYPE* pBufferHeader = 0;
       
   245 		for (TUint i=0; i<bufferCount; i++)
       
   246 			{
       
   247 			pBufferHeader = iBuffersToEmpty[i];
       
   248 			pBufferHeader->nTickCount = KNullTickCount;
       
   249 			iCallbacks.
       
   250 				BufferDoneNotification(
       
   251 					pBufferHeader,
       
   252 					pBufferHeader->nInputPortIndex,
       
   253 					OMX_DirInput
       
   254 					);
       
   255 			}
       
   256 		// Empty buffer lists...
       
   257 		iBuffersToEmpty.Reset();
       
   258 
       
   259 		iBufferMutex.Signal();
       
   260 		return OMX_ErrorNone;
       
   261 	}
       
   262 	else
       
   263 		{
       
   264 		iBufferMutex.Signal();
       
   265 		return OMX_ErrorBadParameter;
       
   266 		}
       
   267 	}
       
   268 
       
   269 /**
       
   270 Update the structure corresponding to the given index which belongs to the static parameters list.
       
   271 
       
   272 @param 	aParamIndex The index representing the desired structure to be updated.
       
   273 @param  aComponentParameterStructure A pointer to structure which has the desired settings that will be used to update the Processing function.
       
   274 		
       
   275 @return OMX_ErrorNone if successful;
       
   276 		OMX_ErrorUnsupportedIndex if unsupported index;
       
   277 		OMX_ErrorUnsupportedSetting if pixel format is EUidPixelFormatUnknown;
       
   278 		Any other OpenMAX IL wide error code;
       
   279 */
       
   280 OMX_ERRORTYPE
       
   281 COmxILGraphicSinkProcessingFunction::ParamIndication(
       
   282 	OMX_INDEXTYPE aParamIndex,
       
   283 	const TAny* apComponentParameterStructure)
       
   284 	{
       
   285 	DEBUG_PRINTF(_L8("COmxILGraphicSinkProcessingFunction::PortParamIndication"));
       
   286 	
       
   287 	switch(aParamIndex)
       
   288 		{
       
   289 		case OMX_IndexParamPortDefinition:
       
   290 			{
       
   291 			const OMX_PARAM_PORTDEFINITIONTYPE* portDefinition = static_cast<const OMX_PARAM_PORTDEFINITIONTYPE*>(apComponentParameterStructure);
       
   292 			
       
   293 			//
       
   294 			// All the fields in SurfaceAttribute structure should be updated.
       
   295 			//
       
   296 			iGraphicSurfaceSettings.iSurfaceAttributes.iSize.iWidth = portDefinition->format.video.nFrameWidth;
       
   297 			iGraphicSurfaceSettings.iSurfaceAttributes.iSize.iHeight = portDefinition->format.video.nFrameHeight;
       
   298 			
       
   299 			// Need to convert OMX Color Format to TUidPixelFormat.
       
   300 			TUidPixelFormat pixelFormat = ConvertPixelFormat(portDefinition->format.video.eColorFormat);
       
   301 			if(pixelFormat == EUidPixelFormatUnknown)
       
   302 				{
       
   303                 return OMX_ErrorUnsupportedSetting;
       
   304 				}
       
   305 			else
       
   306 				{
       
   307                 iGraphicSurfaceSettings.iSurfaceAttributes.iPixelFormat = pixelFormat;
       
   308 				}
       
   309 			
       
   310 			iGraphicSurfaceSettings.iSurfaceAttributes.iBuffers = portDefinition->nBufferCountActual;
       
   311 			iGraphicSurfaceSettings.iSurfaceAttributes.iStride = portDefinition->format.video.nStride;
       
   312 			break;
       
   313 			}
       
   314 		case OMX_IndexParamVideoPortFormat:
       
   315 			{
       
   316 			const OMX_VIDEO_PARAM_PORTFORMATTYPE* videoPortFormat = static_cast<const OMX_VIDEO_PARAM_PORTFORMATTYPE*>(apComponentParameterStructure);
       
   317 
       
   318 			// only OMX_COLOR_FORMATTYPE eColorFormat to be used for SurfaceAttributes.iPixelFormat		
       
   319 			TUidPixelFormat pixelFormat = ConvertPixelFormat(videoPortFormat->eColorFormat);
       
   320 			if(pixelFormat == EUidPixelFormatUnknown)
       
   321 				{
       
   322 				return OMX_ErrorUnsupportedSetting;
       
   323 				}
       
   324 			else
       
   325 				{
       
   326                 iGraphicSurfaceSettings.iSurfaceAttributes.iPixelFormat = pixelFormat;
       
   327 				}
       
   328 			break;
       
   329 			}
       
   330 		default:
       
   331 			{
       
   332 			return OMX_ErrorUnsupportedIndex;
       
   333 			}
       
   334 		}
       
   335 	return OMX_ErrorNone;
       
   336 	}
       
   337 
       
   338 /**
       
   339 Update the structure corresponding to the given index which belongs to the dynamic configuration list.
       
   340 
       
   341 @param 	aConfigIndex The index representing the desired structure to be updated.
       
   342 @param  aComponentConfigStructure A pointer to structure which has the desired settings that will be used to update the Processing function.
       
   343 		
       
   344 @return OMX_ErrorNone if successful;
       
   345 		OMX_ErrorUnsupportedIndex if unsupported index;
       
   346 		OMX_ErrorUnsupportedSetting if SurfaceConfiguration returns error;
       
   347 		Any other OpenMAX IL wide error code;
       
   348 */
       
   349 OMX_ERRORTYPE
       
   350 COmxILGraphicSinkProcessingFunction::ConfigIndication(OMX_INDEXTYPE aConfigIndex,
       
   351 													  const TAny* apComponentConfigStructure)
       
   352 	{
       
   353 	DEBUG_PRINTF(_L8("COmxILGraphicSinkProcessingFunction::ConfigIndication"));
       
   354 
       
   355 	TInt err = KErrNone;
       
   356 	
       
   357 	switch(aConfigIndex)
       
   358 		{
       
   359 	    case OMX_SymbianIndexConfigSharedChunkMetadata:
       
   360             {           
       
   361             const OMX_SYMBIAN_CONFIG_SHAREDCHUNKMETADATATYPE*
       
   362                 pSharedChunkMetadata
       
   363                 = static_cast<
       
   364                 const OMX_SYMBIAN_CONFIG_SHAREDCHUNKMETADATATYPE*>(
       
   365                     apComponentConfigStructure);
       
   366  
       
   367             iGraphicSurfaceAccess->iSharedChunkHandleId = pSharedChunkMetadata->nHandleId;
       
   368             iGraphicSurfaceAccess->iSharedChunkThreadId = pSharedChunkMetadata->nOwnerThreadId;
       
   369             
       
   370             iGraphicSurfaceAccess->iIsLocalChunk = EFalse;
       
   371             break;
       
   372             }
       
   373 		case OMX_IndexConfigCommonScale:
       
   374 			{
       
   375 			const OMX_CONFIG_SCALEFACTORTYPE* scaleFactor = static_cast<const OMX_CONFIG_SCALEFACTORTYPE*>(apComponentConfigStructure);
       
   376 
       
   377 			err = iGraphicSurfaceSettings.iSurfaceConfig.SetExtent(TRect(TSize(scaleFactor->xWidth, scaleFactor->xHeight)));
       
   378 			if(err != KErrNone)
       
   379 				{
       
   380 				return OMX_ErrorUnsupportedSetting;
       
   381 				}
       
   382 
       
   383 			break;
       
   384 			}
       
   385 		case OMX_IndexConfigCommonOutputSize:
       
   386 			{
       
   387 			const OMX_FRAMESIZETYPE* frameSize = static_cast<const OMX_FRAMESIZETYPE*>(apComponentConfigStructure);
       
   388 
       
   389 			err = iGraphicSurfaceSettings.iSurfaceConfig.SetExtent(TRect(TSize(frameSize->nWidth, frameSize->nHeight)));
       
   390 			if(err != KErrNone)
       
   391 				{
       
   392 				return OMX_ErrorUnsupportedSetting;
       
   393 				}
       
   394 			
       
   395 			break;
       
   396 			}
       
   397 		case OMX_IndexConfigCommonInputCrop:
       
   398 		case OMX_IndexConfigCommonOutputCrop:
       
   399 		case OMX_IndexConfigCommonExclusionRect:
       
   400 			{
       
   401 			const OMX_CONFIG_RECTTYPE* rec = static_cast<const OMX_CONFIG_RECTTYPE*>(apComponentConfigStructure);
       
   402 
       
   403 			err = iGraphicSurfaceSettings.iSurfaceConfig.SetExtent(TRect(TPoint(rec->nTop, rec->nLeft), TSize(rec->nWidth, rec->nHeight)));
       
   404 			if(err != KErrNone)
       
   405 				{
       
   406 				return OMX_ErrorUnsupportedSetting;
       
   407 				}
       
   408 						
       
   409 			break;
       
   410 			}
       
   411 		default:
       
   412 			{
       
   413 			return OMX_ErrorUnsupportedIndex;
       
   414 			}
       
   415 		}
       
   416 	
       
   417 	return OMX_ErrorNone;
       
   418 	}
       
   419 
       
   420 void COmxILGraphicSinkProcessingFunction::SetSharedChunkBufConfig(TMMSharedChunkBufConfig aSharedChunkBufConfig)
       
   421     {
       
   422     iGraphicSurfaceAccess->iSharedChunkBufConfig = aSharedChunkBufConfig;
       
   423     }
       
   424 
       
   425 void COmxILGraphicSinkProcessingFunction::GetSharedChunkMetadata(
       
   426     OMX_U32& aHandleId,
       
   427     OMX_U64& aThreadId) const
       
   428     {
       
   429     aHandleId = iGraphicSurfaceAccess->iSharedChunkHandleId;
       
   430     aThreadId = iGraphicSurfaceAccess->iSharedChunkThreadId;
       
   431     }
       
   432 
       
   433 /**
       
   434 This method is invoked whenever the component is requested to emtpy/display the contents of the buffers passed as function arguments.
       
   435 
       
   436 @param 	apBufferHeader A pointer to buffer header.
       
   437 @param  aDirection provides the direction either input or output. This can be used as a further check whether buffers received are valid or not.
       
   438 		
       
   439 @return OMX_ErrorNone if successful;
       
   440 		Any other OpenMAX IL wide error code;
       
   441 */
       
   442 OMX_ERRORTYPE
       
   443 COmxILGraphicSinkProcessingFunction::BufferIndication(
       
   444 	OMX_BUFFERHEADERTYPE* apBufferHeader,
       
   445 	OMX_DIRTYPE aDirection)
       
   446 	{
       
   447     if (aDirection != OMX_DirInput)
       
   448         {
       
   449         return OMX_ErrorBadParameter;
       
   450         }
       
   451     //The nTickCount is just internal here, stored temporarily. So it is count not time period.
       
   452     apBufferHeader->nTickCount = User::FastCounter();
       
   453     iBufferMutex.Wait();
       
   454     OMX_ERRORTYPE ret = OMX_ErrorNone;
       
   455     if (iBuffersToEmpty.Append(apBufferHeader) != KErrNone)
       
   456         {
       
   457         apBufferHeader->nTickCount = KNullTickCount;
       
   458         ret = OMX_ErrorInsufficientResources;
       
   459         }
       
   460     else if (iState != OMX_StateExecuting)
       
   461         {
       
   462         // If Component not in an executing state delay processing buffer
       
   463         ret = OMX_ErrorNone;
       
   464         }
       
   465     else if (iPFHelper->BufferIndication() != KErrNone)
       
   466         {
       
   467         apBufferHeader->nTickCount = KNullTickCount;
       
   468         ret = OMX_ErrorInsufficientResources;
       
   469         }
       
   470     iBufferMutex.Signal();
       
   471     return ret;
       
   472 	}
       
   473 
       
   474 /**
       
   475 This method is used to check whether the required buffer is held by the processing function or not.
       
   476 
       
   477 @param 	apBufferHeader A pointer to buffer header being searched.
       
   478 @param  aDirection provides the direction either input or output. This can be used as a further check whether buffers received are valid or not.
       
   479 		
       
   480 @return OMX_TRUE if find the buffer;
       
   481 		OMX_FALSE if fail to find the buffer;
       
   482 */
       
   483 OMX_BOOL
       
   484 COmxILGraphicSinkProcessingFunction::BufferRemovalIndication(
       
   485 	OMX_BUFFERHEADERTYPE* apBufferHeader,
       
   486 	OMX_DIRTYPE /* aDirection */)
       
   487 	{
       
   488     TBool headerDeletionResult = ETrue;
       
   489     
       
   490 	TInt headerIndexInArray = KErrNotFound;
       
   491 	iBufferMutex.Wait();
       
   492 	if (KErrNotFound !=
       
   493 		(headerIndexInArray =
       
   494 		 iBuffersToEmpty.Find(apBufferHeader)))
       
   495 		{
       
   496 		iBuffersToEmpty.Remove(headerIndexInArray);
       
   497 		}
       
   498 	else if(iBufferOnScreen == apBufferHeader)
       
   499 		{
       
   500 		iBufferOnScreen = NULL;
       
   501 		}
       
   502 	else
       
   503 		{
       
   504 		headerDeletionResult = EFalse;
       
   505 		}
       
   506 	iBufferMutex.Signal();
       
   507     return (headerDeletionResult ? OMX_TRUE : OMX_FALSE);
       
   508 	}
       
   509 
       
   510 /**
       
   511 This method creates COmxILMMBuffer class object. Also creates surface and allocates the chunks based on the number of buffers, 
       
   512 maps the surface in the given process. It also allocates the resources like creating the message queue and other necessary C 
       
   513 class objects. This method gets called when the component acts as buffer supplier.
       
   514 
       
   515 @param 	aPortSpecificBuffer gives the starting address of the specific buffer.
       
   516 @param  aPortPrivate gives the private data which is COmxILMMBuffer pointer in this case.
       
   517 		
       
   518 @leave  OMX_ErrorNone if successful;
       
   519 @leave  OMX_ErrorInsufficientResources if function returns KErrNoMemory;
       
   520 @leave  OMX_ErrorBadParameter if function returns errors except KErrNoMemory;
       
   521 @leave  Any other OpenMAX IL wide error code;
       
   522 */
       
   523 void COmxILGraphicSinkProcessingFunction::CreateBufferL(OMX_U8*& aPortSpecificBuffer, OMX_PTR& aPortPrivate, OMX_U32 aBufferCountActual)
       
   524 	{
       
   525 	iGraphicSurfaceAccess->CreateBufferL(aPortSpecificBuffer, aPortPrivate, aBufferCountActual);
       
   526 	}
       
   527 
       
   528 /**
       
   529 Destroy MM buffer, close surface, and deallocate other resources like message queue and C class objects. This is called when component
       
   530 acts as buffer supplier.
       
   531 @param  apPortPrivate gives the private data which is COmxILMMBuffer pointer in this case.
       
   532 */
       
   533 void COmxILGraphicSinkProcessingFunction::DestroyBuffer(OMX_PTR /*apPortPrivate*/)
       
   534 	{
       
   535 	iGraphicSurfaceAccess->iBufferIdGenerator--;
       
   536 	// to reset surface id in case client requests different settings.
       
   537 	if(iGraphicSurfaceAccess && iGraphicSurfaceAccess->iBufferIdGenerator == 0)
       
   538 		{
       
   539 		iGraphicSurfaceAccess->ResetSurfaceId();		
       
   540 		iGraphicSurfaceAccess->CloseChunk();
       
   541 		}
       
   542 	}
       
   543 
       
   544 /**
       
   545 Creates the surface by utilizing the buffers passed via application private data. It then maps the surface in the given process. 
       
   546 It also allocates the resources like creating the message queue and other necessary C class objects. This method gets called when 
       
   547 the component acts as non buffer supplier.
       
   548 
       
   549 @param apBuffer gives the starting address of the specific buffer.
       
   550 @param aAppPrivate provides the private data which is COmxILMMBuffer pointer in this case and holds details of buffers already allocated.
       
   551 @param aBufferCountActual The actual number of buffers.
       
   552 
       
   553 @leave  OMX_ErrorNone if successful;
       
   554 @leave  OMX_ErrorInsufficientResources if aPortPrivate is null or functions return KErrNoMemory;
       
   555 @leave	OMX_ErrorBadParameter if functions return errors except KErrNoMemory;
       
   556 @leave	Any other OpenMAX IL wide error code;
       
   557 */
       
   558 void COmxILGraphicSinkProcessingFunction::InitBufferL(OMX_U8* apBuffer, OMX_U32 aBufferCountActual)
       
   559 	{
       
   560 	iGraphicSurfaceAccess->InitBufferL(apBuffer, aBufferCountActual);
       
   561 	}
       
   562 
       
   563 /**
       
   564 Deallocate resources like message queue and C class objects. This is called when component acts as non buffer supplier.
       
   565 */
       
   566 void COmxILGraphicSinkProcessingFunction::DeInitBuffer()
       
   567 	{
       
   568 	// to reset surface id in case client requests different settings.
       
   569 	if(iGraphicSurfaceAccess)
       
   570 		{
       
   571 		iGraphicSurfaceAccess->ResetSurfaceId(); 
       
   572 		iGraphicSurfaceAccess->CloseChunk();
       
   573 		}
       
   574 	}
       
   575 
       
   576 /**
       
   577 Initialise surface attribute structure.
       
   578 */	
       
   579 void COmxILGraphicSinkProcessingFunction::InitSurfaceAttributes()
       
   580 	{
       
   581 	RSurfaceManager::TSurfaceCreationAttributes* attr = &iGraphicSurfaceSettings.iSurfaceAttributes;
       
   582 	
       
   583 	attr->iAlignment = KRefGfxAlignment;
       
   584 	attr->iContiguous = KRefGfxContiguous;;
       
   585 	attr->iCacheAttrib = RSurfaceManager::ENotCached;
       
   586 	attr->iMappable = ETrue;
       
   587 	}
       
   588 
       
   589 TUidPixelFormat COmxILGraphicSinkProcessingFunction::ConvertPixelFormat(OMX_COLOR_FORMATTYPE aColorFormat)
       
   590 	{
       
   591 	switch(aColorFormat)
       
   592 		{
       
   593 		// OMX "Planar" formats not currently supported by GraphicSink since data comes in more than one buffer.
       
   594 		// "PackedPlanar" formats can be added easily provided the GCE backend supports them.
       
   595 
       
   596 		case OMX_COLOR_Format16bitRGB565:
       
   597 			return EUidPixelFormatRGB_565;
       
   598 
       
   599 		case OMX_COLOR_Format32bitARGB8888:
       
   600 			return EUidPixelFormatARGB_8888;
       
   601 
       
   602 		case OMX_COLOR_FormatYCrYCb:
       
   603 			return EUidPixelFormatYUV_422Reversed;
       
   604 		
       
   605 		case OMX_COLOR_FormatCbYCrY:
       
   606 			return EUidPixelFormatYUV_422Interleaved;
       
   607 
       
   608 		// Need to map color format to Symbian pixel format.
       
   609 		default:
       
   610 			{
       
   611 			return EUidPixelFormatUnknown;
       
   612 			}
       
   613 		}
       
   614 	}
       
   615 
       
   616 void COmxILGraphicSinkProcessingFunction::WaitForTransitionToPauseToFinish()
       
   617     {
       
   618     if(RThread().Id() == iOwnerThreadId)
       
   619         {
       
   620         //if the owner thread is the same thread as the one created the active objects in this processing function
       
   621         //then we can wait by using CActiveSchedulerWait
       
   622         DEBUG_PRINTF(_L8("GraphicSinkProcessingFunction::WaitForTransitionToPauseToFinish - blocking transition to pause with active scheduler wait now"));
       
   623         iTransitionToPauseWait->Start();
       
   624         }
       
   625     else
       
   626         {
       
   627         //if this is a thread different from the creator thread then semaphore is needed to block this thread until the transition
       
   628         //to paused state completes
       
   629         DEBUG_PRINTF(_L8("GraphicSinkProcessingFunction::WaitForTransitionToPauseToFinish - blocking thread with semaphore now"));
       
   630         iTransitionToPauseWaitSemaphore.Wait();
       
   631         }
       
   632     }
       
   633 
       
   634 void COmxILGraphicSinkProcessingFunction::TransitionToPauseFinished()
       
   635     {
       
   636     if(iTransitionToPauseWait->IsStarted())
       
   637         {
       
   638         DEBUG_PRINTF(_L8("GraphicSinkProcessingFunction::TransitionToPauseFinished - unblocking transition to pause (active scheduler wait) now"));
       
   639         iTransitionToPauseWait->AsyncStop();
       
   640         }
       
   641     else
       
   642         {
       
   643         DEBUG_PRINTF(_L8("GraphicSinkProcessingFunction::TransitionToPauseFinished - unblocking transition to pause (semaphore) now"));
       
   644         iTransitionToPauseWaitSemaphore.Signal();
       
   645         }
       
   646     }
       
   647 
       
   648 COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess* COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::NewL(COmxILGraphicSinkProcessingFunction& aParent)
       
   649 	{
       
   650 	return new (ELeave) CGraphicSurfaceAccess(aParent);
       
   651 	}
       
   652 
       
   653 COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::CGraphicSurfaceAccess(COmxILGraphicSinkProcessingFunction& aParent)
       
   654 : CActive(EPriorityStandard),
       
   655   iIsLocalChunk(ETrue),
       
   656   iParent(aParent)
       
   657 	{
       
   658 	CActiveScheduler::Add(this);
       
   659 	iSurfaceId = TSurfaceId::CreateNullId();
       
   660 	iOffsetArray.Reset();
       
   661 	}
       
   662 
       
   663 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::CloseChunk()
       
   664     {
       
   665     if(iChunk.Handle())
       
   666         {
       
   667         iChunk.Close();
       
   668         }
       
   669     }
       
   670 
       
   671 COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::~CGraphicSurfaceAccess()
       
   672 	{
       
   673 	Cancel();
       
   674 	
       
   675 	CloseChunk();
       
   676 
       
   677 	if (!iSurfaceId.IsNull())
       
   678 	    {
       
   679 	    iParent.SurfaceManager().CloseSurface(iSurfaceId);	// ignore the error
       
   680 	    }
       
   681     #ifdef ILCOMPONENTCONFORMANCE
       
   682 	iArrayOffsets.Close();
       
   683     #endif
       
   684 
       
   685 	iOffsetArray.Close();
       
   686 	iSurfaceUpdateSession.Close();
       
   687 
       
   688 	}
       
   689 
       
   690 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::RunL()
       
   691 	{
       
   692 	// The buffer is not on the list implies that they have already been flushed/spotted 
       
   693 	// via BufferFlushingIndication/BufferRemovalIndication
       
   694 	iParent.iBufferMutex.Wait();
       
   695 	TInt index = iParent.BuffersToEmpty().Find(iCurrentBuffer);
       
   696 	if (KErrNotFound != index)
       
   697 		{
       
   698 		switch(iStatus.Int())
       
   699 			{
       
   700 			case KErrNone: 
       
   701 				{
       
   702 				// Consumed all data completely and setting nFilledLen to zero.
       
   703 				iCurrentBuffer->nFilledLen = 0;
       
   704 				break;
       
   705 				}
       
   706 			case KErrCancel:
       
   707 			default:
       
   708 				{
       
   709 				// Leave actual value of iCurrentBuffer->nFilledLen
       
   710 				DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::RunL() err = %d"), iStatus.Int());
       
   711 				}
       
   712 			};
       
   713 
       
   714 		if(iStatus.Int() != KErrNone)
       
   715 		    {
       
   716 		    iCurrentBuffer->nTickCount = KNullTickCount;
       
   717 		    }
       
   718 		else
       
   719 			{
       
   720 			TUint32 currentTickCount = User::FastCounter();
       
   721 
       
   722 			// On some hardware boards, tick count decrements as time increases so
       
   723 			// need to check which way the counter is going
       
   724 			if (currentTickCount >= iCurrentBuffer->nTickCount)
       
   725 				{
       
   726 				iCurrentBuffer->nTickCount = (currentTickCount - iCurrentBuffer->nTickCount) / iParent.GetFastCounterFrequency();
       
   727 				}
       
   728 			else
       
   729 				{
       
   730 				iCurrentBuffer->nTickCount = (iCurrentBuffer->nTickCount - currentTickCount) / iParent.GetFastCounterFrequency();
       
   731 				}
       
   732 			}
       
   733 
       
   734         
       
   735         if(iCurrentBuffer->nFlags & OMX_BUFFERFLAG_EOS)
       
   736             {
       
   737             iParent.GetCallbacks().EventNotification(OMX_EventBufferFlag, iCurrentBuffer->nInputPortIndex, iCurrentBuffer->nFlags, NULL);
       
   738             }
       
   739 
       
   740 		iCurrentBuffer->nFilledLen = 0;
       
   741 		iCurrentBuffer->nFlags = 0;
       
   742 		iCurrentBuffer->nOffset = 0;
       
   743 		iCurrentBuffer->nTimeStamp = 0;
       
   744 
       
   745 		// now sending back to framework..
       
   746 		if(iParent.iBufferOnScreen != NULL)
       
   747 			{
       
   748 			// TODO error handling
       
   749 			iParent.GetCallbacks().BufferDoneNotification(iParent.iBufferOnScreen, iParent.iBufferOnScreen->nInputPortIndex,OMX_DirInput);
       
   750 			}
       
   751 		iParent.iBufferOnScreen = iCurrentBuffer;
       
   752 
       
   753 		iParent.BuffersToEmpty().Remove(index);
       
   754 		iCurrentBuffer = NULL;
       
   755 		
       
   756 		// check if any more buffers to be consumed..
       
   757 		if (ProcessNextBuffer() != KErrNone)
       
   758 			{
       
   759 			iParent.GetCallbacks().ErrorEventNotification(OMX_ErrorInsufficientResources);
       
   760 			}
       
   761 		}
       
   762 	iParent.iBufferMutex.Signal();
       
   763 	}
       
   764 
       
   765 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::CreateBufferL(OMX_U8*& aPortSpecificBuffer, OMX_PTR& aPortPrivate, OMX_U32 aBufferCountActual)
       
   766 	{
       
   767 	if(iSurfaceId.IsNull())
       
   768 		{
       
   769 		// race condition on nBufferCountActual
       
   770 		if(aBufferCountActual != iParent.GraphicSurfaceSettings().iSurfaceAttributes.iBuffers)
       
   771 		    {
       
   772 		    iParent.GraphicSurfaceSettings().iSurfaceAttributes.iBuffers = aBufferCountActual;
       
   773 		    }
       
   774 
       
   775 		User::LeaveIfError(iParent.SurfaceManager().CreateSurface(iParent.GraphicSurfaceSettings().iSurfaceAttributesBuf, iSurfaceId));
       
   776 		
       
   777 		RChunk chunk;
       
   778 		CleanupClosePushL(chunk);
       
   779 		User::LeaveIfError(iParent.SurfaceManager().MapSurface(iSurfaceId, chunk));
       
   780 		
       
   781 		//We need to change the chunk handle to be shared by the whole process.
       
   782 		RThread thread;
       
   783 		CleanupClosePushL(thread);
       
   784         iChunk.SetHandle(chunk.Handle());
       
   785         User::LeaveIfError(iChunk.Duplicate(thread));
       
   786 		CleanupStack::PopAndDestroy(2, &chunk);
       
   787 
       
   788         // for SetConfig(OMX_SYMBIAN_CONFIG_SHARED_CHUNK_METADATA)
       
   789         iSharedChunkHandleId = iChunk.Handle();
       
   790         iSharedChunkThreadId = RThread().Id().Id();
       
   791 
       
   792 		switch(iParent.iGraphicSurfaceSettings.iSurfaceAttributes.iPixelFormat)
       
   793 			{
       
   794 		case EUidPixelFormatYUV_422Reversed:
       
   795 			{
       
   796 			// fill buffer 0 with black
       
   797 			TUint32* data = reinterpret_cast<TUint32*>(iChunk.Base());
       
   798 			TInt numPixelPairs = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iStride * iParent.GraphicSurfaceSettings().iSurfaceAttributes.iSize.iHeight / 4;
       
   799 			for(TInt offset = 0; offset < numPixelPairs; offset++)
       
   800 				{
       
   801 				data[offset] = 0x80108010;
       
   802 				}
       
   803 			}
       
   804 			break;
       
   805 		case EUidPixelFormatYUV_422Interleaved:
       
   806 			{
       
   807 			// fill buffer 0 with black
       
   808 			TUint32* data = reinterpret_cast<TUint32*>(iChunk.Base());
       
   809 			TInt numPixelPairs = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iStride * iParent.GraphicSurfaceSettings().iSurfaceAttributes.iSize.iHeight / 4;
       
   810 			for(TInt offset = 0; offset < numPixelPairs; offset++)
       
   811 				{
       
   812 				data[offset] = 0x10801080;
       
   813 				}
       
   814 			}
       
   815 			break;
       
   816 		case EUidPixelFormatRGB_565:
       
   817 		case EUidPixelFormatARGB_8888:
       
   818 			Mem::FillZ(iChunk.Base(), iParent.GraphicSurfaceSettings().iSurfaceAttributes.iStride * iParent.GraphicSurfaceSettings().iSurfaceAttributes.iSize.iHeight);
       
   819 			break;
       
   820 		default:
       
   821 #ifdef _DEBUG
       
   822 		    // Panic in a debug build. It will make people think about how the error should be handled.
       
   823 		    Panic(EUndefinedPixelFormat);
       
   824 #endif
       
   825 			break;
       
   826 			}
       
   827 		
       
   828 		// Now, GFX needs to make sure that TSurfaceConfiguration has valid surface id
       
   829 		// so that IL Client can use RSurfaceManager::SetBackroundSurface()
       
   830 		User::LeaveIfError(iParent.GraphicSurfaceSettings().iSurfaceConfig.SetSurfaceId(iSurfaceId));
       
   831 		iParent.iCallbacks.EventNotification(OMX_EventPortSettingsChanged, OMX_NokiaIndexParamGraphicSurfaceConfig, 0, NULL);
       
   832 		
       
   833 		chunk.Close();
       
   834         #ifdef ILCOMPONENTCONFORMANCE
       
   835 		iIsBufferSupplier = ETrue;
       
   836         #endif
       
   837 		}
       
   838 	
       
   839 	ASSERT(iChunk.Handle());
       
   840 	
       
   841 
       
   842 	RSurfaceManager::TInfoBuf surfaceInfoBuf;
       
   843 	RSurfaceManager::TSurfaceInfoV01& surfaceInfo (surfaceInfoBuf());
       
   844 	User::LeaveIfError(iParent.SurfaceManager().SurfaceInfo(iSurfaceId, surfaceInfoBuf));
       
   845     for (TInt i = 0 ; i < surfaceInfo.iBuffers ; i++)
       
   846         {
       
   847         TInt offset = 0;
       
   848         User::LeaveIfError(iParent.SurfaceManager().GetBufferOffset(iSurfaceId, i, offset));
       
   849 
       
   850         if(iBufferIdGenerator == 0)
       
   851             {
       
   852             iOffsetArray.AppendL(offset);
       
   853             }
       
   854         }
       
   855 
       
   856     aPortSpecificBuffer = iChunk.Base() + iOffsetArray[iBufferIdGenerator];
       
   857     aPortPrivate = NULL;
       
   858 	
       
   859 	iBufferIdGenerator++;
       
   860 	}
       
   861 
       
   862 
       
   863 #ifndef ILCOMPONENTCONFORMANCE
       
   864 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL(OMX_U8* apBuffer, OMX_U32 aBufferCountActual)
       
   865 {
       
   866     // open chunk at the beginning
       
   867     if(iChunk.Handle() == NULL)
       
   868         {
       
   869         // only support chunk extension otherwise error
       
   870         if(iSharedChunkThreadId == NULL || iSharedChunkHandleId == NULL)
       
   871             {
       
   872             DEBUG_PRINTF(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL handles not valie"));
       
   873             User::Leave(KErrBadHandle);
       
   874             }
       
   875         
       
   876         // race condition on nBufferCountActual
       
   877         if(aBufferCountActual != iParent.GraphicSurfaceSettings().iSurfaceAttributes.iBuffers)
       
   878             {
       
   879             iParent.GraphicSurfaceSettings().iSurfaceAttributes.iBuffers = aBufferCountActual;
       
   880             }
       
   881         
       
   882         DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL iSharedChunkThreadId = %Lu"), iSharedChunkThreadId);
       
   883         DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL iSharedChunkHandleId = %Lu"), iSharedChunkHandleId);
       
   884 
       
   885         RThread chunkOwnerThread;
       
   886         User::LeaveIfError(chunkOwnerThread.Open(TThreadId(iSharedChunkThreadId)));
       
   887         CleanupClosePushL(chunkOwnerThread);
       
   888                 
       
   889         iChunk.SetHandle(iSharedChunkHandleId);
       
   890         User::LeaveIfError(iChunk.Duplicate(chunkOwnerThread));
       
   891         CleanupStack::PopAndDestroy(&chunkOwnerThread);
       
   892         }
       
   893     
       
   894     // differ creating surface id with chunk at last call
       
   895     if(iSurfaceId.IsNull() && (((aBufferCountActual - 1) == iOffsetArray.Count())))
       
   896         {    
       
   897         // offsetBetweenBuffer & iBufferSizeInBytes in chunkconfig must be same
       
   898         TInt offsetBetweenBuffer;
       
   899         if(aBufferCountActual == 1) // if only one buffer is used, use iBufferSizeInBytes instead..
       
   900             {
       
   901             offsetBetweenBuffer = iSharedChunkBufConfig.iBufferSizeInBytes;
       
   902             }
       
   903         else
       
   904             {
       
   905             offsetBetweenBuffer = iOffsetArray[1] - iOffsetArray[0];
       
   906             }
       
   907                   
       
   908         DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL offsetBetweenBuffer = %d"), offsetBetweenBuffer);
       
   909         DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL iBufferSizeInBytes = %d"), iSharedChunkBufConfig.iBufferSizeInBytes);
       
   910 
       
   911         // update surface attributes
       
   912         iParent.GraphicSurfaceSettings().iSurfaceAttributes.iOffsetBetweenBuffers = offsetBetweenBuffer;
       
   913             
       
   914         TInt err = KErrGeneral;
       
   915         // create surface id with chunk
       
   916         err = iParent.SurfaceManager().CreateSurface(iParent.GraphicSurfaceSettings().iSurfaceAttributesBuf, iSurfaceId, iChunk);
       
   917         if(err != KErrNone)
       
   918             {
       
   919             DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL createsurface err = %d"), err);
       
   920             User::Leave(err);
       
   921             }
       
   922 
       
   923         // Now, GFX needs to make sure that TSurfaceConfiguration has valid surface id
       
   924         err = iParent.GraphicSurfaceSettings().iSurfaceConfig.SetSurfaceId(iSurfaceId);	   
       
   925         if(err != KErrNone)
       
   926             {
       
   927             DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL SetSurfaceId err = %d"), err);
       
   928             User::Leave(err);
       
   929             }
       
   930       
       
   931         RSurfaceManager::TInfoBuf surfaceInfoBuf;
       
   932         RSurfaceManager::TSurfaceInfoV01& surfaceInfo (surfaceInfoBuf());
       
   933         surfaceInfo.iSize = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iSize;
       
   934         surfaceInfo.iBuffers = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iBuffers;
       
   935         surfaceInfo.iPixelFormat = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iPixelFormat;
       
   936         surfaceInfo.iStride = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iStride;
       
   937         surfaceInfo.iContiguous = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iContiguous;
       
   938         surfaceInfo.iCacheAttrib = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iCacheAttrib;
       
   939         surfaceInfo.iMappable = iParent.GraphicSurfaceSettings().iSurfaceAttributes.iMappable;
       
   940         
       
   941         err = iParent.SurfaceManager().SurfaceInfo(iSurfaceId, surfaceInfoBuf);
       
   942         if(err != KErrNone)
       
   943             {
       
   944             DEBUG_PRINTF2(_L8("COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL SurfaceInfo err = %d"), err);  
       
   945             User::Leave(err);
       
   946             }
       
   947 
       
   948         // everything is fine and now ready to rock and roll...
       
   949         iParent.iCallbacks.EventNotification(OMX_EventPortSettingsChanged, OMX_NokiaIndexParamGraphicSurfaceConfig, 0, NULL);
       
   950         } 
       
   951     
       
   952     // save offsets
       
   953     TInt offset = apBuffer - iChunk.Base();
       
   954     iOffsetArray.AppendL(offset);
       
   955 	}
       
   956 
       
   957 #else 
       
   958 
       
   959 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::InitBufferL(OMX_U8* /*apBuffer*/, OMX_U32 aBufferCountActual)
       
   960     {
       
   961     if(iSurfaceId.IsNull())
       
   962         {
       
   963         User::LeaveIfError(iParent.SurfaceManager().CreateSurface(iParent.GraphicSurfaceSettings().iSurfaceAttributesBuf, iSurfaceId));
       
   964         
       
   965         RChunk chunk;
       
   966         User::LeaveIfError(iParent.SurfaceManager().MapSurface(iSurfaceId, chunk));
       
   967         CleanupClosePushL(chunk);
       
   968         
       
   969         //We need to change the chunk handle to be shared by the whole process.
       
   970         RThread thread;
       
   971         CleanupClosePushL(thread);
       
   972         iChunk.SetHandle(chunk.Handle());
       
   973         User::LeaveIfError(iChunk.Duplicate(thread));
       
   974         CleanupStack::PopAndDestroy(2, &chunk);
       
   975             
       
   976         // Now, GFX needs to make sure that TSurfaceConfiguration has valid surface id
       
   977         // so that IL Client can use RSurfaceManager::SetBackroundSurface()
       
   978         User::LeaveIfError(iParent.GraphicSurfaceSettings().iSurfaceConfig.SetSurfaceId(iSurfaceId));
       
   979         iParent.iCallbacks.EventNotification(OMX_EventPortSettingsChanged, OMX_NokiaIndexParamGraphicSurfaceConfig, 0, NULL);
       
   980         
       
   981         iIsBufferSupplier = EFalse;
       
   982         
       
   983         for(TInt i = 0 ; i < aBufferCountActual ; i++)
       
   984             {
       
   985             TInt offset = 0;
       
   986             User::LeaveIfError(iParent.SurfaceManager().GetBufferOffset(iSurfaceId, i, offset));
       
   987             iArrayOffsets.AppendL(offset);
       
   988             }   
       
   989         }
       
   990 
       
   991     }
       
   992 #endif //ILCOMPONENTCONFORMANCE
       
   993 
       
   994 TInt COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::ProcessNextBuffer()
       
   995     {
       
   996     __ASSERT_DEBUG(iParent.iBufferMutex.IsHeld(), User::Invariant());
       
   997     
       
   998     TInt err = KErrNone;
       
   999     
       
  1000     if ((iParent.BuffersToEmpty().Count()>0) && !IsActive() && iParent.State() == OMX_StateExecuting)
       
  1001         {
       
  1002         iCurrentBuffer = iParent.BuffersToEmpty()[0];
       
  1003         TInt bufferId = KErrNotFound;
       
  1004 
       
  1005         if (iCurrentBuffer->nFilledLen == 0)
       
  1006             {
       
  1007             // Nothing in the buffer so no need to display it. The buffer might have a flag
       
  1008             // that needs processing though. Self complete to keep the state machine running.
       
  1009             iStatus = KRequestPending;
       
  1010             SetActive();
       
  1011             TRequestStatus* status = &iStatus;
       
  1012             User::RequestComplete(status, KErrNone);
       
  1013             return KErrNone;
       
  1014             }
       
  1015 
       
  1016 #ifdef ILCOMPONENTCONFORMANCE
       
  1017         if (iIsBufferSupplier)
       
  1018             {
       
  1019 #endif
       
  1020 			TInt offset = iCurrentBuffer->pBuffer - iChunk.Base();
       
  1021 			bufferId = iOffsetArray.Find(offset);
       
  1022 #ifdef ILCOMPONENTCONFORMANCE
       
  1023             }
       
  1024         else
       
  1025             {
       
  1026             // Copy data from IL Conformance Suite in to Chunk address at specific address.
       
  1027             TPtr8 ptr(iChunk.Base(),iCurrentBuffer->nFilledLen ,iCurrentBuffer->nAllocLen);
       
  1028             ptr.Copy(iCurrentBuffer->pBuffer + iCurrentBuffer->nOffset, iCurrentBuffer->nFilledLen);
       
  1029             // isn't nOffset likely going to be 0? better to map buffer pointer to buffer id directly
       
  1030             bufferId = iArrayOffsets.Find(iCurrentBuffer->nOffset);
       
  1031             // nOffset is not ideal for identifying buffer area since it's likely each buffer header
       
  1032             // will have a unique pBuffer and nOffset == 0. We could calculate buffer ID by finding
       
  1033             // the buffer header on the buffer header array in the port, but this isn't how bufferID
       
  1034             // is calculated in the rest of the code. (we could just store the buffer ID on the
       
  1035             // pInputPortPrivate but we have a habit of trying to export GS specific info into COmxILMMBuffer)
       
  1036             __ASSERT_ALWAYS(bufferId == 0, User::Invariant());
       
  1037             }
       
  1038 #endif  
       
  1039 
       
  1040         if(KErrNotFound == bufferId)
       
  1041             {
       
  1042             // An error here means that the buffer will not be displayed and RunL() will not be
       
  1043             // invoked. However the buffer might have a flag that needs processing. Self complete
       
  1044             // to keep the state machine running.
       
  1045             iStatus = KRequestPending;
       
  1046             SetActive();
       
  1047             TRequestStatus* status = &iStatus;
       
  1048             User::RequestComplete(status, KErrNotFound);
       
  1049             return KErrNotFound;
       
  1050             }
       
  1051 
       
  1052 		// due to COmxMMILBuffer dependency. to be removed 
       
  1053         if (iIsLocalChunk)
       
  1054             {
       
  1055             // copy data into local chunk
       
  1056             TPtr8 ptr(iCurrentBuffer->pBuffer,iCurrentBuffer->nFilledLen ,iCurrentBuffer->nAllocLen);
       
  1057             ptr.Copy(iChunk.Base() + offset, iCurrentBuffer->nFilledLen);
       
  1058             }
       
  1059 
       
  1060         iSurfaceUpdateSession.NotifyWhenDisplayed(iStatus, iTimeStamp);
       
  1061         SetActive();
       
  1062 
       
  1063         err = iSurfaceUpdateSession.SubmitUpdate(KAllScreens, iSurfaceId, bufferId);
       
  1064         if(err)
       
  1065             {
       
  1066             // An error here means that the buffer will not be displayed and RunL() will not be
       
  1067             // invoked. However the buffer might have a flag that needs processing. Self complete
       
  1068             // to keep the state machine running.
       
  1069             iStatus = KRequestPending;
       
  1070             SetActive();
       
  1071             TRequestStatus* status = &iStatus;
       
  1072             User::RequestComplete(status, err);
       
  1073             }
       
  1074         }
       
  1075     
       
  1076     return err;
       
  1077     }
       
  1078 
       
  1079 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::DoCancel()
       
  1080 	{
       
  1081     if (iSurfaceUpdateSession.Handle() != KNullHandle)
       
  1082         {
       
  1083         iSurfaceUpdateSession.CancelAllUpdateNotifications();
       
  1084         }
       
  1085     
       
  1086 	iCurrentBuffer = NULL;
       
  1087 	}
       
  1088 
       
  1089 TInt COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::OpenDevice()
       
  1090     {
       
  1091     TInt err = iSurfaceUpdateSession.Connect(KSurfaceUpdateNumOfMessageSlots);
       
  1092     
       
  1093     if (err == KErrNotFound || err != KErrNone)
       
  1094         {
       
  1095 #ifdef __WINSCW__
       
  1096         DEBUG_PRINTF(_L8("Make sure SYMBIAN_GRAPHICS_USE_GCE ON is specified in epoc.ini"));
       
  1097 #else
       
  1098         DEBUG_PRINTF(_L8("Make sure SYMBIAN_GRAPHICS_USE_GCE is defined in ROM build"));
       
  1099 #endif
       
  1100         }
       
  1101     
       
  1102     return err;
       
  1103     }
       
  1104 
       
  1105 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::CloseDevice()
       
  1106     {
       
  1107     iSurfaceUpdateSession.CancelAllUpdateNotifications();
       
  1108     
       
  1109     if (!iSurfaceId.IsNull())
       
  1110         {
       
  1111         iParent.SurfaceManager().CloseSurface(iSurfaceId);  // ignore the error
       
  1112         }
       
  1113     
       
  1114     iSurfaceUpdateSession.Close();
       
  1115     // RSurface::Open() happened in context of caller.
       
  1116     iParent.SurfaceManager().Close();
       
  1117 
       
  1118     iOffsetArray.Reset();
       
  1119     }
       
  1120 
       
  1121 TInt COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::Execute()
       
  1122 	{
       
  1123 	iParent.SetState(OMX_StateExecuting);
       
  1124 	iFirstFrameDisplayed = EFalse;
       
  1125 	TInt r = ProcessNextBuffer();
       
  1126 	return r;
       
  1127 	}
       
  1128 
       
  1129 TInt COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::Pause()
       
  1130 	{
       
  1131 	iParent.SetState(OMX_StatePause);
       
  1132 	iFirstFrameDisplayed = EFalse;
       
  1133 	Cancel();
       
  1134 	iParent.TransitionToPauseFinished();
       
  1135 	return KErrNone;
       
  1136 	}
       
  1137 
       
  1138 TInt COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::Stop()
       
  1139 	{
       
  1140 	if(iParent.State() == OMX_StateExecuting || iParent.State() == OMX_StatePause)
       
  1141 		{
       
  1142 		// Cancel and flush the device driver
       
  1143 		Cancel();
       
  1144 		iParent.SetState(OMX_StateIdle);
       
  1145 		iFirstFrameDisplayed = EFalse;
       
  1146 		}
       
  1147 	return KErrNone;
       
  1148 	}
       
  1149 
       
  1150 void COmxILGraphicSinkProcessingFunction::CGraphicSurfaceAccess::ResetSurfaceId()
       
  1151 	{
       
  1152 	iSurfaceId = TSurfaceId::CreateNullId();
       
  1153 	}
       
  1154 
       
  1155 COmxILGraphicSinkProcessingFunction::CPFHelper* COmxILGraphicSinkProcessingFunction::CPFHelper::NewL(COmxILGraphicSinkProcessingFunction& aParent, CGraphicSurfaceAccess& aGraphicSurfaceAccess)
       
  1156 	{
       
  1157 	CPFHelper* self = new (ELeave) CPFHelper(aParent, aGraphicSurfaceAccess);
       
  1158 	CleanupStack::PushL(self);
       
  1159 	self->ConstructL();
       
  1160 	CleanupStack::Pop(self);
       
  1161 	return self;
       
  1162 	}
       
  1163 
       
  1164 COmxILGraphicSinkProcessingFunction::CPFHelper::CPFHelper(COmxILGraphicSinkProcessingFunction& aParent, CGraphicSurfaceAccess& aSurfaceAccess)
       
  1165 : CActive(EPriorityUserInput),
       
  1166   iParent(aParent),
       
  1167   iGraphicSurfaceAccess(aSurfaceAccess)
       
  1168 	{
       
  1169 	CActiveScheduler::Add(this);
       
  1170 	}
       
  1171 	
       
  1172 void COmxILGraphicSinkProcessingFunction::CPFHelper::ConstructL()
       
  1173 	{
       
  1174 	User::LeaveIfError(iMsgQueue.CreateLocal(KMaxMsgQueueEntries));
       
  1175 	SetActive();
       
  1176 	iMsgQueue.NotifyDataAvailable(iStatus);
       
  1177 	}
       
  1178 	
       
  1179 COmxILGraphicSinkProcessingFunction::CPFHelper::~CPFHelper()
       
  1180 	{
       
  1181 	Cancel(); 
       
  1182 	iMsgQueue.Close();
       
  1183 	}
       
  1184 
       
  1185 void COmxILGraphicSinkProcessingFunction::CPFHelper::RunL()
       
  1186 	{
       
  1187 	iParent.iBufferMutex.Wait();
       
  1188 	if (ProcessQueue() != KErrNone)
       
  1189 		{
       
  1190 		iParent.GetCallbacks().ErrorEventNotification(OMX_ErrorInsufficientResources);
       
  1191 		}
       
  1192 	
       
  1193 	// setup for next callbacks		
       
  1194 	SetActive();
       
  1195 	iMsgQueue.NotifyDataAvailable(iStatus);
       
  1196 	iParent.iBufferMutex.Signal();
       
  1197 	}
       
  1198 
       
  1199 void COmxILGraphicSinkProcessingFunction::CPFHelper::DoCancel()
       
  1200 	{
       
  1201 	if (iMsgQueue.Handle())
       
  1202 		{
       
  1203 		ProcessQueue();	// TODO: ignore the error?
       
  1204 		iMsgQueue.CancelDataAvailable();
       
  1205 		}
       
  1206 	}
       
  1207 
       
  1208 TInt COmxILGraphicSinkProcessingFunction::CPFHelper::ProcessQueue()
       
  1209 	{
       
  1210 	TMessageType msg;
       
  1211 	TInt err = iMsgQueue.Receive(msg);
       
  1212 	while (err == KErrNone)
       
  1213 		{
       
  1214 		switch (msg)
       
  1215 			{
       
  1216 			case EOpenDevice:
       
  1217 			    {
       
  1218 			    err = iGraphicSurfaceAccess.OpenDevice();
       
  1219 			    break;
       
  1220 			    }
       
  1221 			case ECloseDevice:
       
  1222                 {
       
  1223                 iGraphicSurfaceAccess.CloseDevice();
       
  1224                 break;
       
  1225                 }
       
  1226 			
       
  1227 			case EExecuteCommand:
       
  1228 				{
       
  1229 				err = iGraphicSurfaceAccess.Execute();	
       
  1230 				break;
       
  1231 				}				
       
  1232 
       
  1233 			case EStopCommand:
       
  1234 				{
       
  1235 				err = iGraphicSurfaceAccess.Stop();	
       
  1236 				break;
       
  1237 				}
       
  1238 				
       
  1239 			case EPauseCommand:
       
  1240 				{
       
  1241 				err = iGraphicSurfaceAccess.Pause();
       
  1242 				break;
       
  1243 				}
       
  1244 				
       
  1245 			case EBufferIndication:
       
  1246 				{
       
  1247 				// Add buffer to list waiting to process.
       
  1248 				// While we could send zero length buffers straight back, this would cause a
       
  1249 				// problem if that buffer has a flag on it that needs processing. So we still
       
  1250 				// pass them on and the graphics surface access code will not display them.
       
  1251 				if (iParent.State() == OMX_StateExecuting || iParent.State() == OMX_StatePause)
       
  1252 					{
       
  1253 					err = iGraphicSurfaceAccess.ProcessNextBuffer();
       
  1254 					}
       
  1255 				break;
       
  1256 				}
       
  1257 			default:
       
  1258 				{
       
  1259 				DEBUG_PRINTF2(_L8("\nMsqQue >> %d"),msg);
       
  1260 				break;
       
  1261 				}					
       
  1262 			}
       
  1263 		
       
  1264 		if (err)
       
  1265 			{
       
  1266 			break;
       
  1267 			}
       
  1268 		
       
  1269 		err = iMsgQueue.Receive(msg);
       
  1270 		}
       
  1271 	
       
  1272     if ( err  == KErrUnderflow)
       
  1273         {
       
  1274         err = KErrNone;
       
  1275         }
       
  1276     
       
  1277 	return err;
       
  1278 	}
       
  1279 
       
  1280 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::OpenDevice()
       
  1281     {
       
  1282     TMessageType message;
       
  1283     message = EOpenDevice;
       
  1284     return ConvertError(iMsgQueue.Send(message));
       
  1285     }
       
  1286 
       
  1287 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::CloseDevice()
       
  1288     {
       
  1289     TMessageType message;
       
  1290     message = ECloseDevice;
       
  1291     return ConvertError(iMsgQueue.Send(message));
       
  1292     }
       
  1293 
       
  1294 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::ExecuteAsync()
       
  1295 	{
       
  1296 	TMessageType message;
       
  1297 	message = EExecuteCommand;
       
  1298     return ConvertError(iMsgQueue.Send(message));
       
  1299 	}
       
  1300 	
       
  1301 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::StopAsync()
       
  1302 	{
       
  1303 	TMessageType message;
       
  1304 	message = EStopCommand;
       
  1305     return ConvertError(iMsgQueue.Send(message));
       
  1306 	}
       
  1307 
       
  1308 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::StopSync()
       
  1309 	{
       
  1310 	// Cancel to process the existing queue before handling this command
       
  1311 	if (IsActive())
       
  1312 	    {
       
  1313 	    Cancel();
       
  1314 	    }
       
  1315 	
       
  1316 	TInt err = iGraphicSurfaceAccess.Stop();
       
  1317 	
       
  1318 	// setup for next callbacks		
       
  1319 	SetActive();
       
  1320 	iMsgQueue.NotifyDataAvailable(iStatus);
       
  1321 	
       
  1322     return ConvertError(err);
       
  1323 	}
       
  1324 
       
  1325 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::Pause()
       
  1326     {
       
  1327     TMessageType message;
       
  1328     message = EPauseCommand;
       
  1329     return ConvertError(iMsgQueue.Send(message));
       
  1330     }
       
  1331 	
       
  1332 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::BufferIndication()
       
  1333 	{
       
  1334 	TMessageType message;
       
  1335 	message = EBufferIndication;
       
  1336     return ConvertError(iMsgQueue.Send(message));
       
  1337 	}
       
  1338 
       
  1339 OMX_ERRORTYPE COmxILGraphicSinkProcessingFunction::CPFHelper::ConvertError(TInt aError)
       
  1340     {
       
  1341     if(aError == KErrNone)
       
  1342         {
       
  1343         return OMX_ErrorNone;
       
  1344         }
       
  1345     else if(aError == KErrOverflow)
       
  1346         {
       
  1347         return OMX_ErrorInsufficientResources; 
       
  1348         }
       
  1349 
       
  1350     // default
       
  1351     return OMX_ErrorUndefined;
       
  1352     }