os/mm/mmdevicefw/mdfunittest/codecapi/omx/pcmcodec/src/OmxPCMCodec.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 			}
   452 		}
   453 
   454 	}
   455 
   456 
   457 CCodecProcessor* CCodecProcessor::NewL(COmxPCMCodec& aParent) 
   458 	{
   459 	CCodecProcessor* self = new (ELeave) CCodecProcessor(aParent);
   460 	CleanupStack::PushL(self);
   461 	self->ConstructL();
   462 	CleanupStack::Pop(self);
   463 	return self;
   464 	}	
   465 	
   466 	
   467 void CCodecProcessor::ConstructL()
   468 	{
   469 	User::LeaveIfError(iMessageQueue.CreateLocal(10));
   470 	// set the default case	
   471 	iInputBitsPerSample = 8;
   472 	iInputDataType = OMX_NumericalDataUnsigned;
   473 	iOutputBitsPerSample = 16;
   474 	iOutputDataType = OMX_NumericalDataSigned;
   475 	}
   476 	
   477 OMX_ERRORTYPE CCodecProcessor::EmptyThisBuffer( 
   478 		OMX_BUFFERHEADERTYPE* pBuffer) 
   479 	{
   480 	TCodecMessage message;
   481 	message.iType = EInputBuffer;
   482 	message.iBuffer = pBuffer;
   483 	if (iMessageQueue.Send(message) == KErrNone)
   484 		{
   485 		return OMX_ErrorNone;	
   486 		}
   487 	else
   488 		{
   489 		return OMX_ErrorUndefined;
   490 		}
   491 	}
   492 	
   493 void CCodecProcessor::Stop()
   494 	{
   495 	TCodecMessage message;
   496 	message.iType = EStopProcessing;
   497 	message.iBuffer = NULL;
   498 	iMessageQueue.Send(message);
   499 	}
   500 	
   501 void CCodecProcessor::Exit()
   502 	{
   503 	TCodecMessage message;
   504 	message.iType = EExit;
   505 	message.iBuffer = NULL;
   506 	iMessageQueue.SendBlocking(message);
   507 	}
   508 	
   509 OMX_ERRORTYPE CCodecProcessor::FillThisBuffer(
   510 									OMX_BUFFERHEADERTYPE* pBuffer) 
   511 	{
   512 	TCodecMessage message;
   513 	message.iType = EOutputBuffer;
   514 	message.iBuffer = pBuffer;
   515 	if (iMessageQueue.Send(message)== KErrNone)
   516 		{
   517 		return OMX_ErrorNone;
   518 		}
   519 	else
   520 		{
   521 		return OMX_ErrorUndefined;
   522 		}
   523 	}
   524 	
   525 void CCodecProcessor::SetInputBitsPerSample(TInt aInputBitsPerSample)
   526 	{
   527 	iInputBitsPerSample = aInputBitsPerSample;
   528 	}
   529 	
   530 void CCodecProcessor::SetInputDataType(OMX_NUMERICALDATATYPE aType)
   531 	{
   532 	iInputDataType = aType;
   533 	}
   534 	
   535 void CCodecProcessor::SetOutputBitsPerSample(TInt aInputBitsPerSample)
   536 	{
   537 	iOutputBitsPerSample = aInputBitsPerSample;
   538 	}
   539 	
   540 void CCodecProcessor::SetOutputDataType(OMX_NUMERICALDATATYPE aType)
   541 	{
   542 	iOutputDataType = aType;
   543 	}
   544 
   545 void CCodecProcessor::ChooseCodec()
   546 	{
   547 	// choose correct conversion codec
   548 	if (iInputBitsPerSample == 8 && iOutputBitsPerSample == 16)
   549 		{
   550 		iOutputSamplesPerInputSample = 2;
   551 		if (iInputDataType == OMX_NumericalDataSigned &&
   552 		iOutputDataType == OMX_NumericalDataSigned)
   553 			{
   554 			iCurrentCodec = &iAudioS8ToS16PcmCodec;
   555 			}
   556 		else if (iInputDataType == OMX_NumericalDataUnsigned &&
   557 			iOutputDataType == OMX_NumericalDataSigned)
   558 			{
   559 			iCurrentCodec = &iAudioU8ToS16PcmCodec;
   560 			}
   561 		}
   562 	else if (iInputBitsPerSample == 16 && iOutputBitsPerSample == 8)
   563 		{
   564 		iOutputSamplesPerInputSample = .5;
   565 		if (iInputDataType == OMX_NumericalDataSigned &&
   566 		iOutputDataType == OMX_NumericalDataSigned)
   567 			{
   568 			iCurrentCodec = &iAudioS16ToS8PcmCodec;
   569 			}
   570 		else if (iInputDataType == OMX_NumericalDataSigned &&
   571 			iOutputDataType == OMX_NumericalDataUnsigned)
   572 			{
   573 			iCurrentCodec = &iAudioS16ToU8PcmCodec;
   574 			}
   575 		}
   576 	
   577 	}
   578 
   579 void CCodecProcessor::ProcessAvailableBuffers()
   580 	{
   581 	// Setup wait for data in queue
   582 	while (iBuffersToFill.Count()>0 && iBuffersToEmpty.Count() > 0)
   583 		{
   584 		TBool lastBuffer = EFalse;
   585 		if (!iStarted)
   586 			{
   587 			ChooseCodec();
   588 			iStarted = ETrue;
   589 			}
   590 		
   591 		OMX_BUFFERHEADERTYPE* srcBuffer = iBuffersToEmpty[0];
   592 		OMX_BUFFERHEADERTYPE* destBuffer = iBuffersToFill[0];
   593 		if (srcBuffer->nFlags & OMX_BUFFERFLAG_EOS)
   594 			{
   595 			lastBuffer = ETrue;
   596 			}
   597 		TInt destBufferPos = destBuffer->nFilledLen;
   598 		
   599 		TInt destBufferSize = destBuffer->nAllocLen - destBufferPos;
   600 		TInt inputSamplesRequired = (TInt)((TReal)destBufferSize / iOutputSamplesPerInputSample);
   601 		
   602 		TInt availableSamples = srcBuffer->nFilledLen - iInputBufferPos;
   603 		
   604 		if (availableSamples <= inputSamplesRequired)
   605 			{
   606 			TInt samplesToConvert = availableSamples;
   607 			if (iOutputSamplesPerInputSample == .5)
   608 				{
   609 				samplesToConvert >>= 1;
   610 				}
   611 			iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert);
   612 			iInputBufferPos = 0; // finished buffer - so reset
   613 			inputSamplesRequired -= availableSamples;
   614 			destBuffer->nFilledLen = (TInt)((TReal)availableSamples * iOutputSamplesPerInputSample);
   615 			srcBuffer->nFilledLen = 0;
   616 			iBuffersToEmpty.Remove(0);
   617 			iParent->EmptyBufferDoneCallback(srcBuffer);			
   618 			
   619 			if (inputSamplesRequired == 0 || lastBuffer)
   620 				{
   621 				iBuffersToFill.Remove(0);
   622 				if (lastBuffer)
   623 					{
   624 					destBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
   625 					// propagate the EOS flag
   626 					iParent->EventHandlerCallback(
   627 						OMX_EventBufferFlag,
   628 						0,
   629 						destBuffer->nFlags,
   630 						NULL);	
   631 					}
   632 				iParent->FillBufferDoneCallback(destBuffer);
   633 				}
   634 			}
   635 		else
   636 			{
   637 			TInt samplesToConvert = inputSamplesRequired;
   638 			if (iOutputSamplesPerInputSample == .5)
   639 				{
   640 				samplesToConvert >>= 2;
   641 				}
   642 
   643 			iCurrentCodec->Convert(&srcBuffer->pBuffer[iInputBufferPos], &destBuffer->pBuffer[destBufferPos], samplesToConvert);
   644 			iInputBufferPos += inputSamplesRequired;
   645 			destBuffer->nFilledLen = destBuffer->nAllocLen;
   646 			iBuffersToFill.Remove(0);
   647 			iParent->FillBufferDoneCallback(destBuffer);
   648 			}		
   649 		}
   650 	}
   651 	
   652 CCodecProcessor::~CCodecProcessor()
   653 	{
   654 	iBuffersToEmpty.Close();
   655 	iBuffersToFill.Close();
   656 	iMessageQueue.Close();
   657 	}
   658 	
   659 	
   660 TInt COmxPCMCodec::StartExecution()
   661 	{
   662 	// create thread with current thread's heap
   663 	// we can thus allocate and free memory across threads
   664 	if (!iCreatedThread)
   665 		{
   666 		TInt err = iProcessingThread.Create(_L("PCMCodec"), 
   667 							&ProcessingThread, 
   668 							KThreadStackSize, 
   669 							&User::Heap(),
   670 							iCodecProcessor);
   671 							
   672 		if (err!=KErrNone)
   673 			{
   674 			return err;
   675 			}
   676 		iCreatedThread = ETrue;
   677 		iThreadDeath = KRequestPending;
   678 		iProcessingThread.Resume();
   679 		}
   680 
   681 	return KErrNone;						
   682 	}
   683 
   684 // Callbacks for the PCM codec
   685 void COmxPCMCodec::EventHandlerCallback( 
   686         			OMX_OUT OMX_EVENTTYPE eEvent, 
   687         			OMX_OUT TUint32 nData1,
   688         			OMX_OUT TUint32 nData2,
   689         			OMX_OUT OMX_STRING cExtraInfo)
   690 	{
   691 	iCallback->EventHandler(
   692 			this,
   693 			iAppData,
   694 			eEvent,
   695 			nData1,
   696 			nData2,
   697 			cExtraInfo);	
   698 	}
   699 	
   700 	
   701 void COmxPCMCodec::FillBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
   702 	{
   703 	iCallback->FillBufferDone(
   704 		*this,
   705 		iAppData,
   706 		aBuffer);
   707 	}
   708 	
   709 void COmxPCMCodec::EmptyBufferDoneCallback(OMX_BUFFERHEADERTYPE* aBuffer)
   710 	{
   711 	iCallback->EmptyBufferDone(
   712 		*this,
   713 		iAppData,
   714 		aBuffer);		
   715 	}
   716 	
   717 // Component Entry Point
   718 OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE hComponent)
   719 	{
   720 	TInt err = COmxPCMCodec::CreateComponent(hComponent);
   721 	if (err == KErrNone)
   722 		{
   723 		return OMX_ErrorNone;
   724 		}		
   725 	else 
   726 		{
   727 		// return problem
   728 		return OMX_ErrorInsufficientResources;		
   729 		}
   730 	}