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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 // Private Generic Library includes
22 #include <ecom/implementationproxy.h>
25 #include <mmf/plugin/mmfcodecimplementationuids.hrh>
28 //*******************************************************************
29 //* GSM Codec to 16 bit PCM Class:
30 //*******************************************************************
32 // __________________________________________________________________________
35 CMMFCodec* CMMFGsmTo16PcmCodec::NewL(TAny* aInitParams)
37 CMMFGsmTo16PcmCodec* self=new(ELeave) CMMFGsmTo16PcmCodec();
38 CleanupStack::PushL(self);
39 self->ConstructL(aInitParams);
40 CleanupStack::Pop(self);
41 return STATIC_CAST( CMMFCodec*, self );
44 CMMFGsmTo16PcmCodec::~CMMFGsmTo16PcmCodec()
49 CMMFGsmTo16PcmCodec::CMMFGsmTo16PcmCodec()
54 void CMMFGsmTo16PcmCodec::ConstructL(TAny* /*aInitParams*/)
56 iCodecPtr = new (ELeave) CGsmTo16PcmWavCodec();
57 iCodecPtr->ConstructL();
62 //handy porting stuff from old MS
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());
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());
74 TCodecProcessResult CMMFGsmTo16PcmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
80 TCodecProcessResult result;
81 result.iStatus = TCodecProcessResult::EProcessIncomplete;
83 //convert from generic CMMFBuffer to CMMFDataBuffer
84 iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
85 iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
87 const TUint srcLen = iSrc->Data().Length();
88 const TUint dstMaxLen = iDst->Data().MaxLength() - iDst->Position();
90 // This is checked only on the first frame.
91 if ((dstMaxLen < KPcmInputFrameSize) && (iSrc->FrameNumber() <= 1))
92 User::Leave(KErrArgument);
94 TUint dstAccumulator = 0;
95 TUint srcAccumulator = 0;
97 TUint dstAdded = KPcmInputFrameSize;
100 if ((iSrc->FrameNumber() == 1) && (iSrc->Position() == 0))
102 iCodecPtr->ResetAllL();
105 if ((iLastFrameNumber != 0) && (iSrc->FrameNumber() <= 1) &&
106 (iDst->Position() == 0) && (iSrc->Position() == 0))
108 iCodecPtr->ResetAllL();
111 iLastFrameNumber = iSrc->FrameNumber();
113 TInt srcShift = iSrc->Position();
114 TInt dstShift = iDst->Position(); // Add offset for Dst Buffer
116 while ((dstAccumulator < dstMaxLen) && (dstAdded))
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);
125 //codecDst.Shift(dstAccumulator);
126 codecDst.Shift(dstAccumulator + dstShift); // Add offset for Dst Buffer
128 iCodecPtr->ProcessL(&codecSrc, &codecDst);
130 dstAdded = codecDst.Length();
131 srcAdded = codecSrc.Length();
133 //rules to trigger a codec reset
134 if (dstAdded == KPcmInputFrameSize)
139 dstAccumulator += codecDst.Length();
140 srcAccumulator += codecSrc.Length();
144 //iDst->Data().SetLength(dstAccumulator);
145 iDst->Data().SetLength(dstAccumulator + dstShift); // Add offset for Dst Buffer
147 result.iSrcBytesProcessed = srcAccumulator;
148 result.iDstBytesAdded = dstAccumulator;
155 if (result.iSrcBytesProcessed + iSrc->Position() >= srcLen)
156 result.iStatus = TCodecProcessResult::EProcessComplete;
158 if (result.iDstBytesAdded < dstMaxLen)
159 result.iStatus = TCodecProcessResult::EDstNotFilled;
165 //*******************************************************************
166 //* 16 bit PCM to GSM Codec Class:
167 //*******************************************************************
169 // __________________________________________________________________________
172 CMMFCodec* CMMF16PcmToGsmCodec::NewL(TAny* aInitParams)
174 CMMF16PcmToGsmCodec* self=new(ELeave) CMMF16PcmToGsmCodec();
175 CleanupStack::PushL(self);
176 self->ConstructL(aInitParams);
177 CleanupStack::Pop(self);
178 return STATIC_CAST( CMMFCodec*, self );
181 CMMF16PcmToGsmCodec::~CMMF16PcmToGsmCodec()
186 CMMF16PcmToGsmCodec::CMMF16PcmToGsmCodec()
191 void CMMF16PcmToGsmCodec::ConstructL(TAny* /*aInitParams*/)
193 iCodecPtr = new (ELeave) C16PcmToGsmWavCodec();
194 iCodecPtr->ConstructL();
195 iLastFrameNumber = 0;
198 //handy porting stuff from old MS
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());
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());
211 TCodecProcessResult CMMF16PcmToGsmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
218 TCodecProcessResult result;
219 result.iStatus = TCodecProcessResult::EProcessIncomplete;
221 //convert from generic CMMFBuffer to CMMFDataBuffer
222 iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
223 iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
225 //const TUint srcLen = iSrc->Data().Length();
226 TUint srcLen = iSrc->Data().Length();
227 const TUint dstMaxLen = iDst->Data().MaxLength() - iDst->Position();
229 // This is checked only on the first frame.
230 if ((dstMaxLen < KGsmEncodedFrameSize) && (iSrc->FrameNumber() <= 1))
231 User::Leave(KErrArgument);
234 TUint dstAccumulator = 0;
235 TUint srcAccumulator = iSrc->Position();
240 if ((iSrc->FrameNumber() == 1) && (iSrc->Position() == 0))
242 iCodecPtr->ResetAllL();
245 if ((iLastFrameNumber != 0) && (iSrc->FrameNumber() <= 1) &&
246 (iDst->Position() == 0) && (iSrc->Position() == 0))
248 iCodecPtr->ResetAllL();
251 iLastFrameNumber = iSrc->FrameNumber();
253 // TInt dstShift = iSrc->Position();
254 TInt dstShift = iDst->Position();
256 while (srcAccumulator < srcLen)
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);
266 //this code chops the data buffer into 640 (or less) byte chunks
267 codecSrc.Set(copySrcPtr/*iSrc->Data()*/);
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);
276 iCodecPtr->ProcessL(&codecSrc, &codecDst);
278 dstAdded = codecDst.Length();
279 srcAdded = codecSrc.Length();
281 //rules to trigger a codec reset
282 if ((dstAdded == KGsmEncodedFrameSize) && (srcAdded == KPcmInputFrameSize))
287 dstAccumulator += codecDst.Length();
288 srcAccumulator += codecSrc.Length();
290 CleanupStack::PopAndDestroy(copySrc);
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)
297 iDst->Data().SetLength(dstAccumulator + iDst->Position());
299 result.iSrcBytesProcessed = srcAccumulator;
300 result.iDstBytesAdded = dstAccumulator;
307 if (result.iSrcBytesProcessed + iSrc->Position() >= srcLen)
308 result.iStatus = TCodecProcessResult::EProcessComplete;
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
323 // __________________________________________________________________________
324 // Exported proxy for instantiation method resolution
325 // Define the interface UIDs
328 const TImplementationProxy ImplementationTable[] =
330 IMPLEMENTATION_PROXY_ENTRY(KMmfUidCodecGSM610ToPCM16, CMMFGsmTo16PcmCodec::NewL),
331 IMPLEMENTATION_PROXY_ENTRY(KMmfUidCodecPCM16ToGSM610, CMMF16PcmToGsmCodec::NewL)
337 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
339 aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
341 return ImplementationTable;
345 //*******************************************************************
346 //* FUNCTION: CGsmTo16PcmWavCodec::CGsmTo16PcmWavCodec
347 //* Constructor for GSM to 16 bit PCM Codec.
348 //*******************************************************************
350 CGsmTo16PcmWavCodec::CGsmTo16PcmWavCodec()
358 //*******************************************************************
359 //* FUNCTION: CGsmTo16PcmWavCodec::~CGsmTo16PcmWavCodec
360 //* Destructor for GSM to 16 bit PCM Codec.
361 //*******************************************************************
363 CGsmTo16PcmWavCodec::~CGsmTo16PcmWavCodec()
371 //*******************************************************************
372 //* FUNCTION: CGsmTo16PcmWavCodec::ConstructL
373 //* Perform 2nd pass of object construction (allocating data on heap).
374 //*******************************************************************
376 void CGsmTo16PcmWavCodec::ConstructL()
378 iGsmDecoder = new (ELeave) CGSM610FR_Decoder;
379 iGsmDecoder->ConstructL();
380 iGsmDecoder->StartL();
387 //*******************************************************************
388 //* FUNCTION: CGsmTo16PcmWavCodec::Reset
389 //* Reset the input/output buffer states.
390 //*******************************************************************
392 void CGsmTo16PcmWavCodec::Reset()
394 iInBufferPtr = iInBuffer;
395 iOutBufferPtr = iOutBuffer;
399 //*******************************************************************
400 //* FUNCTION: CGsmTo16PcmWavCodec::Reset
401 //* Reset the input/output buffer states.
402 //*******************************************************************
404 void CGsmTo16PcmWavCodec::ResetAllL()
410 iGsmDecoder->StartL();
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).
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).
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
429 //*******************************************************************
431 void CGsmTo16PcmWavCodec::ProcessL(TMMFPtr8* aSrc, TMMFPtr8* aDst)
434 TUint8* srcPtr = NULL;
435 TUint8* dstPtr = NULL;
436 const TUint srcLen = aSrc->Length();
437 const TUint dstLen = aDst->Length();
442 //**************************************************
443 //* Get Input Data: Only want to process more input
444 //* data if the output buffer is empty.
445 //**************************************************
447 if ( iOutBufferCount == 0 )
449 srcPtr = CONST_CAST(TUint8*, aSrc->Ptr());
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 //*************************************************
459 if ( (iInBufferCount == 0) && (srcLen >= KGsmEncodedFrameSize) )
461 srcUsed = KGsmEncodedFrameSize;
465 TInt canCache = KGsmEncodedFrameSize - iInBufferCount;
466 srcUsed = Min (canCache, srcLen);
468 for (TInt count = 0; count < srcUsed; count++)
470 //not worth use a mem copy
471 *iInBufferPtr++ = *srcPtr++;
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 //*************************************************
483 iInBufferCount += srcUsed;
484 if ( iInBufferCount == KGsmEncodedFrameSize )
487 iInBufferPtr = iInBuffer;
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 //*************************************************
501 if ( srcPtr != NULL )
503 // Determine where to put output data
504 dstPtr = CONST_CAST(TUint8*, aDst->Ptr());
505 dstUsed = KPcmInputFrameSize;
507 if ( dstLen < KPcmInputFrameSize )
510 iOutBufferCount = KPcmInputFrameSize;
514 iGsmDecoder->ExecuteL (srcPtr, dstPtr);
518 //*************************************************
519 //* If any data is stored in the output buffer,
520 //* then output as much of it as well fit in the
522 //*************************************************
524 if ( iOutBufferCount > 0 )
526 dstUsed = Min ((TInt)iOutBufferCount, (TInt)dstLen);
527 TPtrC8 outPtr (iOutBufferPtr, dstUsed);
530 aDst->Append (outPtr);
532 iOutBufferCount -= dstUsed;
533 iOutBufferPtr += dstUsed;
535 if ( iOutBufferCount == 0 )
537 iOutBufferPtr = iOutBuffer;
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 //*************************************************
548 aSrc->SetLength(srcUsed);
549 aDst->SetLength(dstUsed);
554 //*******************************************************************
555 //* FUNCTION: C16PcmToGsmWavCodec::C16PcmToGsmWavCodec
556 //* Constructor for 16 bit PCM to GSM Codec.
557 //*******************************************************************
559 C16PcmToGsmWavCodec::C16PcmToGsmWavCodec()
567 //*******************************************************************
568 //* FUNCTION: C16PcmToGsmWavCodec::~C16PcmToGsmWavCodec
569 //* Destructor for 16 bit PCM to GSM Codec.
570 //*******************************************************************
572 C16PcmToGsmWavCodec::~C16PcmToGsmWavCodec()
580 //*******************************************************************
581 //* FUNCTION: C16PcmToGsmWavCodec::ConstructL
582 //* Perform 2nd pass of object construction (allocating data on heap).
583 //*******************************************************************
585 void C16PcmToGsmWavCodec::ConstructL()
588 iGsmEncoder = new (ELeave) CGSM610FR_Encoder;
589 iGsmEncoder->ConstructL();
590 iGsmEncoder->StartL();
597 //*******************************************************************
598 //* FUNCTION: C16PcmToGsmWavCodec::Reset
599 //* Reset the input/output buffer states.
600 //*******************************************************************
602 void C16PcmToGsmWavCodec::Reset()
605 iInBufferPtr = iInBuffer;
606 iOutBufferPtr = iOutBuffer;
610 void C16PcmToGsmWavCodec::ResetAllL()
616 iGsmEncoder->StartL();
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).
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).
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
635 //*******************************************************************
638 void C16PcmToGsmWavCodec::ProcessL(TMMFPtr8* aSrc, TMMFPtr8* aDst)
640 TUint8* srcPtr = NULL;
641 TUint8* dstPtr = NULL;
642 const TUint srcLen = aSrc->Length();
643 const TUint dstLen = aDst->Length();
648 //**************************************************
649 //* Get Input Data: Only want to process more input
650 //* data if the output buffer is empty.
651 //**************************************************
653 if ( iOutBufferCount == 0 )
655 srcPtr = CONST_CAST(TUint8*, aSrc->Ptr());
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 //*************************************************
665 if ( (iInBufferCount == 0) && (srcLen >= KPcmInputFrameSize) )
667 srcUsed = KPcmInputFrameSize;
671 TInt canCache = KPcmInputFrameSize - iInBufferCount;
672 srcUsed = Min (canCache, srcLen);
674 for (TInt count = 0; count < srcUsed; count++)
676 *iInBufferPtr++ = *srcPtr++;
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 //*************************************************
688 iInBufferCount += srcUsed;
689 if ( iInBufferCount == KPcmInputFrameSize )
692 iInBufferPtr = iInBuffer;
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 //*************************************************
706 if ( srcPtr != NULL )
708 // Determine where to put output data
709 dstPtr = CONST_CAST(TUint8*, aDst->Ptr());
710 dstUsed = KGsmEncodedFrameSize;
712 if ( dstLen < KGsmEncodedFrameSize )
715 iOutBufferCount = KGsmEncodedFrameSize;
719 iGsmEncoder->ExecuteL (srcPtr, dstPtr);
723 //*************************************************
724 //* If any data is stored in the output buffer,
725 //* then output as much of it as well fit in the
727 //*************************************************
729 if ( iOutBufferCount > 0 )
731 dstUsed = Min ((TInt)iOutBufferCount, (TInt)dstLen);
732 TPtrC8 outPtr (iOutBufferPtr, dstUsed);
735 aDst->Append (outPtr);
737 iOutBufferCount -= dstUsed;
738 iOutBufferPtr += dstUsed;
740 if ( iOutBufferCount == 0 )
742 iOutBufferPtr = iOutBuffer;
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 //*************************************************
753 aSrc->SetLength(srcUsed);
754 aDst->SetLength(dstUsed);