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