diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccilbcpayloadformat/src/ilbcpayloadformatwrite.cpp --- /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( aSink ); + iRtpDataSink = static_cast( tmp ); + } + else if ( isRedEncoder ) + { + CMccRedPayloadWrite* tmp = static_cast( aSink ); + iRtpDataSink = static_cast( 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( 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( 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( 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( 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