mmdevicefw/mdfunittest/codecapi/omx/pcmcodec/src/OmxPCMCodec.cpp
changeset 0 40261b775718
child 38 4269ca484c7b
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32debug.h>
       
    17 #include <stdio.h>
       
    18 #include <string.h>
       
    19 #include <stdlib.h>
       
    20 #include <openmax/il/khronos/v1_x/OMX_Core.h>
       
    21 #include <openmax/il/khronos/v1_x/OMX_Audio.h>
       
    22 
       
    23 #include "OmxImpl.h"
       
    24 #include "OmxPCMCodec.h"
       
    25 
       
    26 const TInt KPCMBufferSize = 4096;
       
    27 
       
    28 const TInt KThreadStackSize = 16384; 
       
    29 
       
    30 const TInt KShutDownTime = 5000000; 
       
    31 		
       
    32 
       
    33 TInt ProcessingThread(TAny* aComponent)
       
    34 	{
       
    35 	// get our class
       
    36 	CCodecProcessor* codecprocessor = static_cast<CCodecProcessor*>(aComponent);
       
    37 
       
    38 	// run the thread
       
    39 	TRAPD(err, codecprocessor->RunThreadL());
       
    40 	// thread has exited or failed to start so return error to the client. 
       
    41 	return err;
       
    42 	}
       
    43 
       
    44 
       
    45 TInt COmxPCMCodec::CreateComponent(OMX_HANDLETYPE hComponent)
       
    46 	{
       
    47 	COmxPCMCodec* self = new COmxPCMCodec(hComponent);
       
    48 	if (self==NULL)
       
    49 		{
       
    50 		return KErrNoMemory;
       
    51 		}		
       
    52 	TRAPD(err, self->ConstructL());
       
    53 	// self is stored in the handle, so we won't return it
       
    54 	return err;
       
    55 	}
       
    56 	
       
    57 OMX_ERRORTYPE COmxPCMCodec::GetComponentVersion(
       
    58        OMX_STRING /*pComponentName*/,
       
    59        OMX_VERSIONTYPE* /*pComponentVersion*/,
       
    60        OMX_VERSIONTYPE* /*pSpecVersion*/,
       
    61        OMX_UUIDTYPE* /*pComponentUUID*/)
       
    62 	{
       
    63 // to be implemented
       
    64 	return OMX_ErrorNone;
       
    65 	}
       
    66 	
       
    67 
       
    68 void COmxPCMCodec::ConstructL()
       
    69 	{
       
    70 	iCodecProcessor = CCodecProcessor::NewL(*this);	
       
    71 	iState = OMX_StateLoaded;
       
    72 	}
       
    73 
       
    74 COmxPCMCodec::COmxPCMCodec(OMX_HANDLETYPE hComponent)
       
    75 	:COmxComponentImpl(hComponent)
       
    76 	{
       
    77 	}
       
    78 	
       
    79 COmxPCMCodec::~COmxPCMCodec()
       
    80 	{
       
    81 	if (iState == OMX_StateExecuting)
       
    82 		{
       
    83 		iCodecProcessor->Stop();
       
    84 		iState = OMX_StateIdle;
       
    85 		}
       
    86 
       
    87 	if (iCreatedThread &&(iProcessingThread.Handle() != KNullHandle) && (iProcessingThread.ExitType() == EExitPending))
       
    88 		{
       
    89 		TRequestStatus logonStatus;
       
    90 		TBool logonFailed = EFalse;
       
    91 		iProcessingThread.Logon(logonStatus);
       
    92 		if(logonStatus != KRequestPending)
       
    93 			{//logon failed. Mostly due to no memory
       
    94 			logonFailed = ETrue;
       
    95 			}		
       
    96 		iCodecProcessor->Exit();
       
    97 		RTimer timer;
       
    98 		TInt err = timer.CreateLocal();
       
    99 		if(err==KErrNone && !logonFailed) //both timer and logon successful
       
   100 			{
       
   101 			TRequestStatus timeout;
       
   102 			timer.After(timeout, KShutDownTime);
       
   103 			User::WaitForRequest(logonStatus, timeout);
       
   104 			if(logonStatus==KRequestPending)
       
   105 				{//Thread has not exited after the timeout. Kill it!
       
   106 				iProcessingThread.LogonCancel(logonStatus);
       
   107 				User::WaitForRequest(logonStatus);
       
   108 				iProcessingThread.Kill(KErrDied);
       
   109 				}
       
   110 			else 
       
   111 				{//Thread exited. Cancel the timer
       
   112 				timer.Cancel();
       
   113 				User::WaitForRequest(timeout);
       
   114 				}
       
   115 			}
       
   116 		else 
       
   117 			{//either timer or Logon method has failed.Poll the thread status a maximum
       
   118 			 // of 10 times and kill the thread if it hasn't exited after the polling
       
   119 			for (TInt i=0; i<10 && iProcessingThread.ExitType() == EExitPending; ++i)
       
   120 				{
       
   121 				User::After(KShutDownTime/10);	// wait for a while
       
   122 				}
       
   123 			
       
   124 			if (iProcessingThread.ExitType() == EExitPending)
       
   125 				{
       
   126 				// The polling hasn't been succesful so we kill the thread
       
   127 				iProcessingThread.Kill(KErrDied);
       
   128 				}
       
   129 			if(!logonFailed)
       
   130 				{
       
   131 				User::WaitForRequest(logonStatus);
       
   132 				}
       
   133 			}	
       
   134 		iProcessingThread.Close();
       
   135 		}
       
   136 	delete iCodecProcessor;
       
   137 	}
       
   138 
       
   139 OMX_ERRORTYPE COmxPCMCodec::SendCommand(
       
   140        OMX_COMMANDTYPE Cmd,
       
   141        TUint32 nParam1,
       
   142        TAny* /*pCmdData*/)
       
   143 	{
       
   144 	OMX_ERRORTYPE error = OMX_ErrorNone;
       
   145 	switch (Cmd)
       
   146 		{
       
   147 	case OMX_CommandStateSet:
       
   148 		OMX_STATETYPE state = (OMX_STATETYPE)nParam1;
       
   149 		if (state == iState)
       
   150 			{
       
   151 			error = OMX_ErrorSameState;
       
   152 			}
       
   153 		else
       
   154 			{
       
   155 			// notify client of the state change
       
   156 			switch (state)
       
   157 				{
       
   158 			case OMX_StateIdle:
       
   159 				{
       
   160 				if (iState == OMX_StateExecuting)
       
   161 					{
       
   162 					iCodecProcessor->Stop();
       
   163 					}
       
   164 				break;
       
   165 				}
       
   166 			case OMX_StateExecuting:
       
   167 				StartExecution();
       
   168 				break;
       
   169 				};
       
   170 	
       
   171 			iState = state;
       
   172 			
       
   173 			EventHandlerCallback(
       
   174 				OMX_EventCmdComplete,
       
   175 				OMX_CommandStateSet,
       
   176 				iState,
       
   177 				NULL);	
       
   178 			break;
       
   179 			}
       
   180 		};	
       
   181 	return error;
       
   182 	}
       
   183 	
       
   184 OMX_ERRORTYPE COmxPCMCodec::GetParameter(
       
   185        OMX_INDEXTYPE nParamIndex,  
       
   186        TAny* ComponentParameterStructure)
       
   187 	{
       
   188 	switch (nParamIndex)
       
   189 		{
       
   190 	case OMX_IndexParamAudioInit :
       
   191 		{
       
   192 		OMX_PORT_PARAM_TYPE* param = static_cast<OMX_PORT_PARAM_TYPE*>(ComponentParameterStructure);
       
   193 		param->nPorts = 2;
       
   194 		}
       
   195 		break;
       
   196 	case OMX_IndexParamPortDefinition:
       
   197 		{
       
   198 		OMX_PARAM_PORTDEFINITIONTYPE* portDef = static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(ComponentParameterStructure);
       
   199 		if (portDef->nPortIndex==0)	
       
   200 			{
       
   201 			portDef->eDir = OMX_DirInput;	
       
   202 			portDef->nBufferSize = KPCMBufferSize;
       
   203 			}
       
   204 		else
       
   205 			{
       
   206 			portDef->eDir = OMX_DirOutput;
       
   207 			portDef->nBufferSize = KPCMBufferSize;
       
   208 			}
       
   209 		}
       
   210 		break;
       
   211 	default:
       
   212 		return OMX_ErrorUnsupportedIndex;
       
   213 		}
       
   214 	return OMX_ErrorNone;
       
   215 	}
       
   216 	
       
   217 OMX_ERRORTYPE COmxPCMCodec::SetParameter(
       
   218        OMX_INDEXTYPE nIndex,
       
   219        TAny* ComponentParameterStructure)
       
   220 	{
       
   221 	ASSERT(iState == OMX_StateLoaded);
       
   222 	switch (nIndex)
       
   223 		{
       
   224 		case OMX_IndexParamAudioPcm:
       
   225 			{
       
   226 			OMX_AUDIO_PARAM_PCMMODETYPE* param = static_cast<OMX_AUDIO_PARAM_PCMMODETYPE*>(ComponentParameterStructure);
       
   227 			switch(param->nPortIndex)
       
   228 				{
       
   229 				case 0: // Input port
       
   230 					{
       
   231 					iCodecProcessor->SetInputBitsPerSample(param->nBitPerSample);
       
   232 					iCodecProcessor->SetInputDataType(param->eNumData);
       
   233 					//break;
       
   234 					return OMX_ErrorNone;
       
   235 					}			
       
   236 				case 1: // Output port
       
   237 					{
       
   238 					iCodecProcessor->SetOutputBitsPerSample(param->nBitPerSample);
       
   239 					iCodecProcessor->SetOutputDataType(param->eNumData);
       
   240 					//break;	
       
   241 					return OMX_ErrorNone;
       
   242 					}
       
   243 				default:
       
   244 					{
       
   245 					return OMX_ErrorUnsupportedIndex;	
       
   246 					}
       
   247 				};
       
   248 			}
       
   249 		default:
       
   250 			{
       
   251 			return OMX_ErrorUnsupportedIndex;
       
   252 			}
       
   253 		};		
       
   254 	//return OMX_ErrorNone;
       
   255 	}
       
   256 	
       
   257 OMX_ERRORTYPE COmxPCMCodec::GetConfig(
       
   258        OMX_INDEXTYPE /*nIndex*/, 
       
   259        TAny* /*value*/)
       
   260 	{
       
   261 	return OMX_ErrorUnsupportedIndex;
       
   262 	}
       
   263 	
       
   264 OMX_ERRORTYPE COmxPCMCodec::SetConfig(
       
   265        OMX_INDEXTYPE /*nIndex*/, 
       
   266        TAny* /*value*/)
       
   267 	{
       
   268 	return OMX_ErrorUnsupportedIndex;
       
   269 	}
       
   270 	
       
   271 OMX_ERRORTYPE COmxPCMCodec::GetExtensionIndex(
       
   272        OMX_STRING /*ParameterName*/,
       
   273        OMX_INDEXTYPE* /*pIndexType*/)
       
   274 	{
       
   275 	return OMX_ErrorNotImplemented;
       
   276 	}
       
   277 	
       
   278 OMX_ERRORTYPE COmxPCMCodec::GetState(
       
   279        OMX_STATETYPE* pState)
       
   280 	{
       
   281 	*pState = iState;
       
   282 	return OMX_ErrorNone;
       
   283 	}
       
   284 
       
   285 OMX_ERRORTYPE COmxPCMCodec::ComponentTunnelRequest(
       
   286 		OMX_HANDLETYPE /*hInput*/,
       
   287 		TUint32 /*nInputPort*/,
       
   288 		OMX_HANDLETYPE /*hOutput*/,
       
   289 		TUint32 /*nOutputPort*/,
       
   290 		OMX_TUNNELSETUPTYPE* /*pTunnelSetup*/)
       
   291 	{
       
   292 	return OMX_ErrorNotImplemented;
       
   293 	}
       
   294 	
       
   295 OMX_ERRORTYPE COmxPCMCodec::UseBuffer(
       
   296        OMX_BUFFERHEADERTYPE** ppBufferHeader,
       
   297        TUint32 /*nPortIndex*/,
       
   298        TAny* pAppPrivate,
       
   299        TUint32 nSizeBytes,
       
   300        TUint8* pBuffer)
       
   301 	{
       
   302 	ASSERT(iState == OMX_StateLoaded);
       
   303 	*ppBufferHeader = new OMX_BUFFERHEADERTYPE;
       
   304 	if (*ppBufferHeader != NULL)
       
   305 		{
       
   306 		(*ppBufferHeader)->pBuffer = pBuffer;
       
   307 		(*ppBufferHeader)->pAppPrivate = pAppPrivate;
       
   308 		(*ppBufferHeader)->nAllocLen = nSizeBytes;
       
   309 		(*ppBufferHeader)->nFilledLen = 0;
       
   310 		(*ppBufferHeader)->nFlags = 0;
       
   311 		(*ppBufferHeader)->pInputPortPrivate = NULL;
       
   312 		(*ppBufferHeader)->pOutputPortPrivate = NULL;
       
   313 		}
       
   314 		
       
   315 	if (*ppBufferHeader)
       
   316 		{
       
   317 		return OMX_ErrorNone;
       
   318 		}
       
   319 	else
       
   320 		{
       
   321 		return OMX_ErrorInsufficientResources;
       
   322 		}
       
   323 	}
       
   324 	
       
   325 OMX_ERRORTYPE COmxPCMCodec::AllocateBuffer(
       
   326 		OMX_BUFFERHEADERTYPE** pBuffer,
       
   327 		TUint32 nPortIndex,
       
   328 		TAny* pAppData,
       
   329 		TUint32 nSizeBytes)
       
   330 	{
       
   331 	ASSERT(iState == OMX_StateLoaded);
       
   332 	
       
   333 	*pBuffer = new OMX_BUFFERHEADERTYPE;
       
   334 	if (*pBuffer != NULL)
       
   335 		{
       
   336 		(*pBuffer)->pBuffer = new unsigned char[nSizeBytes];
       
   337 		// store our allocated memory in component's private store
       
   338 		switch (nPortIndex)
       
   339 			{
       
   340 		case 0:
       
   341 			(*pBuffer)->pInputPortPrivate = (*pBuffer)->pBuffer;
       
   342 			(*pBuffer)->pOutputPortPrivate = NULL;
       
   343 			break;
       
   344 		case 1:
       
   345 			(*pBuffer)->pOutputPortPrivate = (*pBuffer)->pBuffer;
       
   346 			(*pBuffer)->pInputPortPrivate = NULL;
       
   347 			break;
       
   348 			};
       
   349 		
       
   350 		
       
   351 		(*pBuffer)->nAllocLen = nSizeBytes;
       
   352 		(*pBuffer)->nFilledLen = 0;
       
   353 		(*pBuffer)->pAppPrivate = pAppData;
       
   354 		}
       
   355 		
       
   356 	if (*pBuffer && (*pBuffer)->pBuffer)
       
   357 		{
       
   358 		return OMX_ErrorNone;
       
   359 		}
       
   360 	else
       
   361 		{
       
   362 		return OMX_ErrorInsufficientResources;
       
   363 		}
       
   364 	}
       
   365 
       
   366 OMX_ERRORTYPE COmxPCMCodec::FreeBuffer(
       
   367 		TUint32 /*nPortIndex*/,
       
   368        OMX_BUFFERHEADERTYPE* pBuffer)
       
   369 	{
       
   370 	if (pBuffer->pInputPortPrivate || 
       
   371 		pBuffer->pOutputPortPrivate)
       
   372 		delete[] pBuffer->pBuffer;
       
   373 	delete pBuffer;
       
   374 	return OMX_ErrorNone;
       
   375 	}
       
   376 OMX_ERRORTYPE COmxPCMCodec::EmptyThisBuffer(
       
   377        OMX_BUFFERHEADERTYPE* pBuffer)
       
   378 	{
       
   379 	ASSERT(iState == OMX_StateExecuting ||
       
   380 			iState == OMX_StateIdle ||
       
   381 			iState == OMX_StatePause);
       
   382 	return iCodecProcessor->EmptyThisBuffer(pBuffer);
       
   383 	}
       
   384 OMX_ERRORTYPE COmxPCMCodec::FillThisBuffer(
       
   385            OMX_BUFFERHEADERTYPE* pBuffer)
       
   386 	{
       
   387 	ASSERT(iState == OMX_StateExecuting ||
       
   388 			iState == OMX_StateIdle ||
       
   389 			iState == OMX_StatePause);
       
   390 	return iCodecProcessor->FillThisBuffer(pBuffer);	
       
   391 	}
       
   392 	
       
   393 OMX_ERRORTYPE COmxPCMCodec::SetCallbacks(
       
   394            OMX_CALLBACKTYPE* pCallbacks, 
       
   395            TAny* pAppData)
       
   396 	{
       
   397 	iCallback = pCallbacks;
       
   398 	iAppData = pAppData;
       
   399 	return OMX_ErrorNone;
       
   400 	}
       
   401 	
       
   402 	
       
   403 CCodecProcessor::CCodecProcessor(COmxPCMCodec& aParent) 
       
   404 	: iParent(&aParent)
       
   405 	{
       
   406 	}
       
   407 
       
   408 void CCodecProcessor::RunThreadL()
       
   409 	{
       
   410 	iQueueStatus = KRequestPending;
       
   411 	iMessageQueue.NotifyDataAvailable(iQueueStatus);
       
   412 	
       
   413 	for (;;)
       
   414 		{
       
   415 		User::WaitForRequest(iQueueStatus);
       
   416 		TCodecMessage msg;
       
   417 		
       
   418 		TBool exit = EFalse;
       
   419 		
       
   420 		while (iMessageQueue.Receive(msg)==KErrNone)
       
   421 			{
       
   422 			switch (msg.iType)
       
   423 				{
       
   424 				case EStopProcessing:
       
   425 					iStarted = EFalse;
       
   426 					break;
       
   427 				case EExit:
       
   428 					exit = ETrue;
       
   429 					break;
       
   430 				case EInputBuffer:
       
   431 					iBuffersToEmpty.Append(msg.iBuffer); 
       
   432 					break;
       
   433 				case EOutputBuffer:
       
   434 					iBuffersToFill.Append(msg.iBuffer);
       
   435 					break;
       
   436 				}
       
   437 			}
       
   438 			
       
   439 		if (exit)
       
   440 			{
       
   441 			break;
       
   442 			}
       
   443 		else
       
   444 			{
       
   445 			// process all available buffers
       
   446 			ProcessAvailableBuffers();	
       
   447 			
       
   448 			// request notification of further queue events
       
   449 			iQueueStatus = KRequestPending;
       
   450 			iMessageQueue.NotifyDataAvailable(iQueueStatus);
       
   451 			//TBool lastBuffer=EFalse;  TODO UNUSED!
       
   452 			}
       
   453 		}
       
   454 
       
   455 	}
       
   456 
       
   457 
       
   458 CCodecProcessor* CCodecProcessor::NewL(COmxPCMCodec& aParent) 
       
   459 	{
       
   460 	CCodecProcessor* self = new (ELeave) CCodecProcessor(aParent);
       
   461 	CleanupStack::PushL(self);
       
   462 	self->ConstructL();
       
   463 	CleanupStack::Pop(self);
       
   464 	return self;
       
   465 	}	
       
   466 	
       
   467 	
       
   468 void CCodecProcessor::ConstructL()
       
   469 	{
       
   470 	User::LeaveIfError(iMessageQueue.CreateLocal(10));
       
   471 	// set the default case	
       
   472 	iInputBitsPerSample = 8;
       
   473 	iInputDataType = OMX_NumericalDataUnsigned;
       
   474 	iOutputBitsPerSample = 16;
       
   475 	iOutputDataType = OMX_NumericalDataSigned;
       
   476 	}
       
   477 	
       
   478 OMX_ERRORTYPE CCodecProcessor::EmptyThisBuffer( 
       
   479 		OMX_BUFFERHEADERTYPE* pBuffer) 
       
   480 	{
       
   481 	TCodecMessage message;
       
   482 	message.iType = EInputBuffer;
       
   483 	message.iBuffer = pBuffer;
       
   484 	if (iMessageQueue.Send(message) == KErrNone)
       
   485 		{
       
   486 		return OMX_ErrorNone;	
       
   487 		}
       
   488 	else
       
   489 		{
       
   490 		return OMX_ErrorUndefined;
       
   491 		}
       
   492 	}
       
   493 	
       
   494 void CCodecProcessor::Stop()
       
   495 	{
       
   496 	TCodecMessage message;
       
   497 	message.iType = EStopProcessing;
       
   498 	message.iBuffer = NULL;
       
   499 	iMessageQueue.Send(message);
       
   500 	}
       
   501 	
       
   502 void CCodecProcessor::Exit()
       
   503 	{
       
   504 	TCodecMessage message;
       
   505 	message.iType = EExit;
       
   506 	message.iBuffer = NULL;
       
   507 	iMessageQueue.SendBlocking(message);
       
   508 	}
       
   509 	
       
   510 OMX_ERRORTYPE CCodecProcessor::FillThisBuffer(
       
   511 									OMX_BUFFERHEADERTYPE* pBuffer) 
       
   512 	{
       
   513 	TCodecMessage message;
       
   514 	message.iType = EOutputBuffer;
       
   515 	message.iBuffer = pBuffer;
       
   516 	if (iMessageQueue.Send(message)== KErrNone)
       
   517 		{
       
   518 		return OMX_ErrorNone;
       
   519 		}
       
   520 	else
       
   521 		{
       
   522 		return OMX_ErrorUndefined;
       
   523 		}
       
   524 	}
       
   525 	
       
   526 void CCodecProcessor::SetInputBitsPerSample(TInt aInputBitsPerSample)
       
   527 	{
       
   528 	iInputBitsPerSample = aInputBitsPerSample;
       
   529 	}
       
   530 	
       
   531 void CCodecProcessor::SetInputDataType(OMX_NUMERICALDATATYPE aType)
       
   532 	{
       
   533 	iInputDataType = aType;
       
   534 	}
       
   535 	
       
   536 void CCodecProcessor::SetOutputBitsPerSample(TInt aInputBitsPerSample)
       
   537 	{
       
   538 	iOutputBitsPerSample = aInputBitsPerSample;
       
   539 	}
       
   540 	
       
   541 void CCodecProcessor::SetOutputDataType(OMX_NUMERICALDATATYPE aType)
       
   542 	{
       
   543 	iOutputDataType = aType;
       
   544 	}
       
   545 
       
   546 void CCodecProcessor::ChooseCodec()
       
   547 	{
       
   548 	// choose correct conversion codec
       
   549 	if (iInputBitsPerSample == 8 && iOutputBitsPerSample == 16)
       
   550 		{
       
   551 		iOutputSamplesPerInputSample = 2;
       
   552 		if (iInputDataType == OMX_NumericalDataSigned &&
       
   553 		iOutputDataType == OMX_NumericalDataSigned)
       
   554 			{
       
   555 			iCurrentCodec = &iAudioS8ToS16PcmCodec;
       
   556 			}
       
   557 		else if (iInputDataType == OMX_NumericalDataUnsigned &&
       
   558 			iOutputDataType == OMX_NumericalDataSigned)
       
   559 			{
       
   560 			iCurrentCodec = &iAudioU8ToS16PcmCodec;
       
   561 			}
       
   562 		}
       
   563 	else if (iInputBitsPerSample == 16 && iOutputBitsPerSample == 8)
       
   564 		{
       
   565 		iOutputSamplesPerInputSample = .5;
       
   566 		if (iInputDataType == OMX_NumericalDataSigned &&
       
   567 		iOutputDataType == OMX_NumericalDataSigned)
       
   568 			{
       
   569 			iCurrentCodec = &iAudioS16ToS8PcmCodec;
       
   570 			}
       
   571 		else if (iInputDataType == OMX_NumericalDataSigned &&
       
   572 			iOutputDataType == OMX_NumericalDataUnsigned)
       
   573 			{
       
   574 			iCurrentCodec = &iAudioS16ToU8PcmCodec;
       
   575 			}
       
   576 		}
       
   577 	
       
   578 	}
       
   579 
       
   580 void CCodecProcessor::ProcessAvailableBuffers()
       
   581 	{
       
   582 	// Setup wait for data in queue
       
   583 	while (iBuffersToFill.Count()>0 && iBuffersToEmpty.Count() > 0)
       
   584 		{
       
   585 		TBool lastBuffer = EFalse;
       
   586 		if (!iStarted)
       
   587 			{
       
   588 			ChooseCodec();
       
   589 			iStarted = ETrue;
       
   590 			}
       
   591 		
       
   592 		OMX_BUFFERHEADERTYPE* srcBuffer = iBuffersToEmpty[0];
       
   593 		OMX_BUFFERHEADERTYPE* destBuffer = iBuffersToFill[0];
       
   594 		if (srcBuffer->nFlags & OMX_BUFFERFLAG_EOS)
       
   595 			{
       
   596 			lastBuffer = ETrue;
       
   597 			}
       
   598 		TInt destBufferPos = destBuffer->nFilledLen;
       
   599 		
       
   600 		TInt destBufferSize = destBuffer->nAllocLen - destBufferPos;
       
   601 		TInt inputSamplesRequired = (TInt)((TReal)destBufferSize / iOutputSamplesPerInputSample);
       
   602 		
       
   603 		TInt availableSamples = srcBuffer->nFilledLen - iInputBufferPos;
       
   604 		
       
   605 		if (availableSamples <= inputSamplesRequired)
       
   606 			{
       
   607 			TInt samplesToConvert = availableSamples;
       
   608 			if (iOutputSamplesPerInputSample == .5)
       
   609 				{
       
   610 				samplesToConvert >>= 1;
       
   611 				}
       
   612 			iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert);
       
   613 			iInputBufferPos = 0; // finished buffer - so reset
       
   614 			inputSamplesRequired -= availableSamples;
       
   615 //			TInt filled = availableSamples;  TODO UNUSED
       
   616 			destBuffer->nFilledLen = (TInt)((TReal)availableSamples * iOutputSamplesPerInputSample);
       
   617 			srcBuffer->nFilledLen = 0;
       
   618 			iBuffersToEmpty.Remove(0);
       
   619 			iParent->EmptyBufferDoneCallback(srcBuffer);			
       
   620 			
       
   621 			if (inputSamplesRequired == 0 || lastBuffer)
       
   622 				{
       
   623 				iBuffersToFill.Remove(0);
       
   624 				if (lastBuffer)
       
   625 					{
       
   626 					destBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
       
   627 					// propagate the EOS flag
       
   628 					iParent->EventHandlerCallback(
       
   629 						OMX_EventBufferFlag,
       
   630 						0,
       
   631 						destBuffer->nFlags,
       
   632 						NULL);	
       
   633 					}
       
   634 				iParent->FillBufferDoneCallback(destBuffer);
       
   635 				}
       
   636 			}
       
   637 		else
       
   638 			{
       
   639 			TInt samplesToConvert = inputSamplesRequired;
       
   640 			if (iOutputSamplesPerInputSample == .5)
       
   641 				{
       
   642 				samplesToConvert >>= 2;
       
   643 				}
       
   644 
       
   645 			iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert);
       
   646 			iInputBufferPos += inputSamplesRequired;
       
   647 			destBuffer->nFilledLen = destBuffer->nAllocLen;
       
   648 			iBuffersToFill.Remove(0);
       
   649 			iParent->FillBufferDoneCallback(destBuffer);
       
   650 			}		
       
   651 		}
       
   652 	}
       
   653 	
       
   654 CCodecProcessor::~CCodecProcessor()
       
   655 	{
       
   656 	iBuffersToEmpty.Close();
       
   657 	iBuffersToFill.Close();
       
   658 	iMessageQueue.Close();
       
   659 	}
       
   660 	
       
   661 	
       
   662 TInt COmxPCMCodec::StartExecution()
       
   663 	{
       
   664 	// create thread with current thread's heap
       
   665 	// we can thus allocate and free memory across threads
       
   666 	if (!iCreatedThread)
       
   667 		{
       
   668 		TInt err = iProcessingThread.Create(_L("PCMCodec"), 
       
   669 							&ProcessingThread, 
       
   670 							KThreadStackSize, 
       
   671 							&User::Heap(),
       
   672 							iCodecProcessor);
       
   673 							
       
   674 		if (err!=KErrNone)
       
   675 			{
       
   676 			return err;
       
   677 			}
       
   678 		iCreatedThread = ETrue;
       
   679 		iThreadDeath = KRequestPending;
       
   680 		iProcessingThread.Resume();
       
   681 		}
       
   682 
       
   683 	return KErrNone;						
       
   684 	}
       
   685 
       
   686 // Callbacks for the PCM codec
       
   687 void COmxPCMCodec::EventHandlerCallback( 
       
   688         			OMX_OUT OMX_EVENTTYPE eEvent, 
       
   689         			OMX_OUT TUint32 nData1,
       
   690         			OMX_OUT TUint32 nData2,
       
   691         			OMX_OUT OMX_STRING cExtraInfo)
       
   692 	{
       
   693 	iCallback->EventHandler(
       
   694 			this,
       
   695 			iAppData,
       
   696 			eEvent,
       
   697 			nData1,
       
   698 			nData2,
       
   699 			cExtraInfo);	
       
   700 	}
       
   701 	
       
   702 	
       
   703 void COmxPCMCodec::FillBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
       
   704 	{
       
   705 	iCallback->FillBufferDone(
       
   706 		*this,
       
   707 		iAppData,
       
   708 		aBuffer);
       
   709 	}
       
   710 	
       
   711 void COmxPCMCodec::EmptyBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
       
   712 	{
       
   713 	iCallback->EmptyBufferDone(
       
   714 		*this,
       
   715 		iAppData,
       
   716 		aBuffer);		
       
   717 	}
       
   718 	
       
   719 // Component Entry Point
       
   720 OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE hComponent)
       
   721 	{
       
   722 	TInt err = COmxPCMCodec::CreateComponent(hComponent);
       
   723 	if (err == KErrNone)
       
   724 		{
       
   725 		return OMX_ErrorNone;
       
   726 		}		
       
   727 	else 
       
   728 		{
       
   729 		// return problem
       
   730 		return OMX_ErrorInsufficientResources;		
       
   731 		}
       
   732 	}