multimediacommscontroller/mmccilbcpayloadformat/src/ilbcpayloadformatread.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccilbcpayloadformat/src/ilbcpayloadformatread.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,960 @@
+/*
+* Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:    PayloadFormat component capable to read RTP payload containing
+*                ILBC audio.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include    "ilbcpayloadformatread.h"
+#include    "mccrtpdatasource.h"
+#include    "ilbcpayloadformatutil.h"
+#include    "mccinternaldef.h"
+#include    "mccdef.h"
+#include    "mccredpayloadread.h"
+
+// MACROS
+#ifdef _DEBUG
+#define TRACE_ILBC_PAYLOAD_FORMAT_READ
+#endif
+
+
+// FORWARD DECLARATIONS
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::CIlbcPayloadFormatRead
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CIlbcPayloadFormatRead::CIlbcPayloadFormatRead () : 
+        iMediaId( KUidMediaTypeAudio )
+    {
+    
+    };
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::ConstructL( MDataSource* aSource )
+    {
+    __ASSERT_ALWAYS( aSource, User::Leave( KErrArgument ) );
+    
+    iClip = aSource;
+    iBufferToReadExists = EFalse;
+    
+    iFourCC.Set( KMccFourCCIdILBC );
+    
+    // Initialize decoding state machine
+    iStateMachine = CFormatDecodeStateMachine::NewL( this );
+    iStateMachine->ChangeState( EDecodeIdle );
+    
+    iCurrentBuffer = EBufferOne;
+    }
+    
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CIlbcPayloadFormatRead* CIlbcPayloadFormatRead::NewL( MDataSource* aSource )
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CIlbcPayloadFormatRead::NewL") );
+    #endif
+    
+    __ASSERT_ALWAYS( aSource, User::Leave( KErrArgument ) );
+
+    CIlbcPayloadFormatRead* self = new ( ELeave ) CIlbcPayloadFormatRead();
+    CleanupStack::PushL( self );
+    self->ConstructL( aSource );
+    CleanupStack::Pop( self );
+    return self;
+    };
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::~CIlbcPayloadFormatRead()
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CIlbcPayloadFormatRead::~CIlbcPayloadFormatRead()
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CIlbcPayloadFormatRead::~CIlbcPayloadFormatRead") );
+    #endif
+    
+    delete iFrameBufferOne;
+    delete iFrameBufferTwo;
+    if ( iSourceBufOwnership )
+        {
+        delete iSourceBuffer;
+        }
+    else
+        {
+        iSourceBuffer = NULL;
+        }
+    
+    delete iStateMachine;
+    iClip = NULL;
+	iFrameArray.Close();
+    };
+    
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SendDataToSinkL
+// Send full frame buffer to DataPath.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::SendDataToSinkL()
+    {
+    if ( iCurrentBuffer == EBufferOne )
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L( "CIlbcPayloadFormatRead::SendDataToSinkL - BufferOne") );
+        #endif
+        
+        iDataPath->BufferFilledL( iFrameBufferOne );
+        iCurrentBuffer = EBufferTwo;
+        if ( iBufferToReadExists && !iFrameBufferOne->LastBuffer() )
+            {
+            // More payload buffer is ready
+            iStateMachine->ChangeState( ESourceDataReady );
+            }
+        }
+    else
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L( "CIlbcPayloadFormatRead::SendDataToSinkL - BufferTwo") );
+        #endif
+
+        iDataPath->BufferFilledL( iFrameBufferTwo );
+        iCurrentBuffer = EBufferOne;
+        if ( iBufferToReadExists && !iFrameBufferTwo->LastBuffer() )
+            {
+            // More payload buffer is ready
+            iStateMachine->ChangeState( ESourceDataReady );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::FillSinkBuffer
+// Fill SinkBuffer.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::FillSinkBufferL()
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L( "CIlbcPayloadFormatRead::FillSinkBuffer" ) );
+    #endif
+
+    CMMFDataBuffer* curFrameBuffer;
+    if ( EBufferOne == iCurrentBuffer )
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L( "IlbcPayloadFormatRead: Filling EBufferOne reqsize: %d"),
+                iFrameBufferOne->RequestSize() );
+        #endif
+            
+        curFrameBuffer = iFrameBufferOne;
+        }
+    else
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L("IlbcPayloadFormatRead: Filling EBufferTwo reqsize: %d"),
+                iFrameBufferTwo->RequestSize() );
+        #endif
+
+        curFrameBuffer = iFrameBufferTwo;
+        }
+    
+    TDes8& dataDes = curFrameBuffer->Data();
+       
+    dataDes.Zero();
+    dataDes.SetLength( KiLBCNumOfHeaderBytes );
+
+    // Put next frame decoded from RTP payload to the framebuffer
+    iBufferToReadExists = GetNextFrame( dataDes );
+    
+    if ( iCnFrame )
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L ("CIlbcPayloadFormatRead::FillSinkBuffer - ADD CNOISE FRAME HEADER") );
+        #endif
+        dataDes[0] = KCNoiseFrameHeaderByte;
+        dataDes[1] = 0;
+        }
+    else
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L ("CIlbcPayloadFormatRead::FillSinkBuffer - ADD AUDIO FRAME HEADER") );
+        #endif        
+        dataDes[0] = KAudioFrameHeaderByte;
+        dataDes[1] = 0;
+        }
+
+    curFrameBuffer->SetFrameNumber( iRecvHeader.iTimestamp + ( ( iFrameIndex - 1 )
+                                    * TUint( iCInfo.iHwFrameTime * KiLBCSampleRate * 0.001 ) ) );
+
+    if ( KIlbcMode20msFrame == iCInfo.iCodecMode  )
+        {
+        dataDes.SetLength( KiLBCFrameSize20ms + KiLBCNumOfHeaderBytes );
+        }
+    else if( KIlbcMode30msFrame == iCInfo.iCodecMode )
+        {
+        dataDes.SetLength( KiLBCFrameSize30ms + KiLBCNumOfHeaderBytes );
+        }
+    else
+        {
+        // Make PC-LINT happy
+        }        
+        
+    curFrameBuffer->SetStatus( EFull );
+    iStateMachine->ChangeState( EEmptyDataToSink );
+
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L ("CIlbcPayloadFormatRead::FillSinkBuffer - DONE") );
+    #endif
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::FillSourceBufferL
+// Send fill buffer request to RTP Data Source.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::FillSourceBufferL()
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print ( _L("CIlbcPayloadFormatRead::FillSourceBufferL") );
+    #endif
+
+    // RtpSourceSink doesn't really need the Media Id.        
+    iClip->FillBufferL( iSourceBuffer, this, iMediaId );
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SourcePrimeL
+// Prime source.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::SourcePrimeL()
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print (_L ("CIlbcPayloadFormatRead::SourcePrimeL()"));
+    #endif
+    
+    iClip->SourcePrimeL();
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SourcePlayL
+// Start playing.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::SourcePlayL()
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print (_L ("CIlbcPayloadFormatRead::SourcePlayL()"));
+    #endif
+
+    iClip->SourcePlayL();
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SourcePauseL
+// Pause source.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::SourcePauseL()
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CIlbcPayloadFormatRead::SourcePauseL") );
+    #endif
+    
+    iStateMachine->Cancel();
+    iStateMachine->ChangeState( EDecodeIdle );
+    
+    iFrameBufferOne->SetLastBuffer( EFalse );
+    iFrameBufferTwo->SetLastBuffer( EFalse );
+
+    iFrameBufferOne->SetStatus( EAvailable );
+    iFrameBufferTwo->SetStatus( EAvailable );
+
+    iBufferToReadExists = EFalse;
+    iCurrentBuffer = EBufferOne;
+    
+    iClip->SourcePauseL();
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SourceStopL
+// Stop source.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::SourceStopL()
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CIlbcPayloadFormatRead::SourceStopL") );
+    #endif
+    
+    // DO NOT RESET PACKET COUNT BACK TO ZERO HERE
+    // UPPER LAYER MAY CALL LastDlPacketCount LATER
+    iStateMachine->Cancel();
+    iStateMachine->ChangeState( EDecodeIdle );
+    
+    iFrameBufferOne->SetLastBuffer( EFalse );
+    iFrameBufferTwo->SetLastBuffer( EFalse );
+
+    iFrameBufferOne->SetStatus( EAvailable );
+    iFrameBufferTwo->SetStatus( EAvailable );
+
+    iBufferToReadExists = EFalse;
+    iCurrentBuffer = EBufferOne;
+
+    iClip->SourceStopL();
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::BufferFilledL
+// RTP data source has filled buffer.
+// NOTE: Although redundancy is negotiated, sender may deside to send audio 
+// packets without redundancy (RFC2198, ch5).
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::DataBufferFilledL( CMMFBuffer* aBuffer,
+                                            const TRtpRecvHeader& aRecvHeader )
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print (_L ("CIlbcPayloadFormatRead::DataBufferFilledL - TSTAMP: %u"),
+            aRecvHeader.iTimestamp );
+    #endif
+    
+    __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( KUidMmfDataBuffer == aBuffer->Type(), 
+        User::Leave( KErrNotSupported ) );
+    __ASSERT_ALWAYS( iSourceBuffer == aBuffer, User::Leave( KErrArgument ) );
+    
+    iRecvHeader = aRecvHeader;
+    if ( KComfortNoisePT == iRecvHeader.iPayloadType 
+        || KOldComfortNoisePT == iRecvHeader.iPayloadType )
+        {
+        iCnFrame = ETrue;
+        }
+    else 
+        {
+        iCnFrame = EFalse;
+        }
+
+    iNumOfFrames = DecodePayload( iSourceBuffer->Data() );
+
+    // Whenever BufferFilledL is called from RtpSourceSink
+    // Set the state machine to fillsinkbuffer
+    if ( iNumOfFrames )
+        {
+        iBufferToReadExists = ETrue;
+        iSourceBuffer->SetFrameNumber( iRecvHeader.iTimestamp );
+        iStateMachine->ChangeState( ESourceDataReady );
+        }
+    else
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print ( _L("CIlbcPayloadFormatRead::BufferFilledL, decode failed" ) );
+        #endif
+        
+        FillSourceBufferL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SampleRate
+// Returns samplerate.
+// -----------------------------------------------------------------------------
+//
+TUint CIlbcPayloadFormatRead::SampleRate()
+    {
+    return KiLBCSampleRate;
+    }  
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SetSampleRate
+// Set samplerate.
+// -----------------------------------------------------------------------------
+//
+TInt CIlbcPayloadFormatRead::SetSampleRate( TUint aSampleRate )
+    {
+    return ( KiLBCSampleRate == aSampleRate ) ? KErrNone : KErrNotSupported;
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::NumChannels
+// Returns number of channels.
+// -----------------------------------------------------------------------------
+//
+TUint CIlbcPayloadFormatRead::NumChannels()
+    {
+    return KMono;
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SourceThreadLogoff
+// Logout the source thread.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::SourceThreadLogoff()
+    {
+    iClip->SourceThreadLogoff();
+    }
+    
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::NegotiateSourceL
+// Negotiate Source. Not used.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::NegotiateSourceL( MDataSink& aDataSink )
+    {
+    iSink = &aDataSink;
+    iClip->NegotiateSourceL( *this );
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SourceThreadLogon
+// Logon the source thread.
+// -----------------------------------------------------------------------------
+//
+TInt CIlbcPayloadFormatRead::SourceThreadLogon(
+                                        MAsyncEventHandler& aEventHandler
+                                        )
+    {
+    if ( iClip )
+        {
+        iClip->SourceThreadLogon( aEventHandler );
+		return KErrNone;
+        }
+    else
+        {
+        return KErrNotReady;
+        }        
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SetSourceDataTypeCode
+// Sets source datatype fourCC code.
+// -----------------------------------------------------------------------------
+//
+TInt CIlbcPayloadFormatRead::SetSourceDataTypeCode( TFourCC aSourceFourCC,
+    TMediaId aMediaId )
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print (_L ("CIlbcPayloadFormatRead::SetSourceDataTypeCode()"));
+    #endif
+    
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType ) 
+        {
+        return KErrNotSupported;
+        }
+
+    iFourCC = aSourceFourCC;
+    iMediaId = aMediaId;
+
+    iClip->SetSourceDataTypeCode( iFourCC, aMediaId );
+    
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SourceDataTypeCode
+// Returns the current datatype FourCC code.
+// -----------------------------------------------------------------------------
+//
+TFourCC CIlbcPayloadFormatRead::SourceDataTypeCode( TMediaId aMediaId )
+    {
+    if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        return iFourCC;
+        }
+    else
+        {
+        return TFourCC(); //defaults to 'NULL' fourCC
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::SinkDataTypeCode
+// Returns the current datatype FourCC code.
+// -----------------------------------------------------------------------------
+//
+TFourCC CIlbcPayloadFormatRead::SinkDataTypeCode( TMediaId aMediaId )
+    {
+    if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        return iFourCC;
+        }
+    else
+        {
+        return TFourCC(); //defaults to 'NULL' fourCC
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::CreateSourceBufferL
+// Create a source buffer for the given media and indicate in aReference 
+// if buffer is created.
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CIlbcPayloadFormatRead::CreateSourceBufferL( TMediaId aMediaId,
+    TBool &aReference )
+    {
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    // the source buffers belong to IlbcPayloadFormatRead, not to datapath
+    // reference should be set to ETrue and destroyed by IlbcPayloadFormatRead
+    // itself.
+    aReference = ETrue;
+    return iFrameBufferOne; 
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::CreateSourceBufferL
+// Create a source buffer for the given media, setting frame size to match
+// the given sink buffer.
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CIlbcPayloadFormatRead::CreateSourceBufferL(TMediaId aMediaId,
+    CMMFBuffer& /*aSinkBuffer*/, TBool& aReference)
+    {
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+        {
+        User::Leave( KErrNotSupported );
+        }
+        
+    return CreateSourceBufferL( aMediaId, aReference );
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::FillBufferL
+// Fill Buffer.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::FillBufferL( CMMFBuffer* aBuffer, 
+    MDataSink* aConsumer, TMediaId aMediaId )
+    {
+    if ( !aBuffer ) 
+        {
+        User::Leave( KErrGeneral );
+        }
+
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+    RDebug::Print( _L("CIlbcPayloadFormatRead::FillBufferL aBuffer 0x%x length %d bytes"),
+        aBuffer, aBuffer->BufferSize() );
+    #endif
+
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    if ( KUidMmfDataBuffer != aBuffer->Type() )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    iDataPath = aConsumer;
+
+    // aBuffer is a reference to those frame buffers that 
+    // IlbcPayloadFormatRead owns
+    aBuffer->SetLastBuffer( EFalse );
+
+    if ( EBufferOne == iCurrentBuffer )
+        {
+        iFrameBufferTwo->SetStatus( EAvailable );
+        }
+    else
+        {
+        iFrameBufferOne->SetStatus( EAvailable );
+        }
+
+    if ( iBufferToReadExists )
+        {
+        // All decoded frame are not passed to the datapath
+        iStateMachine->ChangeState( ESourceDataReady );
+        }
+    else
+        {
+        // Time to ask more payload from datasource
+        FillSourceBufferL();
+        } 
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::Streams
+// Return number of audio streams for the given media.
+// -----------------------------------------------------------------------------
+//
+TUint CIlbcPayloadFormatRead::Streams( TUid aMediaType ) const
+    {
+    // Need to check aMediaType for audio
+    if ( KUidMediaTypeAudio == aMediaType )
+        {
+        return 1;
+        }
+    else
+        {
+        return 0;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::FrameTimeInterval
+// Return the frame time interval for the given media.
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CIlbcPayloadFormatRead::FrameTimeInterval(
+    TMediaId aMediaId ) const
+    {
+    if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        return iFrameTimeInterval;
+        }
+    else
+        {
+        return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::Duration
+// Return the frame time interval for the given media
+// NOT SUPPORTED
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CIlbcPayloadFormatRead::Duration(
+    TMediaId /*aMediaType*/) const
+    {
+    return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+    }
+    
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::DecodePayload
+// Decodes all audio frames from the received RTP payload buffer. Decoded
+// audio frames are saved to the internal array so that audio frames can be
+// requested one at a time with GetNextFrame() -method.
+// No assumption about frame count in RTP packet is done.
+// -----------------------------------------------------------------------------
+//
+TInt CIlbcPayloadFormatRead::DecodePayload( const TDesC8& aSourceBuffer )
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CIlbcPayloadFormatRead::DecodePayload Src Size: %d" ),
+            aSourceBuffer.Size() );
+    #endif
+    
+    iFrameIndex = 0;
+    
+    const TUint8* framePtr = aSourceBuffer.Ptr();
+    const TUint payloadSize( aSourceBuffer.Size() );
+    const TUint8* endPtr = aSourceBuffer.Ptr() + payloadSize;
+    
+    // Calculate parameters for frame ripping
+    TInt frames( 0 );
+    TUint frameSize( 0 );
+    
+    // Frames of different modes MUST NOT be included within the same payload
+    frameSize = payloadSize % KiLBCFrameSize20ms ? KiLBCFrameSize30ms : KiLBCFrameSize20ms;
+    frames = payloadSize / frameSize;
+    
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CILBCPayloadFormatRead::DecodePayload framesize: %d, frames: %d" ),
+            frameSize, frames );
+    #endif
+    
+    // Construct pointers to frames in payload
+    while ( frames-- )
+        {
+        TPtr8 bufPtr( const_cast<TUint8*>(framePtr), frameSize, frameSize );
+        iFrameArray.Append( bufPtr );
+
+        framePtr += frameSize;
+        
+        if ( framePtr >= endPtr )
+            {
+            frames = 0;
+            }
+        }
+        
+    return iFrameArray.Count();
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::GetNextFrameL
+// Passes next audio frame decoded with DecodePayload(). Return ETrue if decoded
+// frames are remaining.
+// -----------------------------------------------------------------------------
+//
+TBool CIlbcPayloadFormatRead::GetNextFrame( TDes8& aToBuffer )
+    {
+    iFrameIndex++;
+    
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CILBCPayloadFormatRead::GetNextFrame - FrameCount: %d"),
+            iFrameArray.Count() );
+        RDebug::Print( _L("CILBCPayloadFormatRead::GetNextFrame - FrameIndex: %d"),
+            iFrameIndex );
+    #endif    
+    
+    const TInt frmCount = iFrameArray.Count();
+    const TInt toMax = aToBuffer.MaxLength();
+    if ( iFrameIndex < frmCount &&
+        ( iFrameArray[iFrameIndex - 1].MaxLength() <= toMax ) )
+        {
+        aToBuffer.Append( iFrameArray[iFrameIndex - 1] );
+        return ETrue;
+        }
+    else if ( iFrameIndex == frmCount &&
+        ( iFrameArray[iFrameIndex - 1].MaxLength() <= toMax ) )
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CILBCPayloadFormatRead::GetNextFrame SRC_LEN: %d"),
+            iFrameArray[iFrameIndex - 1].Length() );
+        RDebug::Print( _L("CILBCPayloadFormatRead::GetNextFrame SRC_MAX: %d"),
+            iFrameArray[iFrameIndex - 1].MaxLength() );
+        RDebug::Print( _L("CILBCPayloadFormatRead::GetNextFrame DEST_LEN: %d"),
+            aToBuffer.Length() );
+        RDebug::Print( _L("CILBCPayloadFormatRead::GetNextFrame DEST_MAX: %d"),
+            aToBuffer.MaxLength() );
+        #endif
+
+        aToBuffer.Append( iFrameArray[iFrameIndex - 1] );
+        iFrameArray.Reset();
+        return EFalse;
+        }
+    else
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L ( "CILBCPayloadFormatRead::GetNextFrame FALSE" ));
+        #endif
+        
+        iFrameArray.Reset(); 
+        return EFalse;
+        }        
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::ConfigurePayloadFormatL
+// Configure payload decoding parameters.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::ConfigurePayloadFormatL(
+    const TDesC8& aConfigParams )
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CIlbcPayloadFormatRead::ConfigurePayloadFormatL IN") );
+    #endif
+    
+    __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
+        User::Leave( KErrArgument ) );
+        
+    TMccCodecInfoBuffer infoBuffer;
+    infoBuffer.Copy( aConfigParams );
+    
+    if ( !infoBuffer().iIsUpdate )
+        {
+        DoConfigurePayloadFormatL( infoBuffer() );
+        }
+    else
+        {
+        UpdateConfigurationL( infoBuffer() );
+        }
+    
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+    RDebug::Print( _L("CIlbcPayloadFormatRead::ConfigurePayloadFormatL OUT") );
+    #endif
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::UpdateConfigurationL
+// Update payload decoder parameters
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::UpdateConfigurationL(
+    const TMccCodecInfo& aCodecInfo )
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+    RDebug::Print( _L("CIlbcPayloadFormatRead::UpdateConfigurationL IN") );
+    #endif
+    
+    if ( iCInfo.iMaxPtime != aCodecInfo.iMaxPtime ||
+         iCInfo.iPtime != aCodecInfo.iPtime ||
+         iCInfo.iHwFrameTime != aCodecInfo.iHwFrameTime ||
+         iCInfo.iBitrate != aCodecInfo.iBitrate )
+        {
+        // Reconfigure payload formatter and update the sourcebuffer fill
+        // request so that multiplexer gets a update to the possibly changed
+        // buffer.
+        DoConfigurePayloadFormatL( aCodecInfo );
+        FillSourceBufferL();
+        }
+    
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+    RDebug::Print( _L("CIlbcPayloadFormatRead::UpdateConfigurationL OUT") );
+    #endif
+    }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::DoConfigurePayloadFormatL
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatRead::DoConfigurePayloadFormatL( const TMccCodecInfo& aCodecInfo )
+    {
+    __ASSERT_ALWAYS( aCodecInfo.iHwFrameTime != 0, User::Leave( KErrArgument ) );
+    
+    iCInfo = aCodecInfo;
+    
+    // Maximum number of frames in RTP payload
+    const TUint pktCount = TUint8( iCInfo.iMaxPtime / iCInfo.iHwFrameTime );
+    
+    if ( KiLBCBitrateWith20ms == iCInfo.iBitrate )
+        {
+        iCInfo.iHwFrameTime = KiLBCFrameTime20ms;    
+        iCInfo.iFrameSize = KiLBCFrameSize20ms;
+        iFrameTimeInterval = (TInt64) KiLBCFrameTime20ms * pktCount;
+        }
+    else if ( KiLBCBitrateWith30ms == iCInfo.iBitrate )
+        {
+        iCInfo.iHwFrameTime = KiLBCFrameTime30ms;
+        iCInfo.iFrameSize = KiLBCFrameSize30ms;
+        iFrameTimeInterval = (TInt64) KiLBCFrameTime30ms * pktCount;
+		}
+    else
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+            RDebug::Print( _L("CIlbcPayloadFormatRead::DoConfigurePayloadFormatL KErrNotSupported") );
+        #endif
+        User::Leave( KErrNotSupported );
+        }        
+    
+    // Create two frame buffers used in data transfer with datapath.
+    // Space for two byte additional header needed by HW codec is reserved.
+    // 30ms mode buffers can be used also for 20ms mode
+    if ( !iFrameBufferOne && !iFrameBufferTwo )
+        {
+        iFrameBufferOne = 
+            CMMFDataBuffer::NewL( KiLBCFrameSize30ms + KiLBCNumOfHeaderBytes );
+        iFrameBufferTwo = 
+            CMMFDataBuffer::NewL( KiLBCFrameSize30ms + KiLBCNumOfHeaderBytes );
+        }
+    
+    // PayloadBuffer contains data received from network
+    TInt plSize = iCInfo.iFrameSize * pktCount;
+    
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CILBCPayloadFormatRead::DoConfigurePayloadFormatL FramesPerPacket: %d" ), pktCount );
+        RDebug::Print( _L("CILBCPayloadFormatRead::DoConfigurePayloadFormatL FrameSize: %d" ), iCInfo.iFrameSize );
+    #endif
+    
+    if ( EGenRedUsed == iCInfo.iAlgoUsed )
+        {
+        #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CG711PayloadFormatRead::DoConfigurePayloadFormatL, RED LEVEL: %d"),
+            iCInfo.iRedundancyCount );
+        #endif
+        if ( iCInfo.iRedundancyCount )
+            {
+            plSize *= iCInfo.iRedundancyCount;
+            }
+        
+        CPayloadFormatRead* redDecoder 
+            = static_cast<CPayloadFormatRead*>( iClip );
+        
+        TMccRedPayloadReadConfig config;
+        config.iRedBlockCount = iCInfo.iRedundancyCount;
+        config.iMaxPayloadSize = iCInfo.iFrameSize * pktCount;
+        config.iNumOfEncodings = 1;
+        config.iRedPayloadType = iCInfo.iRedundantPayload;
+        config.InitPayloadTypes();
+        config.iEncPayloadTypes[0] = iCInfo.iPayloadType;
+        TMccRedPayloadReadPckg pckg( config );
+        redDecoder->ConfigurePayloadFormatL( pckg );
+        }
+    
+    // PayloadBuffer contains data received from network
+    if ( iSourceBufOwnership )
+        {
+        delete iSourceBuffer;
+        }
+        
+    iSourceBuffer = NULL;
+    iSourceBuffer = CreateClipBufferL( plSize, iSourceBufOwnership );
+    }
+    
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatRead::CreateClipBufferL
+// Creates buffer needed in data transfer with format readers clip.
+// -----------------------------------------------------------------------------
+//
+CMMFDataBuffer* CIlbcPayloadFormatRead::CreateClipBufferL( 
+        TUint aSize, TBool& aIsOwnBuffer )
+    {
+    #ifdef TRACE_ILBC_PAYLOAD_FORMAT_READ
+        RDebug::Print( _L("CIlbcPayloadFormatRead::CreateClipBufferL") );
+    #endif
+    
+    CMMFDataBuffer* buffer( NULL );
+    if ( iClip->CanCreateSourceBuffer() )
+        {
+        static_cast<CMMFFormatDecode*>( iClip )->SuggestSourceBufferSize( aSize );
+        
+        TBool reference( EFalse );
+        CMMFBuffer* sourceBuf 
+            = iClip->CreateSourceBufferL( KUidMediaTypeAudio, reference );
+        TBool isSupportedBuf 
+            = CMMFBuffer::IsSupportedDataBuffer( sourceBuf->Type() );
+        TBool isOwnBuffer = reference ? EFalse : ETrue;
+        
+        if ( !isSupportedBuf )
+            {
+            if ( isOwnBuffer )
+                {
+                delete sourceBuf;
+                }
+            
+            User::Leave( KErrNotSupported );
+            }
+        
+        aIsOwnBuffer = isOwnBuffer;
+        buffer = static_cast<CMMFDataBuffer*>( sourceBuf );
+        }
+    else
+        {
+        aIsOwnBuffer = ETrue;
+        buffer = CMMFDataBuffer::NewL( aSize );
+        }
+    
+    return buffer;
+    }
+    
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+//  End of File