--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccilbcpayloadformat/src/ilbcpayloadformatwrite.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,785 @@
+/*
+* 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 ILBC audio.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "ilbcpayloadformatwrite.h"
+#include "mccrtpdatasink.h"
+#include "ilbcpayloadformatutil.h"
+#include "mccuids.hrh"
+#include "mccdef.h"
+#include "mccinternaldef.h"
+#include "mccrtpmediaclock.h"
+#include "mccredpayloadwrite.h"
+
+// MACROS
+#ifdef _DEBUG
+#define TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+#endif
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::CIlbcPayloadFormatWrite
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CIlbcPayloadFormatWrite::CIlbcPayloadFormatWrite()
+ {
+
+ };
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::ConstructL( MDataSink* aSink )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::ConstructL") );
+ #endif
+
+ __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
+
+ // Set default values
+ iFramesPerPacket = 1;
+ iFourCC.Set( KMccFourCCIdILBC );
+
+ // Set data sink
+ 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
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CG711PayloadFormatWrite::ConstructL, sink not RTP one") );
+ #endif
+ }
+
+ iClip = aSink;
+
+ // Initialize state machine
+ iStateMachine = CFormatEncodeStateMachine::NewL( this );
+ iStateMachine->ChangeState( EEncodeIdle );
+ };
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CIlbcPayloadFormatWrite* CIlbcPayloadFormatWrite::NewL( MDataSink* aSink )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::NewL") );
+ #endif
+
+ __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
+
+ CIlbcPayloadFormatWrite* self = new ( ELeave ) CIlbcPayloadFormatWrite();
+ CleanupStack::PushL( self );
+ self->ConstructL ( aSink );
+ CleanupStack::Pop( self );
+ return self;
+ };
+
+// Destructor
+CIlbcPayloadFormatWrite::~CIlbcPayloadFormatWrite()
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::~CIlbcPayloadFormatWrite") );
+ #endif
+
+ if ( iStateMachine )
+ {
+ iStateMachine->Cancel();
+ }
+
+ // Media clock is not owned
+ if ( iRtpMediaClock )
+ {
+ iRtpMediaClock->UnregisterMediaFormat( iKey );
+ }
+
+ delete iSourceBuffer;
+ delete iSinkBuffer;
+ delete iStateMachine;
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SinkThreadLogon
+// Passes the logon command to the sink clip
+// -----------------------------------------------------------------------------
+//
+TInt CIlbcPayloadFormatWrite::SinkThreadLogon(
+ MAsyncEventHandler& aEventHandler )
+ {
+ iClip->SinkThreadLogon( aEventHandler );
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SinkThreadLogoff
+// Passes the logoff command to the sink clip
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::SinkThreadLogoff()
+ {
+ iClip->SinkThreadLogoff();
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::CreateSinkBufferL
+// Create a sink buffer
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CIlbcPayloadFormatWrite::CreateSinkBufferL( TMediaId aMediaId,
+ TBool &aReference )
+ {
+ if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print (_L ("CIlbcPayloadFormatWrite::CreateSinkBufferL KErrNotSupported"));
+ #endif
+
+ User::Leave( KErrNotSupported );
+ return NULL;
+ }
+ else
+ {
+ aReference = ETrue;
+
+ // Create buffer for data transfer between UL datapth and FormatWrite.
+ // 30ms mode buffers can be used also for 20ms mode.
+ if ( KiLBCBitrateWith30ms == iCInfo.iBitrate ||
+ KiLBCBitrateWith20ms == iCInfo.iBitrate )
+ {
+ return CreateSinkBufferOfSizeL(
+ KiLBCNumOfHeaderBytes + KiLBCFrameSize30ms );
+ }
+ else
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print (_L ("CIlbcPayloadFormatWrite::CreateSinkBufferL KErrNotReady"));
+ #endif
+
+ User::Leave( KErrNotReady );
+ return NULL;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::CreateSinkBufferOfSizeL
+// Create a sink buffer of the given size.
+// -----------------------------------------------------------------------------
+//
+CMMFDataBuffer* CIlbcPayloadFormatWrite::CreateSinkBufferOfSizeL( TUint aSize )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::CreateSinkBufferOfSizeL") );
+ #endif
+
+ // Needs to create source buffer
+ if ( !iSourceBuffer )
+ {
+ iSourceBuffer = CMMFDataBuffer::NewL( aSize );
+ iSourceBuffer->Data().FillZ( aSize );
+ iSourceBuffer->SetRequestSizeL( aSize );
+ }
+
+ return iSourceBuffer;
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::EmptyBufferL
+// Empty the given source buffer
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::EmptyBufferL( CMMFBuffer* aBuffer,
+ MDataSource* aSupplier, TMediaId aMediaId )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptyBufferL aBuffer = 0x%x"),
+ aBuffer );
+ #endif
+
+ __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;
+ iMediaId = aMediaId;
+ iSourceBuffer = static_cast<CMMFDataBuffer*>( aBuffer );
+
+ if ( !iSinkBuffer )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptyBufferL, sink not ready!") );
+ #endif
+ iStateMachine->ChangeState( ESourceBufferEmptied );
+ return;
+ }
+
+ TUint32 ts = 0;
+ User::LeaveIfError( iRtpMediaClock->GetTimeStamp( iKey, ts ) );
+
+ if ( iRtpMediaClock->TimeBasedIncrement() )
+ {
+ iFirstPacketFinished = EFalse;
+ }
+
+ if ( 0 == iFrameIndex )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptyBufferL, SetTimeToPlay") );
+ #endif
+
+ iSinkBuffer->SetTimeToPlay( TInt64( ts ) );
+ iSinkBuffer->SetFrameNumber( aBuffer->FrameNumber() );
+ }
+ else
+ {
+ iSourceBuffer->SetTimeToPlay( TInt64( ts ) );
+ }
+
+ iStateMachine->ChangeState( EEmptySourceBuffer );
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SetSinkDataTypeCode
+// Set the sink data type to the given four CC code for the given media
+// -----------------------------------------------------------------------------
+//
+TInt CIlbcPayloadFormatWrite::SetSinkDataTypeCode( TFourCC aSinkFourCC,
+ TMediaId aMediaId )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print (_L ("CIlbcPayloadFormatWrite::SetSinkDataTypeCode()"));
+ #endif
+
+ if ( KUidMediaTypeAudio != aMediaId.iMediaType )
+ {
+ return KErrNotSupported;
+ }
+
+ iFourCC = aSinkFourCC;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SinkDataTypeCode
+// Return the sink data type (four CC code) for the given media
+// -----------------------------------------------------------------------------
+//
+TFourCC CIlbcPayloadFormatWrite::SinkDataTypeCode( TMediaId aMediaId )
+ {
+ if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+ {
+ return iFourCC;
+ }
+ else
+ {
+ return TFourCC(); //defaults to 'NULL' fourCC
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::BufferEmptiedL
+// Called after payload buffer is completely emptied by RtpDataSink.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ )
+ {
+
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::NumChannels
+// Returns number of channels
+// -----------------------------------------------------------------------------
+//
+TUint CIlbcPayloadFormatWrite::NumChannels()
+ {
+ return KMono;
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SampleRate
+// Returns SampleRate
+// -----------------------------------------------------------------------------
+//
+TUint CIlbcPayloadFormatWrite::SampleRate()
+ {
+ return KiLBCSampleRate;
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SetSampleRate
+// Set SampleRate
+// -----------------------------------------------------------------------------
+//
+TInt CIlbcPayloadFormatWrite::SetSampleRate( TUint aSampleRate )
+ {
+ return ( KiLBCSampleRate == aSampleRate ) ? KErrNone : KErrNotSupported;
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::FrameTimeInterval
+// Return the frame time interval for the given media
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CIlbcPayloadFormatWrite::FrameTimeInterval(
+ TMediaId aMediaId ) const
+ {
+ if ( KUidMediaTypeAudio == aMediaId.iMediaType )
+ {
+ return iFrameTimeInterval;
+ }
+ else
+ {
+ return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::Duration
+// Return the frame time interval for the given media
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CIlbcPayloadFormatWrite::Duration(
+ TMediaId /*aMediaType*/) const
+ {
+ return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::EmptySourceBufferL
+// Empty the given sourcebuffer
+// Sourcebuffer is given in iSourceBuffer
+// Called by statemachine
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::EmptySourceBufferL()
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptySourceBufferL - SIZE OF SRC BUF: %d"),
+ iSourceBuffer->Data().Size() );
+ #endif
+
+ TPtrC8 audioFrame( iSourceBuffer->Data().Mid( KiLBCNumOfHeaderBytes ) );
+ TPtrC8 frameHeader = iSourceBuffer->Data().Left( KiLBCNumOfHeaderBytes );
+ TDes8& destDes = iSinkBuffer->Data();
+
+ if ( audioFrame.Size() > destDes.MaxSize() - destDes.Size() || !frameHeader.Length() )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptySourceBufferL \
+ AUDIOFRAME DOES NOT FIT TO SINK BUF") );
+ RDebug::Print( _L("%d > %d || !%d"), audioFrame.Size(), destDes.MaxSize()-destDes.Size(),
+ !frameHeader.Length() );
+ #endif
+ }
+ else
+ {
+ if ( KAudioFrameHeaderByte == frameHeader[0] )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptySourceBufferL AUDIO FRAME") );
+ #endif
+ if ( iCNModeON )
+ {
+ iCNModeON = EFalse;
+ iFirstPacketFinished = EFalse;
+ }
+
+ destDes.Append( audioFrame );
+ iFrameIndex++;
+ }
+ else if ( KCNoiseFrameHeaderByte == frameHeader[0] )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptySourceBufferL CNOISE FRAME") );
+ #endif
+ if ( destDes.Size() )
+ {
+ // Send audio frames first
+ DeliverPacketL( *iSinkBuffer );
+ iSinkBuffer->SetTimeToPlay( iSourceBuffer->TimeToPlay() );
+ }
+
+ iCNModeON = ETrue;
+ destDes.Append( audioFrame );
+
+ // Only one comfort noise frame per RTP packet
+ iFrameIndex = iFramesPerPacket;
+ }
+ else
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::EmptySourceBufferL NULL BIT RATE FRAME") );
+ #endif
+ }
+ }
+
+ if ( iFrameIndex == iFramesPerPacket )
+ {
+ // Reset variables
+ iFrameIndex = 0;
+ this->DeliverPacketL( *iSinkBuffer );
+ destDes.Zero();
+ }
+
+ iStateMachine->ChangeState( ESourceBufferEmptied );
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::DeliverPacketL
+// Prepare the packet header and deliver the packet to the datasink.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::DeliverPacketL( CMMFDataBuffer& aPayload )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::DeliverPacketL - TSTAMP: %u"),
+ static_cast<TUint32>( aPayload.TimeToPlay().Int64() ) );
+ #endif
+
+ if ( !iClip )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::DeliverPacketL - NO DATASINK") );
+ #endif
+ User::Leave( KErrNotReady );
+ }
+
+ // Construct RTP header.
+ if ( !iFirstPacketFinished && !iCNModeON )
+ {
+ iRtpSendHeader.iMarker = 1;
+ iFirstPacketFinished = ETrue;
+ }
+ else
+ {
+ iRtpSendHeader.iMarker = 0;
+ }
+
+ if ( !iRtpDataSink )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::DeliverPacketL - NO DATASINK") );
+ #endif
+ User::Leave( KErrNotReady );
+ }
+
+ iRtpSendHeader.iTimestamp
+ = static_cast<TUint32>( aPayload.TimeToPlay().Int64() );
+
+ if ( iCNModeON )
+ {
+ if ( iCInfo.iComfortNoiseGenerationPt != KPayloadTypeUndefined )
+ {
+ iRtpSendHeader.iPayloadType = iCInfo.iComfortNoiseGenerationPt;
+
+ if ( aPayload.Data().Size() )
+ {
+ if ( iIsRtpSink )
+ {
+ iRtpDataSink->EmptyBufferL( &aPayload, this, iMediaId, iRtpSendHeader );
+ }
+ else
+ {
+ aPayload.SetLastBuffer( iRtpSendHeader.iMarker );
+ iClip->EmptyBufferL( &aPayload, this, iMediaId );
+ }
+ }
+ }
+ }
+ else
+ {
+ iRtpSendHeader.iPayloadType = iCInfo.iPayloadType;
+
+ if ( aPayload.Data().Size() )
+ {
+ if ( iIsRtpSink )
+ {
+ iRtpDataSink->EmptyBufferL( &aPayload, this, iMediaId, iRtpSendHeader );
+ }
+ else
+ {
+ aPayload.SetLastBuffer( iRtpSendHeader.iMarker );
+ iClip->EmptyBufferL( &aPayload, this, iMediaId );
+ }
+ }
+
+ }
+
+ // Reset the payload buffer -- only if previous EmptyBufferL() is a
+ // synchronous call
+ aPayload.Data().Zero();
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SourceBufferEmptiedL
+// Handle the event that sourcebuffer has been emptied.
+// Sourcebuffer is given in "iSourceBuffer".
+// Called by the statemachine.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::SourceBufferEmptiedL()
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::SourceBufferEmptiedL") );
+ #endif
+
+ iDataPath->BufferEmptiedL( iSourceBuffer );
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SinkPrimeL
+// Prime sink
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::SinkPrimeL()
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print (_L ("CIlbcPayloadFormatWrite::SinkPrimeL()"));
+ #endif
+
+ iClip->SinkPrimeL();
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SinkPlayL
+// Start playing
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::SinkPlayL()
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print (_L ("CIlbcPayloadFormatWrite::SinkPlayL()"));
+ #endif
+
+ // Allocate buffer for data transfer between
+ // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder
+ delete iSinkBuffer;
+ iSinkBuffer = NULL;
+ iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iFrameSize * iFramesPerPacket );
+
+ // Start state machine
+ iStateMachine->ChangeState( EEncodeIdle );
+ // RTP Header marker-bit must be set to 1 when starting stream
+ iFirstPacketFinished = EFalse;
+
+ // Start a new cycle of frame collecting
+ iFrameIndex = 0;
+
+ if ( iSinkBuffer )
+ {
+ iSinkBuffer->SetLastBuffer( EFalse );
+ }
+
+ iClip->SinkPlayL();
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SinkPauseL
+// Pause sink
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::SinkPauseL()
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::SinkPauseL") );
+ #endif
+
+ iStateMachine->Cancel();
+ iStateMachine->ChangeState( EEncodeIdle );
+
+ iClip->SinkPauseL();
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::SinkStopL
+// Stop sink
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::SinkStopL()
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::SinkStopL") );
+ #endif
+
+ // Stop state machine
+ iStateMachine->Cancel();
+ iStateMachine->ChangeState( EEncodeIdle );
+ iClip->SinkStopL();
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::ConfigurePayloadFormatL
+// Configure payload encoding parameters.
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::ConfigurePayloadFormatL( const TDesC8& aConfigParams,
+ CMccRtpMediaClock& aClock )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::ConfigurePayloadFormatL IN") );
+ #endif
+ __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
+ User::Leave( KErrArgument ) );
+
+ iRtpMediaClock = &aClock;
+
+ TMccCodecInfoBuffer infoBuffer;
+ infoBuffer.Copy( aConfigParams );
+
+ if ( !infoBuffer().iIsUpdate )
+ {
+ DoConfigurePayloadFormatL( infoBuffer() );
+ }
+ else
+ {
+ UpdateConfigurationL( infoBuffer() );
+ }
+
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::ConfigurePayloadFormatL OUT") );
+ #endif
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::UpdateConfigurationL
+// Update payload encoding parameters
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::UpdateConfigurationL( const TMccCodecInfo& aCodecInfo )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::UpdateConfigurationL") );
+ #endif
+
+ iCInfo.iPayloadType = aCodecInfo.iPayloadType;
+
+ if ( iCInfo.iMaxPtime != aCodecInfo.iMaxPtime ||
+ iCInfo.iPtime != aCodecInfo.iPtime ||
+ iCInfo.iHwFrameTime != aCodecInfo.iHwFrameTime ||
+ iCInfo.iBitrate != aCodecInfo.iBitrate ||
+ iCInfo.iComfortNoiseGenerationPt != aCodecInfo.iComfortNoiseGenerationPt )
+ {
+ DoConfigurePayloadFormatL( aCodecInfo );
+
+ // Allocate buffer for data transfer between
+ // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder
+ delete iSinkBuffer;
+ iSinkBuffer = NULL;
+ iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iFrameSize * iFramesPerPacket );
+
+ // Start a new cycle of frame collecting
+ iFrameIndex = 0;
+ }
+
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::UpdateConfigurationL OUT") );
+ #endif
+ }
+
+// -----------------------------------------------------------------------------
+// CIlbcPayloadFormatWrite::DoConfigurePayloadFormatL
+// -----------------------------------------------------------------------------
+//
+void CIlbcPayloadFormatWrite::DoConfigurePayloadFormatL( const TMccCodecInfo& aCodecInfo )
+ {
+ __ASSERT_ALWAYS( aCodecInfo.iHwFrameTime != 0, User::Leave( KErrArgument ) );
+
+ iCInfo = aCodecInfo;
+ iKey = iRtpMediaClock->RegisterMediaFormat( KiLBCSampleRate, iCInfo.iHwFrameTime );
+
+ if ( KiLBCBitrateWith20ms == iCInfo.iBitrate )
+ {
+ iCInfo.iHwFrameTime = KiLBCFrameTime20ms;
+ // Maximum number of frames in RTP payload
+ iFramesPerPacket = iCInfo.iPtime / iCInfo.iHwFrameTime;
+ iCInfo.iFrameSize = KiLBCFrameSize20ms;
+ iFrameTimeInterval = TInt64( KiLBCFrameTime20ms * TUint8( iFramesPerPacket ) );
+ }
+ else if ( KiLBCBitrateWith30ms == iCInfo.iBitrate )
+ {
+ iCInfo.iHwFrameTime = KiLBCFrameTime30ms;
+ // Maximum number of frames in RTP payload
+ iFramesPerPacket = iCInfo.iPtime / iCInfo.iHwFrameTime;
+ iCInfo.iFrameSize = KiLBCFrameSize30ms;
+ iFrameTimeInterval = TInt64( KiLBCFrameTime30ms * TUint8( iFramesPerPacket ) );
+ }
+ else
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::ConfigurePayloadFormatL - BITRATE INVALID: %d"), iCInfo.iBitrate );
+ #endif
+ User::Leave( KErrArgument );
+ }
+
+ if ( EGenRedUsed == iCInfo.iAlgoUsed )
+ {
+ #ifdef TRACE_ILBC_PAYLOAD_FORMAT_WRITE
+ RDebug::Print( _L("CIlbcPayloadFormatWrite::ConfigurePayloadFormatL, RED LEVEL: %d"),
+ iCInfo.iRedundancyCount );
+ #endif
+
+ CPayloadFormatWrite* redEncoder
+ = static_cast<CMccRedPayloadWrite*>( iClip );
+
+ TMccRedPayloadWriteConfig config;
+ config.iRedBlockCount = iCInfo.iRedundancyCount;
+ config.iMaxPayloadSize = iCInfo.iFrameSize * iFramesPerPacket;
+ config.iNumOfEncodings = 1;
+ config.iRedPayloadType = iCInfo.iRedundantPayload;
+ config.InitPayloadTypes();
+ config.iEncPayloadTypes[0] = iCInfo.iPayloadType;
+ TMccRedPayloadWritePckg pckg( config );
+ redEncoder->ConfigurePayloadFormatL( pckg, *iRtpMediaClock );
+ }
+ }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// End of File