multimediacommscontroller/mmccg711payloadformat/src/g711payloadformatwrite.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccg711payloadformat/src/g711payloadformatwrite.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,675 @@
+/*
+* 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:    Payload format component capable to write RTP payload
+*                containing G711 audio.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "rtpheader.h"
+#include    "g711payloadformatwrite.h"
+#include    "mccrtpdatasink.h"
+#include    "g711payloadformatdefs.h"
+#include    "mccuids.hrh"
+#include    "mccdef.h"
+#include    "mccrtpmediaclock.h"
+#include    "mccredpayloadwrite.h"
+#include    "mccinternaldef.h"
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatRead::CG711PayloadFormatRead
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CG711PayloadFormatWrite::CG711PayloadFormatWrite()
+    {
+    }
+    
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::ConstructL ( MDataSink* aSink )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::ConstructL()" );
+    
+    __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
+    
+    // Set default values
+    iFourCC.Set( KMccFourCCIdG711 );
+    
+    iIsRtpSink = ( KMccRtpSinkUid  == aSink->DataSinkType() );
+    TBool isRedEncoder 
+        = ( TUid::Uid( KImplUidRedPayloadFormatEncode ) == aSink->DataSinkType() );
+    
+    if ( iIsRtpSink )
+        {
+        CMccRtpDataSink* tmp = static_cast<CMccRtpDataSink*>( aSink );
+        iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp );
+        }
+    else if ( isRedEncoder )
+        {
+        CMccRedPayloadWrite* tmp = static_cast<CMccRedPayloadWrite*>( aSink );
+        iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp );
+        iIsRtpSink = ETrue;
+        }
+    else
+        {
+        DP_G711_WRITE( "CG711PayloadFormatWrite::ConstructL, sink not RTP one" );
+        }
+    
+    iClip = aSink;
+    
+    // Initialize state machine
+    iStateMachine = CFormatEncodeStateMachine::NewL( this );
+    iStateMachine->ChangeState( EEncodeIdle );
+    }
+    
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CG711PayloadFormatWrite* CG711PayloadFormatWrite::NewL ( MDataSink* aSink )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::NewL()" );
+    
+    __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
+    
+    CG711PayloadFormatWrite* self = new (ELeave) CG711PayloadFormatWrite;
+    CleanupStack::PushL( self );
+    self->ConstructL( aSink );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// Destructor
+CG711PayloadFormatWrite::~CG711PayloadFormatWrite ()
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::~CG711PayloadFormatWrite()" );
+    if ( iStateMachine )
+        {
+        iStateMachine->Cancel();
+        }
+    
+    // Media clock is not owned
+    if ( iRtpMediaClock )
+        {
+        iRtpMediaClock->UnregisterMediaFormat( iKey );
+        }
+    
+    delete iSourceBuffer;
+    delete iSinkBuffer;
+    delete iStateMachine;
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SinkThreadLogon
+// Passes the logon command to the sink clip
+// -----------------------------------------------------------------------------
+//
+TInt CG711PayloadFormatWrite::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
+    {
+    iClip->SinkThreadLogon( aEventHandler );
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SinkThreadLogoff
+// Passes the logoff command to the sink clip
+// -----------------------------------------------------------------------------
+void CG711PayloadFormatWrite::SinkThreadLogoff()
+    {
+    iClip->SinkThreadLogoff();
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::CreateSinkBufferL
+// Create a sink buffer
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CG711PayloadFormatWrite::CreateSinkBufferL( TMediaId aMediaId,
+                                                        TBool &aReference )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::CreateSinkBufferL()" );
+    
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    aReference = ETrue;
+
+    // Create buffer for data transfer between ULDataPath and FormatWrite
+    return CreateSinkBufferOfSizeL( iCInfo.iFrameSize + KVoIPHeaderLength );
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::CreateSinkBufferOfSizeL
+// Create a sink buffer of the given size.
+// -----------------------------------------------------------------------------
+//
+CMMFDataBuffer* CG711PayloadFormatWrite::CreateSinkBufferOfSizeL( TUint aSize )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::CreateSinkBufferOfSizeL()" );
+    
+    // Needs to create source buffer
+    if ( !iSourceBuffer )
+	    {  
+	    iSourceBuffer = CMMFDataBuffer::NewL( aSize );
+    	iSourceBuffer->Data().FillZ( aSize );
+    	iSourceBuffer->SetRequestSizeL( aSize );
+	    }
+	    
+    return iSourceBuffer;
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::EmptyBufferL
+// Empty the given source buffer
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::EmptyBufferL( CMMFBuffer* aBuffer, 
+                                            MDataSource* aSupplier, 
+                                            TMediaId aMediaId )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::EmptyBufferL()" );
+    
+    __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( aBuffer == iSourceBuffer, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( aSupplier, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( KUidMediaTypeAudio == aMediaId.iMediaType,
+        User::Leave( KErrNotSupported ) );
+    
+    // Save source buffer parameters and change the state.
+    iDataPath = aSupplier;
+    iSourceBuffer = static_cast<CMMFDataBuffer*>( aBuffer );
+    
+    if ( !iSinkBuffer )
+        {
+        DP_G711_WRITE( "CG711PayloadFormatWrite::EmptyBufferL, sink not ready!" );
+        
+        iStateMachine->ChangeState( ESourceBufferEmptied );
+        return;
+        }
+    
+    // Check if hw has sent different length buffer compared to last time.
+    // This means that we need to update the media clock. This allows G.711
+    // codec to change dynamically the buffer size.
+    const TInt dataLen( iSourceBuffer->Data().Length() - KVoIPHeaderLength );
+    const TInt audioLen( dataLen / KBitsPerByte );
+    if ( audioLen != iCInfo.iHwFrameTime )
+        {
+        // Re-register to RTP clock.
+        iCInfo.iHwFrameTime = audioLen;
+        iRtpMediaClock->UnregisterMediaFormat( iKey );
+        iKey = iRtpMediaClock->RegisterMediaFormat( KDefaultSampleRate, iCInfo.iHwFrameTime );
+        }
+        
+    DP_G711_WRITE( "CG711PayloadFormatWrite::EmptyBufferL, SetTimeToPlay" );
+    
+    TUint32 ts = 0;
+    User::LeaveIfError( iRtpMediaClock->GetTimeStamp( iKey, ts ) );
+    
+    if ( iRtpMediaClock->TimeBasedIncrement() )
+    	{
+    	DP_G711_WRITE( 
+    		"CG711PayloadFormatWrite::EmptyBufferL(), New stream begins" );
+    	iFirstPacketFinished = EFalse;
+    	}
+    
+    if ( !iSinkBuffer->Data().Length() )
+        {
+        iSinkBuffer->SetTimeToPlay( TInt64( ts ) );
+        iSinkBuffer->SetFrameNumber( aBuffer->FrameNumber() );
+        }
+    else
+        {
+        iSourceBuffer->SetTimeToPlay( TInt64( ts ) );
+        }
+    
+    iStateMachine->ChangeState( EEmptySourceBuffer );
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SetSinkDataTypeCode
+// Set the sink data type to the given four CC code for the given media
+// -----------------------------------------------------------------------------
+//
+TInt CG711PayloadFormatWrite::SetSinkDataTypeCode( TFourCC aSinkFourCC,
+                                                   TMediaId aMediaId )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::SetSinkDataTypeCode()" );
+    
+    if ( KUidMediaTypeAudio != aMediaId.iMediaType ) 
+        {
+        return KErrNotSupported;
+        }
+    
+    iFourCC = aSinkFourCC;
+    
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SinkDataTypeCode
+// Return the sink data type (four CC code) for the given media ID
+// -----------------------------------------------------------------------------
+//
+TFourCC CG711PayloadFormatWrite::SinkDataTypeCode( TMediaId aMediaId )
+    {
+    if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        return iFourCC;
+        }
+    else
+        {
+        return TFourCC(); //defaults to 'NULL' fourCC
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::BufferEmptiedL
+// Called after payload buffer is completely emptied by RtpDataSink.
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ )
+    {
+        
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::NumChannels
+// Returns number of channels
+// -----------------------------------------------------------------------------
+//
+TUint CG711PayloadFormatWrite::NumChannels()
+    {
+    return KMono;
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SampleRate
+// Returns SampleRate
+// -----------------------------------------------------------------------------
+//
+TUint CG711PayloadFormatWrite::SampleRate()
+    {
+    return KDefaultSampleRate;
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SetSampleRate
+// Set SampleRate
+// -----------------------------------------------------------------------------
+//
+TInt CG711PayloadFormatWrite::SetSampleRate( TUint aSampleRate )
+    {
+    if ( KDefaultSampleRate != aSampleRate )
+        {
+        return KErrNotSupported;
+        }
+    else
+        {
+        return KErrNone;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::FrameTimeInterval
+// Return the frame time interval for the given media
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds 
+    CG711PayloadFormatWrite::FrameTimeInterval( TMediaId aMediaId ) const
+    {
+    if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+        {
+        return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+        }
+    else
+        {
+        return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::Duration
+// Return the frame time interval for the given media
+// NOT SUPPORTED
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds 
+    CG711PayloadFormatWrite::Duration( TMediaId /*aMediaType*/ ) const
+    {
+    return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::EmptySourceBufferL
+// Empty the given sourcebuffer
+// Sourcebuffer is given in iSourceBuffer
+// Called by statemachine
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::EmptySourceBufferL()
+	{
+    const TDesC8& srcDes( iSourceBuffer->Data() );
+    
+    DP_G711_WRITE2( "CG711PayloadFormatWrite::EmptySourceBufferL - SRC BUF SIZE: %d", srcDes.Size() );
+    DP_G711_WRITE2( "CG711PayloadFormatWrite::EmptySourceBufferL - AUDIO SIZE: %d", srcDes.Size() - KVoIPHeaderLength );
+    
+    TPtrC8 audioFrame( srcDes.Mid( KVoIPHeaderLength ) );
+    TPtrC8 frameHeader( srcDes.Left( KVoIPHeaderLength ) );
+    TDes8& destDes( iSinkBuffer->Data() );
+
+    if ( audioFrame.Size() > destDes.MaxSize() - destDes.Size() || !frameHeader.Length() )
+        {
+        DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL WARNING SRCBUF LARGER THAN SINKBUF" );
+        }
+    else
+        {
+        const TUint8 frmHdrByte( frameHeader[0] );
+        if ( KVoIPAudioFrame == frmHdrByte )
+            {
+            DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL - AUDIO FRAME" );
+            if ( iCNModeON )
+                {
+                iCNModeON = EFalse;
+                iFirstPacketFinished = EFalse;
+                }
+
+            destDes.Append( audioFrame );
+            }
+        else if ( KVoIPCNFrame == frmHdrByte )
+            {
+            DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL - CNOISE FRAME" );
+            if ( destDes.Length() )
+                {
+                // Send audio frames first
+                DeliverPacketL( *iSinkBuffer );
+                iSinkBuffer->SetTimeToPlay( iSourceBuffer->TimeToPlay() );
+                }
+
+            iCNModeON = ETrue;
+            destDes.Append( audioFrame );
+            }
+        else
+            {
+            DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL - UNVOICED NON-SID FRAME" );
+            }
+        }        
+    
+    // If we have filled the buffer enough or the frame is a CN packet
+    // then send it.
+    const TInt sendBytes( iCInfo.iPtime * KBitsPerByte );
+    if ( sendBytes == destDes.Size() || iCNModeON )
+        {
+        this->DeliverPacketL( *iSinkBuffer );
+        }
+
+    iStateMachine->ChangeState( ESourceBufferEmptied );
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::DeliverPacketL
+// Prepare the packet header and deliver the packet to the datasink.
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::DeliverPacketL( CMMFDataBuffer& aPayload )
+    {
+    DP_G711_WRITE2( "CG711PayloadFormatWrite::DeliverPacketL - TSTAMP: %u",
+        static_cast<TUint32>( aPayload.TimeToPlay().Int64() ) );
+    
+    if ( !iClip )
+        {
+        DP_G711_WRITE( "CG711PayloadFormatWrite::DeliverPacketL NO DATASINK!" );
+
+        User::Leave( KErrNotReady );
+        }
+
+    // Construct RTP header. Note that CN frames must not have the marker bit
+    // set, only first audioframe after silence period.
+    TRtpSendHeader sendHdr;
+    if ( !iFirstPacketFinished && !iCNModeON )
+        {
+        sendHdr.iMarker = 1;
+        iFirstPacketFinished = ETrue;
+        }
+    else
+        {
+        sendHdr.iMarker = 0;
+        }
+
+    sendHdr.iTimestamp 
+        = static_cast<TUint32>( aPayload.TimeToPlay().Int64() );
+    
+    const TMediaId mediaId( KUidMediaTypeAudio );
+    const TInt dataSize( aPayload.Data().Size() );
+    if ( iCNModeON )
+        {
+        if ( iCInfo.iComfortNoiseGenerationPt != KPayloadTypeUndefined )
+            {
+            sendHdr.iPayloadType = iCInfo.iComfortNoiseGenerationPt;
+            if ( dataSize )
+                {  
+                if ( iIsRtpSink )
+                    {
+                    iRtpDataSink->EmptyBufferL( &aPayload, this, mediaId, sendHdr );
+                    }
+                else
+                    {
+        		    aPayload.SetLastBuffer( sendHdr.iMarker );
+                    iClip->EmptyBufferL( &aPayload, this, mediaId );
+                    }
+                }
+            }
+        }
+    else
+        {
+        sendHdr.iPayloadType = iCInfo.iPayloadType;
+        
+        if ( dataSize )
+            {  
+            if ( iIsRtpSink )
+                {
+                iRtpDataSink->EmptyBufferL( &aPayload, this, mediaId, sendHdr );
+                }
+            else
+                {
+    		    aPayload.SetLastBuffer( sendHdr.iMarker );
+                iClip->EmptyBufferL( &aPayload, this, mediaId );
+                }
+            }
+        }        
+    
+    // Reset the payload buffer -- only if previous EmptyBufferL() is a 
+    // synchronous call.
+    aPayload.Data().Zero();
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SourceBufferEmptiedL
+// Handle the event that sourcebuffer has been emptied.
+// Sourcebuffer is given in "iSourceBuffer".
+// Called by the statemachine.
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::SourceBufferEmptiedL()
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::SourceBufferEmptiedL()" );
+    iDataPath->BufferEmptiedL( iSourceBuffer );
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SinkPrimeL
+// Prime sink
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::SinkPrimeL()
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::SinkPrimeL()"  );
+    iClip->SinkPrimeL();
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SinkPlayL
+// Start playing.
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::SinkPlayL()
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::SinkPlayL()" );
+    // Allocate buffer for data transfer between 
+    // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder
+    delete iSinkBuffer;
+    iSinkBuffer = NULL;
+    iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iPtime * KBitsPerByte );
+    
+    // Start state machine
+    iStateMachine->ChangeState( EEncodeIdle ); 
+    iFirstPacketFinished = EFalse;
+
+    // Start a new cycle of frame collecting
+    if ( iSinkBuffer )
+        {
+        iSinkBuffer->SetLastBuffer( EFalse );
+        }
+
+    iClip->SinkPlayL();
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SinkPauseL
+// Pause sink
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::SinkPauseL()
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::SinkPauseL()" );
+    iStateMachine->Cancel();
+    iStateMachine->ChangeState( EEncodeIdle );
+    
+    iClip->SinkPauseL();
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::SinkStopL
+// Stop sink
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::SinkStopL()
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::SinkStopL" );
+    
+    // Stop state machine
+    iStateMachine->Cancel();
+    iStateMachine->ChangeState( EEncodeIdle );
+    
+    iClip->SinkStopL();
+    }
+
+// ---------------------------------------------------------------------------
+// CG711PayloadFormatWrite::ConfigurePayloadFormatL
+// Configure payload encoding parameters
+// ---------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::ConfigurePayloadFormatL( const TDesC8& aConfigParams, 
+    CMccRtpMediaClock& aClock  )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::ConfigurePayloadFormatL" );
+    
+    __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
+        User::Leave( KErrArgument ) );
+    
+    TMccCodecInfoBuffer infoBuffer;
+    infoBuffer.Copy( aConfigParams );
+    
+    if ( !infoBuffer().iIsUpdate )
+        {
+        iCInfo = infoBuffer();
+        iRtpMediaClock = &aClock;  
+        iKey = iRtpMediaClock->RegisterMediaFormat( KDefaultSampleRate, iCInfo.iHwFrameTime );
+        
+        if( iCInfo.iHwFrameTime )
+            {
+            iCInfo.iFrameSize = TUint( iCInfo.iHwFrameTime * KDefaultSampleRateInkHz );
+            }
+        else
+            {
+            DP_G711_WRITE( "CG711PayloadFormatWrite::ConfigurePayloadFormatL KErrArgument" );
+            User::Leave( KErrArgument );
+            }
+        
+        DP_G711_WRITE2( "CG711PayloadFormatWrite::ConfigurePayloadFormatL FrameSize: %d", iCInfo.iFrameSize );
+        
+        if ( EGenRedUsed == iCInfo.iAlgoUsed )
+            {
+            DP_G711_WRITE2( "CG711PayloadFormatWrite::ConfigurePayloadFormatL, RED LEVEL: %d",
+                iCInfo.iRedundancyCount );
+            
+            CPayloadFormatWrite* redEncoder
+                = static_cast<CMccRedPayloadWrite*>( iClip );
+            
+            TMccRedPayloadWriteConfig config;
+            config.iRedBlockCount = iCInfo.iRedundancyCount;
+            config.iMaxPayloadSize = iCInfo.iPtime * KBitsPerByte;
+            config.iNumOfEncodings = 1;
+            config.iRedPayloadType = iCInfo.iRedundantPayload;
+            config.InitPayloadTypes();
+            config.iEncPayloadTypes[0] = iCInfo.iPayloadType;
+            TMccRedPayloadWritePckg pckg( config );
+            redEncoder->ConfigurePayloadFormatL( pckg, *iRtpMediaClock );
+            }
+        }
+    else
+        {
+        UpdateConfigurationL( infoBuffer() ); 
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CG711PayloadFormatWrite::UpdateConfigurationL
+// Update payload encoding parameters
+// -----------------------------------------------------------------------------
+//
+void CG711PayloadFormatWrite::UpdateConfigurationL( TMccCodecInfo& aCodecInfo )
+    {
+    DP_G711_WRITE( "CG711PayloadFormatWrite::UpdateConfigurationL" );
+    
+    iCInfo.iPtime = aCodecInfo.iPtime;
+    iCInfo.iPayloadType = aCodecInfo.iPayloadType;
+    iCInfo.iComfortNoiseGenerationPt = aCodecInfo.iComfortNoiseGenerationPt;
+    
+    // Allocate buffer for data transfer between 
+    // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder
+    delete iSinkBuffer;
+    iSinkBuffer = NULL;
+    iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iPtime * KBitsPerByte );
+    
+    DP_G711_WRITE( "CG711PayloadFormatWrite::UpdateConfigurationL, exit" );
+    }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+//  End of File