multimediacommscontroller/mmccamrpayloadformat/src/amrpayloadformatread.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccamrpayloadformat/src/amrpayloadformatread.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1173 @@
+/*
+* Copyright (c) 2004-2006 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 plugin capable to read RTP payload containing
+*                AMR audio.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <mmf/common/mmffourcc.h>
+#include "amrpayloadformatread.h"
+#include "amrpayloadencoder.h"
+#include "amrpayloaddecoder.h"
+#include "amrpayloaddecoderoa.h"
+#include "amrpayloadformatutil.h"
+#include "amrcommonutil.h"
+#include "mccrtpdatasource.h"
+#include "mccuids.hrh"
+#include "mccinternaldef.h"
+#include "amrpayloadformatter.h"
+#include "mccredpayloadread.h"
+
+#ifdef VOIP_TRACE_ENABLED
+#include <voip_trace.h>
+#endif
+
+// CONSTANTS
+const TReal KTimeMultiplier = 0.001;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::CAmrPayloadFormatRead
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CAmrPayloadFormatRead::CAmrPayloadFormatRead ( ) :
+    iIsNb( ETrue ), iSamplingRate( KAmrNbSampleRate ), iChannels( 1 ),
+    iMode( EAmrFrame12_2 ), iCmr ( EAmrModeReq7 ), iStreamEncoder( TStreamEncoder() )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::ConstructL ( MDataSource* aSource )
+    {
+    User::LeaveIfNull( aSource );
+
+    iRtpDataSource = aSource;
+    iClip = aSource;
+    iBufferToReadExists = EFalse;
+
+    iFourCC.Set( TFourCC( ' ','A','M','R' ) );
+
+    // Set default value of iChannels and iFramesPerPacket
+    iFramesPerPacket = 1;
+    iChannels = 1;
+    
+    // Initialize decoding state machine
+    iStateMachine = CFormatDecodeStateMachine::NewL( this );
+    iStateMachine->ChangeState( EDecodeIdle );
+
+    iCurrentBuffer = EBufferOne;
+    
+    #ifdef FTD_ENABLED
+    
+    User::LeaveIfError( iJBufStatsQueue.OpenGlobal( KMccJBufferStats, 
+        EOwnerProcess ) );    
+    
+    #endif        
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::NewL
+//
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CAmrPayloadFormatRead* CAmrPayloadFormatRead::NewL ( MDataSource* aSource )
+    {
+    __ASSERT_ALWAYS( aSource, User::Leave( KErrArgument ) );
+
+    AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::NewL" );
+    
+    CAmrPayloadFormatRead* self = new ( ELeave ) CAmrPayloadFormatRead;
+    CleanupStack::PushL ( self );
+    self->ConstructL ( aSource );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::~CAmrPayloadFormatRead
+//
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CAmrPayloadFormatRead::~CAmrPayloadFormatRead ( )
+    {
+    // commented out CreateSourceBufferL now sets aReference to ETrue.
+    // datapath doesn't clean this buffer any longer.
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead: 0x%x", this );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iFrameBufferOne: 0x%x", iFrameBufferOne );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iFrameBufferTwo: 0x%x", iFrameBufferTwo );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iSourceBuffer: 0x%x", iSourceBuffer );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iStateMachine: 0x%x", iStateMachine );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iPayloadDecoder: 0x%x", iPayloadDecoder );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iRtpDataSource: 0x%x", iRtpDataSource );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iClip: 0x%x", iClip );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iDataPath: 0x%x", iDataPath );
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::~CAmrPayloadFormatRead iBufferToRead: 0x%x", iBufferToRead );
+    #endif
+    
+
+    delete iFrameBufferOne;
+    delete iFrameBufferTwo;
+    if ( iSourceBufOwnership )
+        {
+        delete iSourceBuffer;
+        }
+    iSourceBuffer = NULL;
+
+    if ( iStateMachine )
+        {
+        iStateMachine->Cancel( );
+        delete iStateMachine;
+        }
+    
+    delete iPayloadDecoder;
+    iRtpDataSource = NULL;
+    iClip = NULL;
+    iDataPath = NULL;
+    iBufferToRead = NULL;
+    iEventHandler = NULL;
+
+    #ifdef FTD_ENABLED
+    iJBufStatsQueue.Close();
+    #endif
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::Streams
+// Return number of audio streams for the given media
+// -----------------------------------------------------------------------------
+//
+TUint CAmrPayloadFormatRead::Streams( TUid aMediaType ) const
+    {
+    if ( KUidMediaTypeAudio == aMediaType )
+        {
+        return 1;
+        }
+    else
+        {
+        return 0;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::FrameTimeInterval
+// Return the frame time interval for the given media
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CAmrPayloadFormatRead::FrameTimeInterval( 
+        TMediaId aMediaId ) const
+    {
+    if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        TInt hwFrametime = static_cast<TInt>( iCInfo.iHwFrameTime );
+        return TTimeIntervalMicroSeconds( TInt64( hwFrametime ) );
+        }
+    else
+        {
+        return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::FillBufferL
+// Fill Buffer
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::FillBufferL( CMMFBuffer* aBuffer, 
+        MDataSink* aConsumer, TMediaId aMediaId )
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    	AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillBufferL( )" );
+    #endif
+    
+    User::LeaveIfNull( aBuffer );
+    User::LeaveIfNull( aConsumer );
+
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    	AMR_PAYLOAD_FORMAT_READ3 ( "CAmrPayloadFormatRead::FillBufferL( ) buffer 0x%x passed in with length %d bytes \n", aBuffer, aBuffer->BufferSize( ) );
+    #endif
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %x %x", MCC_TRACE, MCC_AMR_PLF_READ_FILLBUFFERL,
+            aBuffer, aConsumer );
+    #endif
+    
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    if ( KUidMmfDataBuffer != aBuffer->Type( ) )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    iDataPath = aConsumer;
+    iMediaId = aMediaId;
+
+    // aBuffer is a reference to those frame buffers that AmrPayloadFormatRead owns
+    aBuffer->SetLastBuffer( EFalse );
+
+    iFillRequested = ETrue;
+
+    if ( iCurrentBuffer == EBufferOne )
+        {
+        iFrameBufferTwo->SetStatus( EAvailable );
+        }
+    else
+        {
+        iFrameBufferOne->SetStatus( EAvailable );
+        }
+
+    if ( iBufferToReadExists ) // Payload has some frames not decoded
+        {
+        iStateMachine->ChangeState( ESourceDataReady );
+        }
+    else
+        {
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ 
+        	AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillBufferL( ), Request data from source\n" );
+        #endif
+
+        FillSourceBufferL(); // No payload ask for it
+        } 
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::DoRead
+// Reads data starting from the given position into the source buffer 
+// -----------------------------------------------------------------------------
+//
+TBool CAmrPayloadFormatRead::DoRead( CMMFBuffer* aBuffer )
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::DoRead" );
+    #endif
+    #ifdef VOIP_MCC_DL_TRACE_ENABLED
+        VoipTrace( "%x %x %x", MCC_TRACE, MCC_AMR_PLF_READ_DOREAD, aBuffer );
+    #endif
+    
+    if ( !aBuffer )
+        {
+        return EFalse;
+        }
+
+    if ( EFull == aBuffer->Status( ) )
+        {
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        RDebug::Print ( _L ( "CAmrPayloadFormatRead::DoRead - Buffer already full" ) );
+        #endif
+
+        return EFalse;
+        }
+
+    if ( iNumOfFrames == 0 )
+        {
+        return EFalse;
+        }
+        
+    TAmrFrame* frames = iPayloadDecoder->Frames( );
+    TDes8& bufferDes = static_cast<CMMFDataBuffer*>( aBuffer )->Data();
+    TInt byteIndex = bufferDes.Length( );
+    
+    TUint8* desPtr = const_cast<TUint8*>( bufferDes.Ptr( ) );
+    iStreamEncoder.Initialize( desPtr, byteIndex, 0 );
+
+   	#ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    	AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::DoRead - iCurrentFrame = %d",
+    	iCurrentFrame );
+    #endif
+    
+    TInt bitCount = iPayloadDecoder->SpeechBitCount( frames[iCurrentFrame].iFrameType );
+    // Calculate byte count
+    TInt nextFrameLen =
+    	bitCount % TInt(KNumValue8) == 0 ? bitCount / TInt(KNumValue8) : bitCount / TInt(KNumValue8) + 1;
+    
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    	AMR_PAYLOAD_FORMAT_READ4 ( "CAmrPayloadFormatRead::DoRead - iCurrentFrame = %d iNumOfFrames = %d byteIndex = %d",
+        	iCurrentFrame, iNumOfFrames, byteIndex );
+    #endif
+
+    // Construct 8-bit frame header.
+    // +-+-+-+-+-+-+-+-+
+    // |P|  FT   |Q|P|P|
+    // +-+-+-+-+-+-+-+-+
+    iStreamEncoder.Encode( 0, 1 );
+    iStreamEncoder.Encode( TInt( frames[iCurrentFrame].iFrameType ), KNumValue4 );
+    iStreamEncoder.Encode( frames[iCurrentFrame].iFrameQualityInd, 1 );
+    iStreamEncoder.Encode( 0, KNumValue2 );
+    
+    if ( bitCount > 0 )
+        {
+        // Construct core frame part ( speech data )
+        iStreamEncoder.Encode( frames[iCurrentFrame].iFrameData, 0, 
+                               frames[iCurrentFrame].iBitIndex, bitCount );
+        if ( iStreamEncoder.BitIndex( ) != 0 )
+            {
+            // Need padding to byte boundray
+            iStreamEncoder.Encode( 0, KNumValue8 - iStreamEncoder.BitIndex( ) );
+            }
+        }
+
+    // Update iCurrentFrame
+    iCurrentFrame++;
+
+    byteIndex = byteIndex + nextFrameLen + 1;       // Add 1 for frame header byte
+
+    // Get next frame length
+    if ( iCurrentFrame < iNumOfFrames )
+        {
+        bitCount = iPayloadDecoder->SpeechBitCount( frames[iCurrentFrame].iFrameType );
+        // Calculate byte count
+        nextFrameLen =
+        	bitCount % (TInt) KNumValue8 == 0 ? bitCount / (TInt) KNumValue8 : bitCount / (TInt) KNumValue8 + 1;
+        }
+
+    bufferDes.SetLength( byteIndex );
+    
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    	AMR_PAYLOAD_FORMAT_READ4 ( "CAmrPayloadFormatRead::DoRead - after decoding iCurrentFrame = %d iNumOfFrames = %d byteIndex = %d",
+        iCurrentFrame, iNumOfFrames, byteIndex );
+    #endif
+
+    if ( iCurrentFrame == iNumOfFrames )
+        {
+        // Packet is fully decoded.
+        // If it is the last buffer from RtpSourceSink, then we are not
+        // expecting more packets. Also SetLastBuffer to notify datapath.
+        if( iBufferToRead->LastBuffer( ) )
+            {
+            aBuffer->SetLastBuffer( ETrue );
+            aBuffer->SetStatus( EFull );
+            }
+        return ETrue;
+        }
+
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::FillSinkBufferL
+// Read RTP payload and convert it into AMR frames.
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::FillSinkBufferL( )
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillSinkBuffer( )" );
+    #endif
+    #ifdef VOIP_MCC_DL_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_FILLSINKBUFFER );
+    #endif    
+
+    CMMFBuffer* curBuffer;
+    if ( EBufferOne == iCurrentBuffer )
+        {
+        curBuffer = iFrameBufferOne;
+        
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillSinkBuffer( ) - Current Buffer One" );
+        #endif
+        }
+    else
+        {
+        curBuffer = iFrameBufferTwo;
+        
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillSinkBuffer( ) - Current Buffer Two" );
+        #endif
+        }
+
+	curBuffer->SetStatus( EAvailable );
+    TBool allFrmBuffered = DoRead( curBuffer );
+	curBuffer->SetFrameNumber(
+		iRecvHeader.iTimestamp + ( ( iCurrentFrame - 1 )
+	    * TUint( iCInfo.iHwFrameTime * iSamplingRate * KTimeMultiplier ) ) );
+
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    AMR_PAYLOAD_FORMAT_READ2 ( "CAmrPayloadFormatRead::FillSinkBuffer - FRAMENUM: %u",
+        curBuffer->FrameNumber() );
+    #endif	                           
+
+    // Do not wait for the buffer to be filled up. If we do, this will cause jitters in
+    // comfort-noise ( SID frame ) playing since SID-frame packets take considerably less
+    // data bytes and it will delay waiting for many SID-frame packets before forwarding them to 
+    // DataPath for further play-out processing.
+    // Instead, forward the data as soon as we receive and decode one packet
+    // to avoid jitters in play-out.
+    if ( allFrmBuffered )
+        {   
+        iBufferToReadExists = EFalse;
+        }
+
+
+    // Do not forward zero length buffers
+    if ( curBuffer->BufferSize() > 0 )
+        {
+        iStateMachine->ChangeState( EEmptyDataToSink );
+        }
+    else
+        {
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ 
+        	AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillSinkBufferL( ), Request data from source\n" );
+        #endif
+        
+        FillSourceBufferL(); // No payload ask for it                           
+        }
+ 
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+   	AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillSinkBuffer - DONE" );
+    #endif
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::FillSourceBufferL
+// Send fill buffer request to RTP Data Source
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::FillSourceBufferL( )
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::FillSourceBufferL( )" );
+    #endif 
+    
+    iClip->FillBufferL(iSourceBuffer, this, iMediaId );     
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SendDataToSinkL
+// Send full frame buffer to Data Path
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::SendDataToSinkL( )
+    {
+    #ifdef VOIP_MCC_DL_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_SENDDATATOSINKL );
+    #endif
+
+    iFillRequested = EFalse;
+          
+    if ( EBufferOne == iCurrentBuffer )
+        {
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::SendDataToSinkL( ) - BufferOne"  );
+        #endif
+
+        iDataPath->BufferFilledL( iFrameBufferOne );
+        iCurrentBuffer = EBufferTwo;
+        if ( iBufferToReadExists && !iFrameBufferOne->LastBuffer( ) )
+            {
+            // More payload buffer is needed
+            iStateMachine->ChangeState( ESourceDataReady );
+            }
+        }
+    else
+        {
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::SendDataToSinkL( ) - BufferTwo" );
+        #endif
+
+        iDataPath->BufferFilledL( iFrameBufferTwo );
+        iCurrentBuffer = EBufferOne;
+        if ( iBufferToReadExists && !iFrameBufferTwo->LastBuffer( ) )
+            {
+            // More payload buffer is needed
+            iStateMachine->ChangeState( ESourceDataReady );
+            }
+       }
+
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::SendDataToSinkL( ) - DONE" );
+    #endif
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::CreateSourceBufferL
+// Create a source buffer for the given media and indicate in aReference if 
+// buffer is created.
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CAmrPayloadFormatRead::CreateSourceBufferL( TMediaId aMediaId, 
+        TBool &aReference )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_CREATESOURCEBUFFERL );
+    #endif
+
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    // the source buffers belong to AmrPayloadFormatRead not to datapath
+    // aference should be set to ETrue and destried by AmrPayloadFormatRead itself.
+    aReference = ETrue;
+    return iFrameBufferOne; 
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::CreateSourceBufferL
+// Create a source buffer for the given media, setting frame size to match
+// the given sink buffer
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CAmrPayloadFormatRead::CreateSourceBufferL( TMediaId aMediaId,
+        CMMFBuffer& /*aSinkBuffer*/, TBool &aReference )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_CREATESOURCEBUFFERL );
+    #endif
+
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+        {
+        User::Leave( KErrNotSupported );
+        }
+    
+    return CreateSourceBufferL( aMediaId, aReference );
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SourceDataTypeCode
+// Return the source data type ( four CC code ) for the given media
+// -----------------------------------------------------------------------------
+//
+TFourCC CAmrPayloadFormatRead::SourceDataTypeCode( TMediaId aMediaId )
+    {
+    if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        	AMR_PAYLOAD_FORMAT_READ2( 
+        		"CAmrPayloadFormatRead::SourceDataTypeCode: 0x%x", iFourCC.FourCC() );
+        #endif
+        return iFourCC;
+        }
+    else
+        {
+        return TFourCC( ); //defaults to 'NULL' fourCC
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SetSourceDataTypeCode
+// Set the source data type to the given four CC code for the given media
+// -----------------------------------------------------------------------------
+//
+TInt CAmrPayloadFormatRead::SetSourceDataTypeCode( TFourCC aSourceFourCC, 
+        TMediaId aMediaId )
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        	AMR_PAYLOAD_FORMAT_READ2( 
+        		"CAmrPayloadFormatRead::SetSourceDataTypeCode: 0x%x", 
+        		aSourceFourCC.FourCC() );
+    #endif
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %d", MCC_TRACE, MCC_AMR_PLF_READ_SETSOURCEDATATYPECODE,
+            aSourceFourCC.FourCC() );
+    #endif    
+    
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType ) 
+        {
+        return KErrNotSupported;
+        }
+
+    iFourCC = aSourceFourCC;
+    iMediaId = aMediaId;
+
+    if ( aSourceFourCC == KMccFourCCIdAMRWB )
+        {
+        // Nb is set true in the constructor by default.
+        iIsNb = EFalse; 
+        SetSampleRate( KAmrWbSampleRate );
+        }
+        
+    iClip->SetSourceDataTypeCode( iFourCC, iMediaId );
+
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SourceThreadLogon
+// Log in to the source thread
+// -----------------------------------------------------------------------------
+//
+TInt CAmrPayloadFormatRead::SourceThreadLogon( 
+        MAsyncEventHandler& aEventHandler )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_SOURCETHREADLOGON );
+    #endif
+    
+    iEventHandler = &aEventHandler;
+    iClip->SourceThreadLogon( aEventHandler );
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::NegotiateSourceL( MDataSink& aDataSink )
+// Negotiate source settings to match data sink object.
+// Re-size frame buffers if needed
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::NegotiateSourceL( MDataSink& /*aDataSink*/ )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_NEGOTIATESOURCEL );
+    #endif
+
+    iClip->NegotiateSourceL( *this );
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SourceThreadLogoff
+// Log out of the source thread.
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::SourceThreadLogoff( )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_SOURCETHREADLOGOFF );
+    #endif
+
+    iClip->SourceThreadLogoff( );
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::DataBufferFilledL
+// Called after the data buffer is filled. Update the number of bytes read
+// and the current read position for the next read operation.
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::DataBufferFilledL( CMMFBuffer* aBuffer, 
+                                           const TRtpRecvHeader& aRtpHeader )
+    {
+    AMR_PAYLOAD_FORMAT_READ2( "CAmrPayloadFormatRead::DataBufferFilledL TSTAMP: %u",
+        aRtpHeader.iTimestamp )
+    
+    __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( KUidMmfDataBuffer == aBuffer->Type(), 
+        User::Leave( KErrNotSupported) );
+    __ASSERT_ALWAYS( iSourceBuffer == aBuffer, User::Leave( KErrArgument ) );
+    
+    AMR_PAYLOAD_FORMAT_READ2( "CAmrPayloadFormatRead::DataBufferFilledL LEN:%d",
+        iSourceBuffer->Data().Length() )
+    
+    if ( !iSourceBuffer->Data().Size() )
+        {
+        AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::BufferFilledL NO DATA" )
+        
+        // Request for a new buffer or playback is stopped
+        FillSourceBufferL();
+        return;
+        }
+        
+    iBufferToRead = iSourceBuffer;
+	iRecvHeader = aRtpHeader;
+    iBufferToReadExists = ETrue;
+
+    // Get a reference to the data
+    TDes8& srcData = iSourceBuffer->Data();
+
+	iPayloadDecoder->SetPayloadBuffer( srcData );
+	iPayloadDecoder->SetChannelCount( iChannels );
+	iPayloadDecoder->SetFrameBlockCount( iFramesPerPacket );
+
+	// Decoder rips off redundant frames already received and increases
+	// timestamp accordingly. This prevents frame placing too early at
+	// jitter buffer's playout buffer.
+	const TUint32 timeStampIncrement = 
+	    TUint32( iCInfo.iHwFrameTime * iChannels * iSamplingRate * KTimeMultiplier );
+
+	iNumOfFrames = iPayloadDecoder->DecodePayload( iRecvHeader.iTimestamp,
+	                                               timeStampIncrement );
+    
+	iBufferToRead->SetFrameNumber( iRecvHeader.iTimestamp );
+
+	// If the mode request has changed and it is a speech mode, then report
+	// it to subcontroller. Otherwise it can be ignored (RFC3267 4.3.1)
+	const TAmrModeRequest updateCmr = iPayloadDecoder->ModeRequest();
+	if ( updateCmr != iCmr && updateCmr != EAmrModeReqNone )
+	    {
+        AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::BufferFilledL MODE CHANGE" )
+        
+        iCmr = updateCmr;
+        SendAmrEventToClient( EMccInternalAmrEventCmr );
+	    }
+	
+    AMR_PAYLOAD_FORMAT_READ2( "CAmrPayloadFormatRead::BufferFilledL MODE_REQ: %u", updateCmr )
+
+    // Read frame data and forward it to data sink
+    iCurrentFrame = 0;
+
+    // Whenever BufferFilledL is called from RtpSourceSink
+    // Set the state machine to fill sinkbuffer
+    if ( iNumOfFrames )
+        {
+        iStateMachine->ChangeState( ESourceDataReady );
+        }
+    else
+        {
+        AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::BufferFilledL NO ACCEPTED FRAMES" )
+        
+        // Request for a new buffer or playback is stopped
+        FillSourceBufferL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::NumChannels
+// Gets the number of channels
+// -----------------------------------------------------------------------------
+//
+TUint CAmrPayloadFormatRead::NumChannels( )
+    {
+    return KMono;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SampleRate
+// Returns the samplerate
+// -----------------------------------------------------------------------------
+//
+TUint CAmrPayloadFormatRead::SampleRate( )
+    {
+    return iSamplingRate;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SetSampleRate
+// Only supported sample rate for AMR-NB is 8000Hz
+// -----------------------------------------------------------------------------
+//
+TInt CAmrPayloadFormatRead::SetSampleRate ( TUint aSampleRate )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %d", MCC_TRACE, MCC_AMR_PLF_READ_SETSAMPLERATE,
+            aSampleRate );
+    #endif
+    
+    if( (iIsNb && KAmrNbSampleRate != aSampleRate) ||
+        (!iIsNb && KAmrWbSampleRate != aSampleRate) )
+        {
+        return KErrNotSupported;
+        }
+    else
+        {
+        iSamplingRate = aSampleRate;
+        return KErrNone;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::Duration
+// Return the clip duration for the given media.
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CAmrPayloadFormatRead::Duration( TMediaId /*aMediaType*/ ) const
+    {
+    return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::CancelDlRequest( )
+// Cancels the statemachine and resets the buffers
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::CancelDlRequest()
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::CancelDlRequest" );
+    #endif
+
+    iStateMachine->Cancel();
+    iStateMachine->ChangeState( EDecodeIdle );
+    
+    if ( iFrameBufferOne && iFrameBufferTwo )
+        {
+        iFrameBufferOne->SetLastBuffer( EFalse );
+        iFrameBufferTwo->SetLastBuffer( EFalse );
+
+        iFrameBufferOne->SetStatus( EAvailable );
+        iFrameBufferTwo->SetStatus( EAvailable );
+        }
+
+    iBufferToReadExists = EFalse;
+    iCurrentBuffer = EBufferOne;
+    iFillRequested = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SourcePrimeL()
+// 
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::SourcePrimeL()
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::SourcePrimeL" );
+    #endif
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_SOURCEPRIMEL );
+    #endif
+
+    iClip->SourcePrimeL();
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SourcePlayL()
+// Starts the source
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::SourcePlayL()
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::SourcePlayL" );
+    #endif
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_SOURCEPLAYL );
+    #endif
+    
+    #ifdef FTD_ENABLED
+    iLatestSeqNum = 0;
+    iTotalFrames = 0;
+    iLostFrames = 0;
+    #endif
+    
+    // Initialize payload decoder
+    iPayloadDecoder->Initialize();
+    
+    iClip->SourcePlayL();
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SourcePauseL()
+// Pauses the source
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::SourcePauseL()
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::SourcePauseL" );
+    #endif
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_SOURCEPAUSEL );
+    #endif
+
+    this->CancelDlRequest();
+    iClip->SourcePauseL();
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SourceStopL( )
+// Stops the source
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::SourceStopL()
+    {
+    #ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+        AMR_PAYLOAD_FORMAT_READ(  "CAmrPayloadFormatRead::SourceStopL" );
+    #endif
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_AMR_PLF_READ_SOURCESTOPL );
+    #endif
+
+    this->CancelDlRequest();
+    iClip->SourceStopL();
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SinkDataTypeCode()
+// Returns the datatype code for this Format Decoder
+// -----------------------------------------------------------------------------
+//
+TFourCC CAmrPayloadFormatRead::SinkDataTypeCode( TMediaId aMediaId )
+    {
+    if( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        return iFourCC;
+        }
+    else
+        {
+        return TFourCC();
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::ConfigurePayloadFormatL
+// Configure payload decoding parameters.
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::ConfigurePayloadFormatL( const TDesC8& aConfigParams )
+    {
+    AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::ConfigurePayloadFormatL (NB/WB)" );
+    __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
+        User::Leave( KErrArgument ) );
+        
+    TMccCodecInfoBuffer infoBuffer;
+    infoBuffer.Copy( aConfigParams );
+    
+    if ( !infoBuffer().iIsUpdate )
+        {
+        __ASSERT_ALWAYS( infoBuffer().iHwFrameTime, User::Leave( KErrArgument ) );
+        
+        iCInfo = infoBuffer();
+        
+        AMR_PAYLOAD_FORMAT_READ5 ( "CAmrPayloadFormatRead::ConfigurePayloadFormatL \
+            MaxPT: %d HWFS: %d FS: %d RED: %d" , iCInfo.iMaxPtime, iCInfo.iHwFrameTime, 
+            iCInfo.iFrameSize, iCInfo.iRedundancyCount );
+        
+        if ( !iPayloadDecoder )
+            {
+            if ( KAmrCodecModeBandwidthEfficient == iCInfo.iCodecMode )
+                {
+                iPayloadDecoder = CAmrPayloadDecoder::NewL( iIsNb );
+                }
+            else if ( KAmrCodecModeOctetAlign == iCInfo.iCodecMode )
+                {
+                iPayloadDecoder = CAmrPayloadDecoderOA::NewL( iIsNb );
+                }
+            else
+                {
+                AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::ConfigurePayloadFormatL KErrArgument" );
+                User::Leave( KErrArgument );
+                }
+            }
+
+        iFramesPerPacket = iCInfo.iMaxPtime / iCInfo.iHwFrameTime;
+        iPayloadDecoder->SetFrameBlockCount( iFramesPerPacket );
+
+        if ( !iFrameBufferOne )
+            {
+            iFrameBufferOne = CMMFDataBuffer::NewL( iCInfo.iFrameSize );
+            }
+        if ( !iFrameBufferTwo )
+            {
+            iFrameBufferTwo = CMMFDataBuffer::NewL( iCInfo.iFrameSize );
+            }
+            
+        if ( iSourceBufOwnership )	
+            {
+            delete iSourceBuffer;
+            }
+        iSourceBuffer = NULL;
+        
+        TInt plSize = iCInfo.iFrameSize * iFramesPerPacket;
+        
+        if ( EAmrFecUsed == iCInfo.iAlgoUsed )
+            {
+            AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::ConfigurePayloadFormatL - Using AMR FEC" );
+            
+            plSize 
+                = ( 0 <= iCInfo.iMaxRed )
+                ? iCInfo.iFrameSize * ( iFramesPerPacket + ( iCInfo.iMaxRed / iCInfo.iHwFrameTime ) )
+                : iCInfo.iFrameSize * ( iFramesPerPacket + KMaxAmrRedCount );
+            }
+        else if ( EGenRedUsed == iCInfo.iAlgoUsed )
+            {
+            AMR_PAYLOAD_FORMAT_READ2( "CAmrPayloadFormatRead::ConfigurePayloadFormatL, RED LEVEL: %d",
+                iCInfo.iRedundancyCount );
+            
+            if ( iCInfo.iRedundancyCount )
+                {
+                plSize *= iCInfo.iRedundancyCount;
+                }
+            
+            CPayloadFormatRead* redDecoder 
+                = static_cast<CPayloadFormatRead*>( iClip );
+            
+            TMccRedPayloadReadConfig config;
+            config.iRedBlockCount = iCInfo.iRedundancyCount;
+            config.iMaxPayloadSize = iCInfo.iFrameSize * iFramesPerPacket;
+            config.iNumOfEncodings = 1;
+            config.iRedPayloadType = iCInfo.iRedundantPayload;
+            config.InitPayloadTypes();
+            config.iEncPayloadTypes[0] = iCInfo.iPayloadType;
+            TMccRedPayloadReadPckg pckg( config );
+            redDecoder->ConfigurePayloadFormatL( pckg );
+            }
+        else
+            {
+            // NOP
+            }
+        
+        iSourceBuffer = CreateClipBufferL( plSize, iSourceBufOwnership );
+        }
+    else
+        {
+        UpdateConfigurationL( infoBuffer() );
+        }            
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::UpdateConfigurationL
+// Update payload decoder parameters
+// -----------------------------------------------------------------------------
+//
+void CAmrPayloadFormatRead::UpdateConfigurationL( const TMccCodecInfo& aCodecInfo )
+    {
+    AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::UpdateConfigurationL" );
+    
+    if ( iCInfo.iMaxPtime != aCodecInfo.iMaxPtime )
+        {       
+        iFramesPerPacket = aCodecInfo.iMaxPtime / iCInfo.iHwFrameTime;
+        iPayloadDecoder->SetFrameBlockCount( iFramesPerPacket );
+              
+        if ( iSourceBufOwnership )
+            {
+            delete iSourceBuffer;
+            }
+        iSourceBuffer = NULL;
+        
+        TInt plSize = iCInfo.iFrameSize * iFramesPerPacket;
+        
+        if ( EAmrFecUsed == iCInfo.iAlgoUsed )
+            {
+            plSize 
+                = ( 0 <= iCInfo.iMaxRed )
+                ? iCInfo.iFrameSize * ( iFramesPerPacket + ( iCInfo.iMaxRed / iCInfo.iHwFrameTime ) )
+                : iCInfo.iFrameSize * ( iFramesPerPacket + KMaxAmrRedCount );
+            }
+        else
+            {
+            AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::ConfigurePayloadFormatL Not using AMR FEC" )
+            }           
+ 
+        iSourceBuffer = CreateClipBufferL( plSize, iSourceBufOwnership );
+        
+        // Initialize payload decoder
+        iPayloadDecoder->Initialize();
+        
+        iCInfo.iMaxPtime = aCodecInfo.iMaxPtime;
+        }
+    
+    AMR_PAYLOAD_FORMAT_READ( "CAmrPayloadFormatRead::UpdateConfigurationL OUT" )
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::SendAmrEventToClient
+// -----------------------------------------------------------------------------
+//    
+void CAmrPayloadFormatRead::SendAmrEventToClient( 
+    TMccInternalEventType aEventType )
+    {
+    TMccAmrEventData eventData;
+    TInt bitrate = ConvertModeToBitrate( iCmr );
+    eventData.iModeRequestBitrate = bitrate;
+    
+    if ( iEventHandler )
+	    {
+	    TMccEvent event;
+	    event.iEventData = TMccAmrEventDataPackage( eventData );
+	    
+	    TMccInternalEvent internalEvent( KMccAmrFormatterUid, 
+	                                     aEventType,
+	                                     event );
+	                                     
+	    iEventHandler->SendEventToClient( internalEvent );	
+	    }
+#ifdef TRACE_AMR_PAYLOAD_FORMAT_READ
+    else
+	    {
+        AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::SendAmrEventToClient, \
+iEventHandler=NULL" )
+	    }
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::CreateClipBufferL
+// Creates buffer needed in data transfer with format readers clip.
+// -----------------------------------------------------------------------------
+//
+CMMFDataBuffer* CAmrPayloadFormatRead::CreateClipBufferL( 
+        TUint aSize, TBool& aIsOwnBuffer )
+    {
+    AMR_PAYLOAD_FORMAT_READ ( "CAmrPayloadFormatRead::CreateClipBufferL" )
+    CMMFDataBuffer* buffer( NULL );
+    
+    if ( iClip->CanCreateSourceBuffer() )
+        {
+        if ( iClip->DataSourceType() == KUidMmfFormatDecode || 
+             iClip->DataSourceType() == KMccMultiplexerUid )
+            {
+            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;
+    }
+
+// -----------------------------------------------------------------------------
+// CAmrPayloadFormatRead::ConvertModeToBitrate
+// Gives corresponding bitrate for mode request depending
+// on formatter mode (nb/wb)
+// -----------------------------------------------------------------------------
+//
+TInt CAmrPayloadFormatRead::ConvertModeToBitrate( TAmrModeRequest aModeRequest )
+    {
+    if ( iIsNb && aModeRequest < KNumberOfNbModes )
+        {
+        return KAmrNbModes[aModeRequest];
+        }
+    
+    if ( !iIsNb && aModeRequest < KNumberOfWbModes )
+        {
+        return KAmrWbModes[aModeRequest];
+        }
+   
+    return 0;
+    }
+    
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+//  End of File