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