os/mm/mmlibs/mmfw/src/Plugin/Codec/audio/GSM610/GSM610.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2002-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 // * INCLUDE FILES:
    15 // 
    16 //
    17 
    18 // Standard includes
    19 #include <e32std.h>
    20 
    21 // Private Generic Library includes
    22 #include <ecom/implementationproxy.h>
    23 #include "GSM610.H"
    24 #include "gsm610fr.h"
    25 #include <mmf/plugin/mmfcodecimplementationuids.hrh>
    26 
    27 
    28 //*******************************************************************
    29 //*  GSM Codec to 16 bit PCM Class:
    30 //*******************************************************************
    31 
    32 // __________________________________________________________________________
    33 // Implementation
    34 
    35 CMMFCodec* CMMFGsmTo16PcmCodec::NewL(TAny* aInitParams)
    36 	{
    37 	CMMFGsmTo16PcmCodec* self=new(ELeave) CMMFGsmTo16PcmCodec();
    38 	CleanupStack::PushL(self);
    39 	self->ConstructL(aInitParams);
    40 	CleanupStack::Pop(self);
    41 	return STATIC_CAST( CMMFCodec*, self );
    42 	}
    43 
    44 CMMFGsmTo16PcmCodec::~CMMFGsmTo16PcmCodec()
    45 	{
    46 	delete iCodecPtr;
    47 	}
    48 
    49 CMMFGsmTo16PcmCodec::CMMFGsmTo16PcmCodec()
    50 	{
    51 
    52 	}
    53 
    54 void CMMFGsmTo16PcmCodec::ConstructL(TAny* /*aInitParams*/)
    55 	{
    56 	iCodecPtr = new (ELeave) CGsmTo16PcmWavCodec();
    57 	iCodecPtr->ConstructL();
    58 	iLastFrameNumber = 0;
    59 	}
    60 
    61 
    62 //handy porting stuff from old MS
    63 
    64 //to convert from a CMMFBuffer to a TUint8*
    65 //---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
    66 //---	TUint8* pSrc = CONST_CAST(TUint8*,iSrc->Data().Ptr());
    67 
    68 //to convert from a CMMFBuffer to a TMMFPtr8 (TMMFPtr8)
    69 //---	TMMFPtr8 codecSrc;
    70 //---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
    71 //---	codecSrc.Set(iSrc->Data());
    72 
    73 
    74 TCodecProcessResult CMMFGsmTo16PcmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
    75 	{
    76 
    77 	TMMFPtr8 codecSrc;
    78 	TMMFPtr8 codecDst;
    79 
    80 	TCodecProcessResult result;
    81 	result.iStatus = TCodecProcessResult::EProcessIncomplete;
    82 
    83 	//convert from generic CMMFBuffer to CMMFDataBuffer
    84 	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
    85 	iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
    86 
    87 	const TUint srcLen = iSrc->Data().Length();
    88 	const TUint dstMaxLen = iDst->Data().MaxLength() - iDst->Position();
    89 
    90 	// This is checked only on the first frame.
    91 	if ((dstMaxLen < KPcmInputFrameSize) && (iSrc->FrameNumber() <= 1))
    92 		User::Leave(KErrArgument);
    93 	 
    94 	TUint dstAccumulator = 0;
    95 	TUint srcAccumulator = 0;
    96 
    97 	TUint dstAdded = KPcmInputFrameSize;
    98 	TUint srcAdded = 0;
    99 
   100 	if ((iSrc->FrameNumber() == 1) && (iSrc->Position() == 0))
   101 		{
   102 		iCodecPtr->ResetAllL();
   103 		}
   104 
   105 	if ((iLastFrameNumber != 0) && (iSrc->FrameNumber() <= 1) && 
   106 		(iDst->Position() == 0) && (iSrc->Position() == 0))
   107 		{
   108 		iCodecPtr->ResetAllL();
   109 		}
   110 
   111 	iLastFrameNumber = iSrc->FrameNumber();
   112 
   113 	TInt srcShift = iSrc->Position();
   114 	TInt dstShift = iDst->Position(); // Add offset for Dst Buffer
   115 
   116 	while ((dstAccumulator < dstMaxLen) && (dstAdded))
   117 		{
   118 		//this code chops the data buffer into 65 (or less) byte chunks
   119 		codecSrc.Set(iSrc->Data());
   120 		codecDst.Set(iDst->Data());
   121 		codecDst.SetLength(iDst->Data().MaxLength());
   122 		//move the data to the end of the last bit of the buffer processed
   123 		codecSrc.Shift(srcAccumulator + srcShift);
   124 
   125 		//codecDst.Shift(dstAccumulator);
   126 		codecDst.Shift(dstAccumulator + dstShift); // Add offset for Dst Buffer
   127 		
   128 		iCodecPtr->ProcessL(&codecSrc, &codecDst);
   129 
   130 		dstAdded = codecDst.Length();
   131 		srcAdded = codecSrc.Length();
   132 
   133 		//rules to trigger a codec reset
   134 		if (dstAdded == KPcmInputFrameSize)
   135 			iCodecPtr->Reset();
   136 		if (srcAdded == 0)
   137 			iCodecPtr->Reset();
   138 	
   139 		dstAccumulator += codecDst.Length();
   140 		srcAccumulator += codecSrc.Length();
   141 
   142 		}
   143 
   144 	//iDst->Data().SetLength(dstAccumulator);
   145 	iDst->Data().SetLength(dstAccumulator + dstShift); // Add offset for Dst Buffer
   146 	
   147 	result.iSrcBytesProcessed = srcAccumulator;
   148 	result.iDstBytesAdded = dstAccumulator;
   149 
   150 	if (!srcAdded)
   151 		{
   152 		srcAdded = srcAdded;
   153 		}
   154 	
   155 	if (result.iSrcBytesProcessed + iSrc->Position() >= srcLen)
   156 		result.iStatus = TCodecProcessResult::EProcessComplete;
   157 		
   158 	if (result.iDstBytesAdded < dstMaxLen)
   159 		result.iStatus = TCodecProcessResult::EDstNotFilled;
   160 
   161 	return result;
   162 	}
   163 
   164 
   165 //*******************************************************************
   166 //* 16 bit PCM to GSM Codec Class:
   167 //*******************************************************************
   168 
   169 // __________________________________________________________________________
   170 // Implementation
   171 
   172 CMMFCodec* CMMF16PcmToGsmCodec::NewL(TAny* aInitParams)
   173 	{
   174 	CMMF16PcmToGsmCodec* self=new(ELeave) CMMF16PcmToGsmCodec();
   175 	CleanupStack::PushL(self);
   176 	self->ConstructL(aInitParams);
   177 	CleanupStack::Pop(self);
   178 	return STATIC_CAST( CMMFCodec*, self );
   179 	}
   180 
   181 CMMF16PcmToGsmCodec::~CMMF16PcmToGsmCodec()
   182 	{
   183 	delete iCodecPtr;
   184 	}
   185 
   186 CMMF16PcmToGsmCodec::CMMF16PcmToGsmCodec()
   187 	{
   188 
   189 	}
   190 
   191 void CMMF16PcmToGsmCodec::ConstructL(TAny* /*aInitParams*/)
   192 	{
   193 	iCodecPtr = new (ELeave) C16PcmToGsmWavCodec();
   194 	iCodecPtr->ConstructL();
   195 	iLastFrameNumber = 0;
   196 	}
   197 
   198 //handy porting stuff from old MS
   199 
   200 //to convert from a CMMFBuffer to a TUint8*
   201 //---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
   202 //---	TUint8* pSrc = CONST_CAST(TUint8*,iSrc->Data().Ptr());
   203 
   204 //to convert from a CMMFBuffer to a TMMFPtr8 (TMMFPtr8)
   205 //---	TMMFPtr8 codecSrc;
   206 //---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
   207 //---	codecSrc.Set(iSrc->Data());
   208 
   209 
   210 
   211 TCodecProcessResult CMMF16PcmToGsmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
   212 	{
   213 
   214 	TMMFPtr8 codecSrc;
   215 	TMMFPtr8 codecDst;
   216 
   217 
   218 	TCodecProcessResult result;
   219 	result.iStatus = TCodecProcessResult::EProcessIncomplete;
   220 
   221 	//convert from generic CMMFBuffer to CMMFDataBuffer
   222 	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
   223 	iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
   224 
   225 	//const TUint srcLen = iSrc->Data().Length();
   226 	TUint srcLen = iSrc->Data().Length();
   227 	const TUint dstMaxLen = iDst->Data().MaxLength() - iDst->Position();
   228 
   229 	// This is checked only on the first frame.
   230 	if ((dstMaxLen < KGsmEncodedFrameSize) && (iSrc->FrameNumber() <= 1))
   231 		User::Leave(KErrArgument);
   232 
   233 
   234 	TUint dstAccumulator = 0;
   235 	TUint srcAccumulator = iSrc->Position();
   236 
   237 	TUint dstAdded = 0;
   238 	TUint srcAdded = 0;
   239 	
   240 	if ((iSrc->FrameNumber() == 1) && (iSrc->Position() == 0))
   241 		{
   242 		iCodecPtr->ResetAllL();
   243 		}
   244 
   245 	if ((iLastFrameNumber != 0) && (iSrc->FrameNumber() <= 1) && 
   246 		(iDst->Position() == 0) && (iSrc->Position() == 0))
   247 		{
   248 		iCodecPtr->ResetAllL();
   249 		}
   250 
   251 	iLastFrameNumber = iSrc->FrameNumber();
   252 
   253 //	TInt dstShift = iSrc->Position();
   254 	TInt dstShift = iDst->Position();
   255 
   256 	while (srcAccumulator < srcLen)
   257 		{
   258 		// Create a copy of iSrc and pass that to the Codec as the Codec, 
   259 		// for some reason, alters the source(iSrc).
   260 		// Easier (& quicker) to make copy than to fix the actual Codec as the code is 
   261 		// old and the GSM610 Codec is already quite slow.
   262 		HBufC* copySrc = HBufC::NewLC(srcLen);
   263 		TPtr8 copySrcPtr((TUint8*)copySrc->Ptr(), srcLen, srcLen);
   264 		copySrcPtr.Copy((TUint8*)iSrc->Data().Ptr(), srcLen); 
   265 
   266 		//this code chops the data buffer into 640 (or less) byte chunks
   267 		codecSrc.Set(copySrcPtr/*iSrc->Data()*/);
   268 
   269 		//codecSrc.Set(iSrc->Data());
   270 		codecDst.Set(iDst->Data());
   271 		codecDst.SetLength(iDst->Data().MaxLength());
   272 		//move the data to the end of the last bit of the buffer processed
   273 		codecSrc.Shift(srcAccumulator);
   274 		codecDst.Shift(dstAccumulator + dstShift);
   275 		
   276 		iCodecPtr->ProcessL(&codecSrc, &codecDst);
   277 
   278 		dstAdded = codecDst.Length();
   279 		srcAdded = codecSrc.Length();
   280 
   281 		//rules to trigger a codec reset
   282 		if ((dstAdded == KGsmEncodedFrameSize) && (srcAdded == KPcmInputFrameSize))
   283 			iCodecPtr->Reset();
   284 		if (srcAdded == 0)
   285 			iCodecPtr->Reset();
   286 	
   287 		dstAccumulator += codecDst.Length();
   288 		srcAccumulator += codecSrc.Length();
   289 
   290 		CleanupStack::PopAndDestroy(copySrc);
   291 
   292 		//need to check that we don't process too much of the destination such that it won't fit in the dst buf
   293 		if ((dstAccumulator + KGsmEncodedFrameSize) > dstMaxLen)
   294 			break;
   295 		}
   296 
   297 	iDst->Data().SetLength(dstAccumulator + iDst->Position());
   298 	
   299 	result.iSrcBytesProcessed = srcAccumulator;
   300 	result.iDstBytesAdded = dstAccumulator;
   301 
   302 	if (!srcAdded)
   303 		{
   304 		srcAdded = srcAdded;
   305 		}
   306 	
   307 	if (result.iSrcBytesProcessed + iSrc->Position() >= srcLen)
   308 		result.iStatus = TCodecProcessResult::EProcessComplete; 
   309 		
   310 	if (result.iDstBytesAdded < dstMaxLen)
   311 		{ //need to check that there is space remaining in the destination buffer to process more
   312 		//need at least KGsmEncodeFrameSize bytes
   313 		if ((dstMaxLen - result.iDstBytesAdded) >= KGsmEncodedFrameSize)
   314 				result.iStatus = TCodecProcessResult::EDstNotFilled; //still space for more frames
   315 //		else result.iStatus = TCodecProcessResult::EProcessComplete; //can't do anything more with src or dest
   316 		}
   317 
   318 	return result;
   319 	}
   320 
   321 
   322 
   323 // __________________________________________________________________________
   324 // Exported proxy for instantiation method resolution
   325 // Define the interface UIDs
   326 
   327 
   328 const TImplementationProxy ImplementationTable[] = 
   329 	{
   330 		IMPLEMENTATION_PROXY_ENTRY(KMmfUidCodecGSM610ToPCM16,	CMMFGsmTo16PcmCodec::NewL),
   331 		IMPLEMENTATION_PROXY_ENTRY(KMmfUidCodecPCM16ToGSM610,	CMMF16PcmToGsmCodec::NewL)
   332 
   333 	};
   334 
   335 
   336 
   337 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
   338 	{
   339 	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
   340 
   341 	return ImplementationTable;
   342 	}
   343 
   344 
   345 //*******************************************************************
   346 //* FUNCTION:  CGsmTo16PcmWavCodec::CGsmTo16PcmWavCodec
   347 //*   Constructor for GSM to 16 bit PCM Codec.
   348 //*******************************************************************
   349 
   350 CGsmTo16PcmWavCodec::CGsmTo16PcmWavCodec()
   351 	{
   352 
   353 	Reset();
   354 
   355 	}
   356 
   357 
   358 //*******************************************************************
   359 //* FUNCTION:  CGsmTo16PcmWavCodec::~CGsmTo16PcmWavCodec
   360 //*   Destructor for GSM to 16 bit PCM Codec.
   361 //*******************************************************************
   362 
   363 CGsmTo16PcmWavCodec::~CGsmTo16PcmWavCodec()
   364 	{
   365 
   366 	delete iGsmDecoder;
   367 
   368 	}
   369 
   370 
   371 //*******************************************************************
   372 //* FUNCTION:  CGsmTo16PcmWavCodec::ConstructL
   373 //*   Perform 2nd pass of object construction (allocating data on heap).
   374 //*******************************************************************
   375 
   376 void CGsmTo16PcmWavCodec::ConstructL()
   377 	{
   378 	iGsmDecoder = new (ELeave) CGSM610FR_Decoder;
   379 	iGsmDecoder->ConstructL();
   380 	iGsmDecoder->StartL();
   381 
   382 	iInBufferCount  = 0;
   383 	iOutBufferCount = 0;
   384 	}
   385 
   386 
   387 //*******************************************************************
   388 //* FUNCTION:  CGsmTo16PcmWavCodec::Reset
   389 //*   Reset the input/output buffer states.
   390 //*******************************************************************
   391 
   392 void CGsmTo16PcmWavCodec::Reset()
   393 	{
   394 	iInBufferPtr    = iInBuffer;
   395 	iOutBufferPtr   = iOutBuffer;
   396 	}
   397 
   398 
   399 //*******************************************************************
   400 //* FUNCTION:  CGsmTo16PcmWavCodec::Reset
   401 //*   Reset the input/output buffer states.
   402 //*******************************************************************
   403 
   404 void CGsmTo16PcmWavCodec::ResetAllL()
   405 	{
   406 	Reset();
   407 	iInBufferCount  = 0;
   408 	iOutBufferCount = 0;
   409 	
   410 	iGsmDecoder->StartL();
   411 	}
   412 
   413 
   414 //*******************************************************************
   415 //* FUNCTION:  CGsmTo16PcmWavCodec::ProcessL
   416 //*   Read GSM data (contained in aSrc) and convert it to raw 16 bit
   417 //*   PCM data (contained in aDst).
   418 //*
   419 //*   NOTE that amount of data contained in input/output buffers
   420 //*   varies, so if there is not enough input data or not enough
   421 //*   room for the output data, then this function must buffer
   422 //*   the data until enough data is received (or removed).
   423 //*
   424 //*   NOTE that this function only buffers input (or output) data
   425 //*   if there is not enough data (or room for output) available
   426 //*   in the input (output) stream.  Otherwise, the data is accessed
   427 //*   directly from the input (output) stream which saves unnecessary
   428 //*   copying of data.
   429 //*******************************************************************
   430 
   431 void CGsmTo16PcmWavCodec::ProcessL(TMMFPtr8* aSrc, TMMFPtr8* aDst)
   432 	{
   433 
   434 	TUint8* srcPtr  = NULL;
   435 	TUint8* dstPtr  = NULL;
   436 	const TUint    srcLen  = aSrc->Length();
   437 	const TUint    dstLen  = aDst->Length();
   438 	TInt	srcUsed = 0;
   439 	TInt	dstUsed = 0;
   440 
   441 
   442 	//**************************************************
   443 	//* Get Input Data:  Only want to process more input
   444 	//* data if the output buffer is empty.
   445 	//**************************************************
   446 
   447 	if ( iOutBufferCount == 0 )
   448 		{
   449 		srcPtr = CONST_CAST(TUint8*, aSrc->Ptr());
   450 
   451 
   452 		//*************************************************
   453 		//* If the input buffer is empty, and there is
   454 		//* enough data in the input stream, then use the
   455 		//* data from the input stream.  Else must append
   456 		//* available input data to the input buffer.
   457 		//*************************************************
   458 
   459 		if ( (iInBufferCount == 0) && (srcLen >= KGsmEncodedFrameSize) )
   460 			{
   461 			srcUsed = KGsmEncodedFrameSize;
   462 			}
   463 		else
   464 			{
   465 			TInt canCache = KGsmEncodedFrameSize - iInBufferCount;
   466 			srcUsed = Min (canCache, srcLen);
   467 
   468 			for (TInt count = 0; count < srcUsed; count++)
   469 				{
   470 				//not worth use a mem copy
   471 				*iInBufferPtr++ = *srcPtr++;
   472 				}
   473 
   474 
   475 			//*************************************************
   476 			//* If the input buffer is now full, then we can
   477 			//* process this data. Otherwise, we don't have
   478 			//* enough data so set srcPtr to NULL to indicate
   479 			//* that there's no data to process yet.
   480 			//*************************************************
   481 
   482 			srcPtr = NULL;
   483 			iInBufferCount += srcUsed;
   484 			if ( iInBufferCount == KGsmEncodedFrameSize )
   485 				{
   486 				srcPtr         = iInBuffer;
   487 				iInBufferPtr   = iInBuffer;
   488 				iInBufferCount = 0;
   489 				}
   490 			}
   491 		}
   492 
   493 
   494 	//*************************************************
   495 	//* If there is enough input data, then determine
   496 	//* where the output should go (output stream or
   497 	//* output buffer if output stream doesn't have
   498 	//* enough room).  Then decode the data.
   499 	//*************************************************
   500 
   501 	if ( srcPtr != NULL )
   502 		{
   503 		// Determine where to put output data
   504 		dstPtr = CONST_CAST(TUint8*, aDst->Ptr());
   505 		dstUsed = KPcmInputFrameSize;
   506 
   507 		if ( dstLen < KPcmInputFrameSize )
   508 			{
   509 			dstPtr = iOutBuffer;
   510 			iOutBufferCount = KPcmInputFrameSize;
   511 			}
   512 
   513 		// Decode the data
   514 		iGsmDecoder->ExecuteL (srcPtr, dstPtr);
   515 		}
   516 
   517 
   518 	//*************************************************
   519 	//* If any data is stored in the output buffer,
   520 	//* then output as much of it as well fit in the
   521 	//* output stream.
   522 	//*************************************************
   523 
   524 	if ( iOutBufferCount > 0 )
   525 		{
   526 		dstUsed = Min ((TInt)iOutBufferCount, (TInt)dstLen);
   527 		TPtrC8 outPtr (iOutBufferPtr, dstUsed);
   528 
   529 		aDst->SetLength(0);
   530 		aDst->Append (outPtr);
   531 
   532 		iOutBufferCount -= dstUsed;
   533 		iOutBufferPtr   += dstUsed;
   534 
   535 		if ( iOutBufferCount == 0 )
   536 			{
   537 			iOutBufferPtr = iOutBuffer;
   538 			}
   539 		}
   540 
   541 
   542 	//*************************************************
   543 	//* Modify the length attributes of the source and
   544 	//* destination data streams to inform the caller
   545 	//* of how much data was used in each buffer.
   546 	//*************************************************
   547 
   548 	aSrc->SetLength(srcUsed); 
   549 	aDst->SetLength(dstUsed); 
   550 
   551 	}
   552 
   553 
   554 //*******************************************************************
   555 //* FUNCTION:  C16PcmToGsmWavCodec::C16PcmToGsmWavCodec
   556 //*   Constructor for 16 bit PCM to GSM Codec.
   557 //*******************************************************************
   558 
   559 C16PcmToGsmWavCodec::C16PcmToGsmWavCodec()
   560 	{
   561 
   562 	Reset();
   563 
   564 	}
   565 
   566 
   567 //*******************************************************************
   568 //* FUNCTION:  C16PcmToGsmWavCodec::~C16PcmToGsmWavCodec
   569 //*   Destructor for 16 bit PCM to GSM Codec.
   570 //*******************************************************************
   571 
   572 C16PcmToGsmWavCodec::~C16PcmToGsmWavCodec()
   573 	{
   574 
   575 	delete iGsmEncoder;
   576 
   577 	}
   578 
   579 
   580 //*******************************************************************
   581 //* FUNCTION:  C16PcmToGsmWavCodec::ConstructL
   582 //*   Perform 2nd pass of object construction (allocating data on heap).
   583 //*******************************************************************
   584 
   585 void C16PcmToGsmWavCodec::ConstructL()
   586 	{
   587 
   588 	iGsmEncoder = new (ELeave) CGSM610FR_Encoder;
   589 	iGsmEncoder->ConstructL();
   590 	iGsmEncoder->StartL();
   591 	iInBufferCount  = 0;
   592 	iOutBufferCount = 0;
   593 
   594 	}
   595 
   596 
   597 //*******************************************************************
   598 //* FUNCTION:  C16PcmToGsmWavCodec::Reset
   599 //*   Reset the input/output buffer states.
   600 //*******************************************************************
   601 
   602 void C16PcmToGsmWavCodec::Reset()
   603 	{
   604 
   605 	iInBufferPtr    = iInBuffer;
   606 	iOutBufferPtr   = iOutBuffer;
   607 	}
   608 
   609 
   610 void C16PcmToGsmWavCodec::ResetAllL()
   611 	{
   612 	Reset();
   613 	iInBufferCount  = 0;
   614 	iOutBufferCount = 0;
   615  
   616 	iGsmEncoder->StartL();
   617 	}
   618 
   619 
   620 //*******************************************************************
   621 //* FUNCTION:  C16PcmToGsmWavCodec::ProcessL
   622 //*   Read raw 16 bit PCM data (contained in aSrc) and convert to
   623 //*   GSM data and return to caller (in aDst).
   624 //*
   625 //*   NOTE that amount of data contained in input/output buffers
   626 //*   varies, so if there is not enough input data or not enough
   627 //*   room for the output data, then this function must buffer
   628 //*   the data until enough data is received (or removed).
   629 //*
   630 //*   NOTE that this function only buffers input (or output) data
   631 //*   if there is not enough data (or room for output) available
   632 //*   in the input (output) stream.  Otherwise, the data is accessed
   633 //*   directly from the input (output) stream which saves unnecessary
   634 //*   copying of data.
   635 //*******************************************************************
   636 
   637 
   638 void C16PcmToGsmWavCodec::ProcessL(TMMFPtr8* aSrc, TMMFPtr8* aDst)
   639 	{
   640 	TUint8* srcPtr  = NULL;
   641 	TUint8* dstPtr  = NULL;
   642 	const TUint    srcLen  = aSrc->Length();
   643 	const TUint    dstLen  = aDst->Length();
   644 	TInt	srcUsed = 0;
   645 	TInt	dstUsed = 0;
   646 
   647 
   648 	//**************************************************
   649 	//* Get Input Data:  Only want to process more input
   650 	//* data if the output buffer is empty.
   651 	//**************************************************
   652 
   653 	if ( iOutBufferCount == 0 )
   654 		{
   655 		srcPtr = CONST_CAST(TUint8*, aSrc->Ptr());
   656 
   657 
   658 		//*************************************************
   659 		//* If the input buffer is empty, and there is
   660 		//* enough data in the input stream, then use the
   661 		//* data from the input stream.  Else must append
   662 		//* available input data to the input buffer.
   663 		//*************************************************
   664 
   665 		if ( (iInBufferCount == 0) && (srcLen >= KPcmInputFrameSize) )
   666 			{
   667 			srcUsed = KPcmInputFrameSize;
   668 			}
   669 		else
   670 			{
   671 			TInt canCache = KPcmInputFrameSize - iInBufferCount;
   672 			srcUsed = Min (canCache, srcLen);
   673 
   674 			for (TInt count = 0; count < srcUsed; count++)
   675 				{
   676 				*iInBufferPtr++ = *srcPtr++;
   677 				}
   678 
   679 
   680 			//*************************************************
   681 			//* If the input buffer is now full, then we can
   682 			//* process this data. Otherwise, we don't have
   683 			//* enough data so set srcPtr to NULL to indicate
   684 			//* that there's no data to process yet.
   685 			//*************************************************
   686 
   687 			srcPtr = NULL;
   688 			iInBufferCount += srcUsed;
   689 			if ( iInBufferCount == KPcmInputFrameSize )
   690 				{
   691 				srcPtr         = iInBuffer;
   692 				iInBufferPtr   = iInBuffer;
   693 				iInBufferCount = 0;
   694 				}
   695 			}
   696 		}
   697 
   698 
   699 	//*************************************************
   700 	//* If there is enough input data, then determine
   701 	//* where the output should go (output stream or
   702 	//* output buffer if output stream doesn't have
   703 	//* enough room).  Then encode the data.
   704 	//*************************************************
   705 
   706 	if ( srcPtr != NULL )
   707 		{
   708 		// Determine where to put output data
   709 		dstPtr = CONST_CAST(TUint8*, aDst->Ptr());
   710 		dstUsed = KGsmEncodedFrameSize;
   711 
   712 		if ( dstLen < KGsmEncodedFrameSize )
   713 			{
   714 			dstPtr = iOutBuffer;
   715 			iOutBufferCount = KGsmEncodedFrameSize;
   716 			}
   717 
   718 		// Encode the data
   719 		iGsmEncoder->ExecuteL (srcPtr, dstPtr);
   720 		}
   721 
   722 
   723 	//*************************************************
   724 	//* If any data is stored in the output buffer,
   725 	//* then output as much of it as well fit in the
   726 	//* output stream.
   727 	//*************************************************
   728 
   729 	if ( iOutBufferCount > 0 )
   730 		{
   731 		dstUsed = Min ((TInt)iOutBufferCount, (TInt)dstLen);
   732 		TPtrC8 outPtr (iOutBufferPtr, dstUsed);
   733 
   734 		aDst->SetLength(0);
   735 		aDst->Append (outPtr);
   736 
   737 		iOutBufferCount -= dstUsed;
   738 		iOutBufferPtr   += dstUsed;
   739 
   740 		if ( iOutBufferCount == 0 )
   741 			{
   742 			iOutBufferPtr = iOutBuffer;
   743 			}
   744 		}
   745 
   746 
   747 	//*************************************************
   748 	//* Modify the length attributes of the source and
   749 	//* destination data streams to inform the caller
   750 	//* of how much data was used in each buffer.
   751 	//*************************************************
   752 
   753 	aSrc->SetLength(srcUsed); 
   754 	aDst->SetLength(dstUsed); 
   755 
   756 
   757 	}
   758