diff -r fb024d5e35fa -r 64c62431ac08 multimediacommscontroller/mmccMsrppayloadformat/src/Msrppayloadformatread.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommscontroller/mmccMsrppayloadformat/src/Msrppayloadformatread.cpp Mon Sep 06 17:32:13 2010 +0530 @@ -0,0 +1,1230 @@ +/* +* Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Provides a comfort noise generator class +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include // charconv.lib + +#include "MsrpPayloadFormatRead.h" +#include "MsrpPayloadFormatWrite.h" // TStringElement, move independent +#include "MccRtpDataSource.h" +#include "Mccinternaldef.h" +#include "MccMsrpFormatLogs.h" +#include "msrppayloadformatdefs.h" + + +// ============================= LOCAL FUNCTIONS =============================== + +const TUint KLostChar = 0xFFFD; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::CMsrpPayloadFormatRead +// +// CMsrpPayloadFormatRead default constructor, can NOT contain Msrp code, +// that might leave +// Phase #1 of 2-phase constructor +// ----------------------------------------------------------------------------- +// +CMsrpPayloadFormatRead::CMsrpPayloadFormatRead ( ) : iFirstPacketsMissing (EFalse), +iPacketSecNumber(EFalse) + { + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::ConstructL ( MDataSource* aSource ) + { + + DP_MSRP_WRITE( "CMsrpPayloadFormatRead::ConstructL" ); + __ASSERT_ALWAYS( aSource, User::Leave( KErrArgument ) ); + + // we are coming downstream, the clip is now the source and + // datapath the sink. If we use RTP source if of source the RTPSource + + iRtpDataSource = aSource; + iClip = aSource; + + //Flags to indicate actions + iFillRequested = EFalse; + iBufferToReadExists = EFalse; + + iFourCC = KMccFourCCIdMSRP ; + //iFourCC.Set( TFourCC( 'T','1','4','0' ) ); + + iRedData = new(ELeave)CArrayFixFlat(3); + TStringElement empty; + iRedData->AppendL(empty); + iRedData->AppendL(empty); + iRedData->AppendL(empty); + + // TODO : refine my sizes + iCharData = HBufC8::NewL( KDataSize ); + iDecodedBuffer = CMMFDataBuffer::NewL( KRedHeaderSize + KDataSize ); + + // Initialize decoding state machine + iStateMachine = CFormatDecodeStateMachine::NewL( this ); + iStateMachine->ChangeState( EDecodeIdle ); + + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::NewL +// Two-phased constructor. +// Static function for creating and constructing an instance of +// the Text/Msrp Format +// Returns: CMsrpPayloadFormatRead* : pointer to created instance +// ----------------------------------------------------------------------------- +// +CMsrpPayloadFormatRead* CMsrpPayloadFormatRead::NewL( + MDataSource* aSource ) + + { + + DP_MSRP_WRITE("CMsrpPayloadFormatRead::NewL"); + + __ASSERT_ALWAYS( aSource, User::Leave( KErrArgument ) ); + + //__ASSERT_ALWAYS( ( KMccRtpSourceUid == aSource->DataSourceType() || + // KMccMsrpSourceUid == aSource->DataSourceType() ), + // User::Leave( KErrArgument ) ); + CMsrpPayloadFormatRead* self = new ( ELeave ) CMsrpPayloadFormatRead; + CleanupStack::PushL ( self ); + self->ConstructL ( aSource ); + CleanupStack::Pop( self ); + return self; + + } + + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::~CMsrpPayloadFormatRead +// +// Destructor. +// ----------------------------------------------------------------------------- +// +CMsrpPayloadFormatRead::~CMsrpPayloadFormatRead( ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::~CMsrpPayloadFormatRead"); + delete iFrameBufferOne; + delete iFrameBufferTwo; + + if ( iSourceBufOwnership ) + { + delete iPayloadBuffer; + } + else + { + iPayloadBuffer = NULL; + } + + if(iRedData) + { + delete iRedData; + iRedData = NULL; + } + + if(iCharData) + { + delete iCharData; + iCharData = NULL; + } + + if(iDecodedBuffer) + { + delete iDecodedBuffer; + iDecodedBuffer = NULL; + } + + if ( iStateMachine ) + { + iStateMachine->Cancel( ); + delete iStateMachine; + } + iCurrentBuffer = NULL; + iRtpDataSource = NULL; + iClip = NULL; + iDataPath = NULL; + iEventHandler = NULL; + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::Streams +// Return number of message streams for the given media +// ----------------------------------------------------------------------------- +// +TUint CMsrpPayloadFormatRead::Streams( TUid /*aMediaType*/) const + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::Streams"); + return 1; + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::FrameTimeInterval +// Return the frame time interval for the given media +// ----------------------------------------------------------------------------- +// +TTimeIntervalMicroSeconds CMsrpPayloadFormatRead::FrameTimeInterval( + TMediaId /*aMediaId*/ ) const + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::FrameTimeInterval"); + + return TTimeIntervalMicroSeconds( TInt64( 0 ) ); + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead:: +// Fill Buffer. If DataSink asks to Fill a buffer +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::FillBufferL( CMMFBuffer* aBuffer, + MDataSink* aConsumer, + TMediaId aMediaId ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::FillBufferL"); + __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( aBuffer->Type() == KUidMmfDataBuffer, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( aConsumer, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iStateMachine, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iFrameBufferOne, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iFrameBufferTwo, User::Leave( KErrArgument ) ); + + iDataPath = aConsumer; + iMediaId = aMediaId; + iFillRequested = ETrue; + + if ( iCurrentBuffer ) + { + iCurrentBuffer->SetStatus( EAvailable ); + iCurrentBuffer = NULL; + } + + if (iFrameBufferOne->Status() == EFull ) + { + iCurrentBuffer = iFrameBufferOne; + iStateMachine->ChangeState( ESourceDataReady ); + } + else if (iFrameBufferTwo->Status() == EFull ) + { + iCurrentBuffer = iFrameBufferTwo; + iStateMachine->ChangeState( ESourceDataReady ); + } + else + { + FillSourceBufferL(); + } +// ResetBuffers(); + } + + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::FillSinkBuffer +// Read RTP payload and convert it into Text/Msrp Data +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::FillSinkBufferL() + { + + // reset all bufs + ResetPacketBuffers(); + const TDesC8& srcBuf( iCurrentBuffer->Data() ); + + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FillSinkBufferL, iPacketCount: %d ", iPacketCount ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FillSinkBufferL, iFirstPacketsMissing: %d ", iFirstPacketsMissing ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FillSinkBufferL, iSatisfySecNumber: %d ", iSatisfySecNumber ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FillSinkBufferL, iLevelsMissing: %d ", iLevelsMissing ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FillSinkBufferL, iDroppedPacketCount: %d ", iDroppedPacketCount ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FillSinkBufferL, iCurrentBuffer Size() : %d ", iCurrentBuffer->Data().Size() ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FillSinkBufferL, Currentbuffer BufferSize() : %d ", iCurrentBuffer->BufferSize() ); + + + // Do not forward zero length buffers, even though we filtered all unwanted data + // allready in BufferFilledL() -method + if ( iCurrentBuffer->BufferSize() > 0 ) + { + + TInt pValue(0); + switch ( iCodecInfo.iRedundancyCount ) + { + case 0: + iDecodedBuffer->Data().Append( iCurrentBuffer->Data() ); + iSatisfySecNumber++; + break; + + case 2: + pValue = DecodePayloadL( srcBuf ); + User::LeaveIfError(HandleRedundancyL(pValue)); + break; + } + + if ( !pValue ) + { + iStateMachine->ChangeState( EEmptyDataToSink ); + } + else + { + FillSourceBufferL(); + } + } + else + { + // No payload or Data sent by SipCon1, ask for more + DP_MSRP_WRITE("CMsrpPayloadFormatRead::FillSinkBufferL - Empty Data"); + iStateMachine->ChangeState( EWaitSourceData ); + } + } + + + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::ResetBuffers() +// Send fill buffer request to RTP Data Source +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::ResetBuffers() +{ + DP_MSRP_WRITE("CMsrpPayloadFormatRead::ResetBuffers"); + if ( iCurrentBuffer ) + { + iCurrentBuffer->SetStatus( EAvailable ); + iCurrentBuffer = NULL; + } + + if (iFrameBufferOne->Status() == EFull ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::ResetBuffers() - FB1 - was FULL"); + iCurrentBuffer = iFrameBufferOne; + iStateMachine->ChangeState( ESourceDataReady ); + } + else if (iFrameBufferTwo->Status() == EFull ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::ResetBuffers() - FB2 - was FULL"); + iCurrentBuffer = iFrameBufferTwo; + iStateMachine->ChangeState( ESourceDataReady ); + } + else + { + iStateMachine->ChangeState( EWaitSourceData ); + } +} + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::FillSourceBufferL +// Send fill buffer request to RTP Data Source +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::FillSourceBufferL() + { + + DP_MSRP_WRITE("CMsrpPayloadFormatRead::FillSourceBufferL"); + __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iPayloadBuffer, User::Leave( KErrArgument ) ); + + iClip->FillBufferL(iPayloadBuffer, this, iMediaId ); + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SendDataToSinkL +// Send full frame buffer to Data Path +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::SendDataToSinkL( ) + { + + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SendDataToSinkL()"); + iFillRequested = EFalse; + iDataPath->BufferFilledL( iDecodedBuffer ); + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::CreateSourceBufferL +// Create a source buffer for the given media and indicate in aReference if +// buffer is created. +// ----------------------------------------------------------------------------- +// +CMMFBuffer* CMsrpPayloadFormatRead::CreateSourceBufferL( + TMediaId /*aMediaId*/, + TBool &aReference ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::CreateSourceBufferL"); + // the source buffers belong to MsrpPayloadFormatRead not to datapath + // aReference should be set to ETrue and destroyed by MsrpPayloadFormatRead + // itself. + aReference = ETrue; + iCurrentBuffer = iFrameBufferOne; + return iFrameBufferOne; + + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::CreateSourceBufferL +// Create a source buffer for the given media, setting frame size to match +// the given sink buffer +// ----------------------------------------------------------------------------- +// +CMMFBuffer* CMsrpPayloadFormatRead::CreateSourceBufferL( + TMediaId aMediaId, + CMMFBuffer& /*aSinkBuffer*/, + TBool &aReference ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::CreateSourceBufferL"); + return CreateSourceBufferL( aMediaId, aReference ); + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SourceDataTypeCode +// Return the source data type ( four CC code ) for the given media +// ----------------------------------------------------------------------------- +// +TFourCC CMsrpPayloadFormatRead::SourceDataTypeCode( + TMediaId aMediaId ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SourceDataTypeCode"); + //TODO: Change me when platform supports + if ( KUidMediaTypeAudio == aMediaId.iMediaType ) + { + return iFourCC; + } + else + { + return TFourCC( ); //defaults to 'NULL' fourCC + } + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SetSourceDataTypeCode +// Set the source data type to the given four CC code for the given +// media +// ----------------------------------------------------------------------------- +// +TInt CMsrpPayloadFormatRead::SetSourceDataTypeCode( TFourCC aSourceFourCC, + TMediaId aMediaId ) + { + + //TODO Change me when platform supports + /* + if ( KUidMediaTypeAudio != aMediaId.iMediaType ) + { + return KErrNotSupported; + } + */ + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SetSourceDataTypeCode"); + iFourCC = aSourceFourCC; + iMediaId = aMediaId; + iClip->SetSourceDataTypeCode( iFourCC, iMediaId ); + return KErrNone; + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SourceThreadLogon +// Log in to the source thread +// ----------------------------------------------------------------------------- +// +TInt CMsrpPayloadFormatRead::SourceThreadLogon( + MAsyncEventHandler& aEventHandler ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SourceThreadLogon"); + iEventHandler = &aEventHandler; + iClip->SourceThreadLogon( aEventHandler ); + return KErrNone; + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::NegotiateSourceL( MDataSink& aDataSink ) +// Negotiate source settings to match data sink object. +// Re-size frame buffers if needed +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::NegotiateSourceL( MDataSink& /*aDataSink*/ ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::NegotiateSourceL"); + __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); + iClip->NegotiateSourceL( *this ); + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SourceThreadLogoff +// Log out of the source thread. +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::SourceThreadLogoff() + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SourceThreadLogoff"); + iClip->SourceThreadLogoff( ); + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::FilterUnwantedData +// this method can be used to filter unwanted data off +// +// e.g SipCon1 sends BOM data in first String and PS data as carriage return +// Engine should NOT touch these but Presentation layer should take care of these + +// Method can be used to filtering pusposes if needed +// ----------------------------------------------------------------------------- +// +TBool CMsrpPayloadFormatRead::FilterUnwantedData(const TDesC8& aBuffer) +{ + + //TODO: We must do a entity recognizer, which handles this kind of data + // This does not affect to actual formatter, instead we + // a) must do it to application side + // b) we must define an interface, which can be called + TBool ret = ETrue; + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::FilterUnwantedData() - BufferSize:%d",aBuffer.Length()); + + //get Three first or Three last chars + if( aBuffer.Length() >= 3 ) + { + //SipCon sends BOM for the first time + TPtrC8 pBOM = aBuffer.Left(3); + if ( pBOM[0] == 0xEF && pBOM[1] == 0xBB && pBOM[2]== 0xBF) + { + //return EFalse if want to filter the whole message + ret = ETrue; + } + + + // last are unicode PS char ( return ) + TPtrC8 pPS = aBuffer.Right(3); + if ( pPS[0] == 0xE2 && pPS[1] == 0x80 && pPS[2]== 0xA8) + { + //return EFalse if want to filter + ret = ETrue; + } + + } + //There might be back spaces and other marks + else if( aBuffer.Length() >= 1 ) + { + TPtrC8 pChar = aBuffer.Left(1); + if( pChar[0] == 0x08 ) + { + ret = ETrue; + } + //bell + else if( pChar[0] == 0x07) + { + ret = ETrue; + } + //tab + else if( pChar[0] == 0x09) + { + ret = ETrue; + } + //escape + else if( pChar[0] == 0x1B) + { + ret = ETrue; + } + + //etc + } + + return ret; +} +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::BufferFilledL +// Called after the data buffer is filled. Update the number of bytes read +// and the current read position for the next read operation. +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::DataBufferFilledL( CMMFBuffer* aBuffer, + const TRtpRecvHeader& aRtpHeader ) + { + + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::SendDataToSinkL() - BufferSize:%d",aBuffer->BufferSize()); + + __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( aBuffer->Type() == KUidMmfDataBuffer, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iStateMachine, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iFrameBufferOne , User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iFrameBufferTwo , User::Leave( KErrArgument ) ); + + + DP_MSRP_WRITE("CMsrpPayloadFormatRead::BufferFilledL with RTP header param:"); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iPadding: %d", aRtpHeader.iPadding ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iExtension: %d", aRtpHeader.iExtension ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iCsrcCount: %d", aRtpHeader.iCsrcCount ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iMarker: %d", aRtpHeader.iMarker ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iPayloadType: %d", aRtpHeader.iPayloadType ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iSeqNum: %d", aRtpHeader.iSeqNum ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iTimestamp: %d", aRtpHeader.iTimestamp ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iHeaderExtension: %d", (TInt)aRtpHeader.iHeaderExtension ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iCsrcList: %d", (TInt)aRtpHeader.iCsrcList ); + + // Do not forward smaller zero length buffers or unwanted data + if ( aBuffer->BufferSize() > 0 && FilterUnwantedData(static_cast( aBuffer )->Data()) ) + { + //check seqnumber, if first packet get sequence Nr. from it + if ( iPacketCount == 0 ) + { + //if marker == 1, then we know this is the first packet + if(aRtpHeader.iMarker == 1) + { + // flag to indicate, because first of idle sends this also + if ( !iPacketSecNumber ) + { + iSatisfySecNumber = aRtpHeader.iSeqNum; + iCheckSum = iSatisfySecNumber; + iPacketSecNumber = ETrue; + } + } + else + { + // first packet was missing, signal this + iFirstPacketsMissing = ETrue; + DP_MSRP_WRITE("First Packet Is MISSING!"); + } + + } + else + { + // 0, -1, -2; ( 0 means expected packet arrived ) + //iLevelsMissing = iSatisfySecNumber - aRtpHeader.iSeqNum; + iLevelsMissing = 0; + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iLevelsMissing: %d", iLevelsMissing ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL aRtpHeader.iSeqNum: %d", aRtpHeader.iSeqNum ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::BufferFilledL iSatisfySecNumber: %d", iSatisfySecNumber ); + } + + + iPacketCount++; + // check for packets arriving late, redundant data allready got + if ( iLevelsMissing <= 0) + { + // we add packet count here. This is for physical packets, not for redundant data + + if ( iFrameBufferOne->Status() == EAvailable ) + { + iFrameBufferOne->Data().Copy( static_cast( aBuffer )->Data() ); + iFrameBufferOne->SetTimeToPlay( aRtpHeader.iTimestamp ); + iFrameBufferOne->SetLastBuffer( aRtpHeader.iMarker ); + iFrameBufferOne->SetFrameNumber( aRtpHeader.iSeqNum ); + iFrameBufferOne->SetStatus( EFull ); + + if (iFrameBufferTwo->Status() == EAvailable ) + { + iCurrentBuffer = iFrameBufferOne; + iStateMachine->ChangeState( ESourceDataReady ); + } + } + else if ( iFrameBufferTwo->Status() == EAvailable ) + { + iFrameBufferTwo->Data().Copy( static_cast( aBuffer )->Data() ); + iFrameBufferTwo->SetTimeToPlay( aRtpHeader.iTimestamp ); + iFrameBufferTwo->SetLastBuffer( aRtpHeader.iMarker ); + iFrameBufferTwo->SetFrameNumber( aRtpHeader.iSeqNum ); + iFrameBufferTwo->SetStatus( EFull ); + + if (iFrameBufferOne->Status() == EAvailable ) + { + iCurrentBuffer = iFrameBufferTwo; + iStateMachine->ChangeState( ESourceDataReady ); + } + } + else + { + // Neither of the buffers is available and leave + User::Leave( KErrNotReady ); + } + } + else + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::BufferFilledL IGNORING Packet, data recovered!"); + } + + } + else + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::BufferFilledL NO PAYLOAD, Data smaller than 8 bytes "); + iStateMachine->ChangeState( EWaitSourceData ); + } + + +} + + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::DecodePayloadL( const TDesC8& aBuffer ) +// +// Decodec payload according level 2 redundancy ( RFC 4103 ) +// First there are Normal RTP Header, which was extracted by RTP Stack. +// Then there are two 32-bit Redundant headers and one 8 -bit primary Header. +// Then there are R2, R1 and Primary data appended respectively. +// ----------------------------------------------------------------------------- +// +TInt CMsrpPayloadFormatRead::DecodePayloadL( const TDesC8& aBuffer ) +{ + DP_MSRP_WRITE("CMsrpPayloadFormatRead::DecodePayload()"); + + TInt ret = KErrNone; + RDebug::Print( _L("CMsrpPayloadFormatRead::DecodePayload() -> %d") , aBuffer.Size() ); + const TUint8* aPtr = aBuffer.Ptr(); + TInt ctr(0); + + // get 1st 32 = R2 header + TUint32 r2Header = Read32( aPtr ); + + RDebug::Print( _L("CMsrpPayloadFormatRead R2 Header Data : %x"), r2Header ); + aPtr += 4; + ctr+= 4; + TUint16 aR2Lenght(0), aR2TimeStamp(0); + TInt err = ParseRedHeader( r2Header, aR2Lenght, aR2TimeStamp ); + + RDebug::Print( _L("CMsrpPayloadFormatRead R2 Lengt : %d , TimeStamp %x "), aR2Lenght, aR2TimeStamp ); + if( err ) + { + User::Leave( err ); + } + + // get 2nd 32 = R1 header + TUint32 r1Header = Read32( aPtr ); + RDebug::Print( _L("CMsrpPayloadFormatRead R1 Header Data : %x"), r1Header ); + aPtr += 4; + ctr +=4; + TUint16 aR1Lenght(0), aR1TimeStamp(0); + err = ParseRedHeader( r1Header, aR1Lenght, aR1TimeStamp ); + RDebug::Print( _L("CMsrpPayloadFormatRead R1 Lengt : %x , TimeStamp %x "), aR1Lenght, aR1TimeStamp ); + if( err ) + { + User::Leave( err ); + } + + // get + TUint8 aPt = ( Read8( aPtr ) & 255 ); + aPtr += 1; + ctr += 1; + TUint8 pPayloadType = ( aPt & 127 ); + TUint8 pBit = ( aPt >> 7 ); + + RDebug::Print( _L("CMsrpPayloadFormatRead Primary data : %d "), aPt ); + RDebug::Print( _L("CMsrpPayloadFormatRead Primary bit : %d , PT %d "), pBit, pPayloadType ); + + //TODO: When IOP-Tests Are done clean me out. + TPtr8 pP = iCharData->Des(); + pP.FillZ(); + pP.Zero(); + pP.Append(aPtr, aR2Lenght); + aPtr += aR2Lenght; + TBuf16 unicode; + User::LeaveIfError( + CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode, pP )); + TStringElement data; + data.iData = unicode; + iRedData->AppendL(data); + + RDebug::Print( _L("CMsrpPayloadFormatRead GOT Data %S "), &pP ); + + pP.FillZ(); + pP.Zero(); + pP.Append(aPtr, aR1Lenght); + aPtr += aR2Lenght; + unicode.FillZ(); + unicode.Zero(); + User::LeaveIfError( + CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode, pP )); + data.iData = unicode; + iRedData->AppendL(data); + + RDebug::Print( _L("CMsrpPayloadFormatRead GOT Data %S "), &pP ); + TInt rest = aBuffer.Size() - ( ctr + aR2Lenght + aR1Lenght); + + //NO PRIMARY DATA, means redundant packet + if( rest == 0) + { + ret = KErrNotFound; + } + + RDebug::Print( _L("CMsrpPayloadFormatRead Rest %d "), rest ); + + pP.FillZ(); + pP.Zero(); + pP.Append(aPtr, rest ); + aPtr += aBuffer.Size(); + unicode.FillZ(); + unicode.Zero(); + User::LeaveIfError( + CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode, pP )); + data.iData = unicode; + iRedData->AppendL(data); + + RDebug::Print( _L("CMsrpPayloadFormatRead GOT Data %S "), &pP ); + return ret; + +} + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::ParseRedHeader +// Small helper method that parses the 32-bit redundant header +// according to RFC 4103 +// ----------------------------------------------------------------------------- +// +TInt CMsrpPayloadFormatRead::ParseRedHeader(TUint32 /*aHeader*/, TUint16& /*aLenght*/, TUint16& /*aTimeStamp*/ ) +{ + // Not Supported +#if 0 + TUint8 aPt = ( aHeader >> 24 ) & 255; + TUint8 aTest = ( aHeader ) & 255; + + TUint8 aBit = ( aPt >> 7 ) & 1; + TUint8 aPayloadType = ( aPt & 127 ); + //TODO: Checks fi PayloadTypes and bits match + + aTimeStamp = ( aHeader >> 10 ) & 0x3FFF; + aLenght = ( aHeader & 0x3FF ); + //TODO: Checks if timestampoffset and lenght is ok +#endif + return KErrNone; +} + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::HandleRedundancyL +// Logic method, that updates all counters and decides what data we should +// append to userBuffer. If packets are missing, we must use redundant data +// ----------------------------------------------------------------------------- +// +TInt CMsrpPayloadFormatRead::HandleRedundancyL(TInt aErrNo) +{ + + DP_MSRP_WRITE2("CAnyPayloadFormatRead::BufferFilledL iLevelsMissing: %d", iLevelsMissing ); + DP_MSRP_WRITE2("CAnyPayloadFormatRead::BufferFilledL iFirstPacketsMissing: %d", iFirstPacketsMissing ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::HandleRedundancy() -> 0 :%S", &iRedData->At(0).iData ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::HandleRedundancy() -> 1 :%S", &iRedData->At(1).iData ); + DP_MSRP_WRITE2("CMsrpPayloadFormatRead::HandleRedundancy() -> 2 :%S", &iRedData->At(2).iData ); + + //if first packet is missing handle all redData + if( iFirstPacketsMissing ) + { + iDecodedBuffer->Data().Append( iRedData->At(2).iData ); + iDecodedBuffer->Data().Append( iRedData->At(1).iData ); + iDecodedBuffer->Data().Append( iRedData->At(0).iData ); + iSatisfySecNumber += 3; + } + else // check levels from + { + switch(iLevelsMissing) + { + case(0): + // expected packet errived + iDecodedBuffer->Data().Append(iRedData->At(2).iData); + iSatisfySecNumber ++; + break; + + case(-1): // one packet missing + if( aErrNo ) + { + iDecodedBuffer->Data().Append(iRedData->At(2).iData); + } + if ( iRedData->At(1).iData.Length() != 0 ) + { + iDecodedBuffer->Data().Append(iRedData->At(1).iData); + } + iSatisfySecNumber += 2; + iDroppedPacketCount += 1; + break; + + case(-2): // two packets missing + if( aErrNo ) + { + iDecodedBuffer->Data().Append(iRedData->At(2).iData); + } + if ( iRedData->At(1).iData.Length() != 0 ) + { + iDecodedBuffer->Data().Append(iRedData->At(1).iData); + } + if ( iRedData->At(0).iData.Length() != 0 ) + { + iPayloadBuffer->Data().Append(iRedData->At(0).iData); + } + iSatisfySecNumber += 3; + iDroppedPacketCount += 2; + break; + + default: + //bacause if network idles or in debugging state + // a lot of packets might not be received. + //we are handlng all as missing chars + DP_MSRP_WRITE("CMsrpPayloadFormatRead::LevelsMissing > 2!"); + + iDecodedBuffer->Data().Append(KLostChar); + iSatisfySecNumber += (-iLevelsMissing ) +1; + iDroppedPacketCount += (-iLevelsMissing ); + + break; + } + } + return KErrNone; +} + + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::ResetPacketBuffers() +// Helper method that that resets all buffers used +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::ResetPacketBuffers() + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::ResetPacketBuffers()"); + iRedData->Reset(); + iCharData->Des().FillZ(); + iCharData->Des().Zero(); + iDecodedBuffer->Data().FillZ(); + iDecodedBuffer->Data().Zero(); + } + + +// NOT CALLED, BECAUSE WE ARE USING RTP ONLY +void CMsrpPayloadFormatRead::BufferFilledL( CMMFBuffer* /*aBuffer*/ ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::BufferFilledL"); + User::Leave( KErrNotSupported ); + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::Duration +// Return the clip duration for the given media. +// ----------------------------------------------------------------------------- +// +TTimeIntervalMicroSeconds CMsrpPayloadFormatRead::Duration( + TMediaId /*aMediaType*/ ) const + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::Duration"); + return TTimeIntervalMicroSeconds( TInt64( 0 ) ); + } + + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::LastDlPacketCount +// Return current packet count for current talk spurt +// ----------------------------------------------------------------------------- +// +TInt CMsrpPayloadFormatRead::LastDlPacketCount( ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::LastDlPacketCount"); + return iPacketCount; + } + + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::CancelDlRequest( ) +// +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::CancelDlRequest() + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::CancelDlRequest"); + iStateMachine->Cancel(); + iStateMachine->ChangeState( EDecodeIdle ); + + if ( iFrameBufferOne && iFrameBufferTwo ) + { + iFrameBufferOne->SetLastBuffer( EFalse ); + iFrameBufferTwo->SetLastBuffer( EFalse ); + + iFrameBufferOne->SetStatus( EAvailable ); + iFrameBufferTwo->SetStatus( EAvailable ); + } + + iBufferToReadExists = EFalse; + iCurrentBuffer = iFrameBufferOne; + iFillRequested = EFalse; + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SourcePrimeL() +// +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::SourcePrimeL() + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SourcePrimeL"); + __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); + iClip->SourcePrimeL(); + } + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SourcePlayL() +// +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::SourcePlayL() + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SourcePlayL"); + __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); + + // init packet count + iPacketCount = 0; + + //init satisfiable sec number count + iSatisfySecNumber = 0; + + iCheckSum = 0; + + // init levelsMissingNumber + iLevelsMissing = 0; + + //init flag + iPacketSecNumber = EFalse; + + iClip->SourcePlayL(); + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SourcePauseL() +// +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::SourcePauseL() + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SourcePauseL"); + __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); + + this->CancelDlRequest(); + iClip->SourcePauseL(); + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SourceStopL( ) +// +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::SourceStopL() + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SourceStopL"); + __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); + + this->CancelDlRequest(); + iClip->SourceStopL(); + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::SinkDataTypeCode() +// Returns the datatype code for this Format Decoder +// ----------------------------------------------------------------------------- +// +TFourCC CMsrpPayloadFormatRead::SinkDataTypeCode( TMediaId aMediaId ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::SinkDataTypeCode"); + //TODO: We have to check that media type text + + if ( KUidMediaTypeAudio == aMediaId.iMediaType ) + { + return iFourCC; + } + else + { + return TFourCC(); //defaults to 'NULL' fourCC + } + + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::ConfigurePayloadFormatL +// Configure payload decoding parameters. +// ----------------------------------------------------------------------------- +// +void CMsrpPayloadFormatRead::ConfigurePayloadFormatL( + const TDesC8& aConfigParams ) + + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::ConfigurePayloadFormatL"); + TMccCodecInfoBuffer infoBuffer; + infoBuffer.Copy( aConfigParams ); + TMccCodecInfo cInfo = infoBuffer(); + + if ( cInfo.iIsUpdate && cInfo.iFrameSize == iCodecInfo.iFrameSize ) + { + //__MsrpFORMAT_CONTROLL( "CMsrpPayloadFormatRead::ConfigurePayloadFormatL, nothing to configure" ) + return; + } + + UpdateConfigurationL( aConfigParams ); + +} + + +void CMsrpPayloadFormatRead::UpdateConfigurationL(const TDesC8& aConfigParams) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::UpdateConfigurationL"); + TMccCodecInfoBuffer infoBuffer; + infoBuffer.Copy( aConfigParams ); + TMccCodecInfo cInfo = infoBuffer(); + + //TODO: get me right + // iCodecInfo = cInfo; + // iCodecInfo.iRedundancyCount = 0; + iCodecInfo = cInfo; + + //Create buffers respectively + if ( !iFrameBufferOne ) + { + iFrameBufferOne = + CMMFDataBuffer::NewL( KRedHeaderSize + KDataSize ); + iFrameBufferOne->SetStatus( EAvailable ); + } + + if ( !iFrameBufferTwo ) + { + iFrameBufferTwo = + CMMFDataBuffer::NewL( KRedHeaderSize + KDataSize ); + iFrameBufferTwo->SetStatus( EAvailable ); + } + + if ( iPayloadBuffer && iSourceBufOwnership ) + { + delete iPayloadBuffer; + iPayloadBuffer = NULL; + } + + iPayloadBuffer + = CreateClipBufferL( KRedHeaderSize + KDataSize, iSourceBufOwnership ); + + iCurrentBuffer = NULL; + + } +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::CreateClipBufferL +// Creates buffer needed in data transfer with format readers clip. +// ----------------------------------------------------------------------------- +// +CMMFDataBuffer* CMsrpPayloadFormatRead::CreateClipBufferL( + TUint aSize, TBool& aIsOwnBuffer ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::CreateClipBufferL"); + CMMFDataBuffer* buffer( NULL ); + + if ( iClip->CanCreateSourceBuffer() ) + { + static_cast( iClip )->SuggestSourceBufferSize( aSize ); + TBool reference( EFalse ); + + //TODO: We have to change media type + 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; + + } + +// ========================== HELPER FUNCTIONS ========================= +// ========================== ========================= +// ========================== ========================= + + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::Read32 +// Helper method that reads 32-bit unsigned integer from databuffer +// ----------------------------------------------------------------------------- +// +TUint32 CMsrpPayloadFormatRead::Read32( const TUint8* const aPointer ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::Read32"); + return ( aPointer[3] + + ( static_cast( aPointer[2] ) << 8 ) + + ( static_cast( aPointer[1] ) << 16 ) + + ( static_cast( aPointer[0] ) << 24 ) ); + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::Read8 +// Helper method that reads 8-bit unsigned integer from databuffer +// ----------------------------------------------------------------------------- +TUint32 CMsrpPayloadFormatRead::Read8( const TUint8 *const aPointer ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::Read8"); + + return static_cast ( aPointer[0] ); + } + +// ----------------------------------------------------------------------------- +// CMsrpPayloadFormatRead::Read24 +// Helper method that reads 24-bit unsigned integer from databuffer +// ----------------------------------------------------------------------------- +TUint32 CMsrpPayloadFormatRead::Read24( const TUint8 *const aPointer ) + { + DP_MSRP_WRITE("CMsrpPayloadFormatRead::Read24"); + + return ( aPointer[2] + ( static_cast( aPointer[1] ) << 8 ) + + ( static_cast( aPointer[0] ) << 16 ) ); + } + + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + +// End of File