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