--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccMsrppayloadformat/src/Msrppayloadformatwrite.cpp Mon Sep 06 17:32:13 2010 +0530
@@ -0,0 +1,1052 @@
+/*
+* 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 <rtpheader.h>
+#include <e32cmn.h>
+#include <utf.h> // charconv.lib
+
+#include "msrppayloadformatwrite.h"
+#include "mccrtpdatasink.h"
+#include "Mccrtpinterface.h"
+
+#include "mccmsrpformatlogs.h"
+#include "mccuids.hrh"
+#include "mccdef.h"
+#include "mccrtpmediaclock.h"
+#include "mccinternaldef.h"
+#include "msrppayloadformatdefs.h"
+#include "mmccinterfacedef.h"
+#include "mccmsrpsink.h"
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatRead::CMsrpPayloadFormatRead
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+// iIdleMode is set to ETrue, because when starting we are in IdleMode
+// -----------------------------------------------------------------------------
+//
+CMsrpPayloadFormatWrite::CMsrpPayloadFormatWrite(): iIdleMode(ETrue)
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::ConstructL ( MDataSink* aSink )
+ {
+
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::ConstructL");
+
+ // Set default values
+ iFourCC = KMccFourCCIdMSRP ;
+ //iFourCC.Set( TFourCC( 'T','1','4','0' ) );
+
+ //we are going upstream, so our source is the datapath and
+ // sink is the clip. If we use RTP, which we do,
+ // our sink is of cource the RTPSink
+ iClip = aSink;
+ iIsRtpSink = ( KMccRtpSinkUid == aSink->DataSinkType() );
+ iIsMsrpSink = (KMccMsrpSinkUid == aSink->DataSinkType() );
+
+ // two levels of redundancy is allways assumed, not necessarily used
+ // RFC4103 RECOMMENDED
+ iRedData = new(ELeave)CArrayFixFlat<TStringElement>(3);
+
+ //userBuffer, handles all data put in by user
+ iUserBuffer = new(ELeave)CArrayFixFlat<TStringElement>(3);
+
+ // init data to null
+ TStringElement one;
+ TStringElement two;
+ TStringElement three;
+ iRedData->AppendL(one);
+ iRedData->AppendL(two);
+ iRedData->AppendL(three);
+
+ // maxsize of the packet
+ iBuf = HBufC8::NewL( KRedHeaderSize + KDataSize );
+ iData = const_cast<TUint8*>( iBuf->Des().Ptr() );
+
+ if ( iIsRtpSink )
+ {
+ CMccRtpDataSink* tmp = static_cast<CMccRtpDataSink*>( aSink );
+ iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp );
+ }
+ else if(iIsMsrpSink)
+ {
+ CMccMsrpSink *tmp = static_cast<CMccMsrpSink*>( aSink );
+ iMsrpDataSink = static_cast<CMccMsrpSink*>( tmp );
+ }
+ else
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::ConstructL Leaving: No RTPSink!");
+ User::Leave(KErrNotSupported);
+ }
+
+ // Initialize state machine
+ iStateMachine = CFormatEncodeStateMachine::NewL( this );
+
+ //init state machine to idle state
+ iStateMachine->ChangeState( EEncodeIdle );
+
+ // Construct Timer for redundant generations.
+ iTimer = CSendStateMachine::NewL( this );
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMsrpPayloadFormatWrite* CMsrpPayloadFormatWrite::NewL ( MDataSink* aSink )
+ {
+
+
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::NewL" );
+ __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
+
+ CMsrpPayloadFormatWrite* self = new (ELeave) CMsrpPayloadFormatWrite;
+ CleanupStack::PushL( self );
+ self->ConstructL( aSink );
+ CleanupStack::Pop( self );
+ return self;
+
+ }
+
+// Destructor
+CMsrpPayloadFormatWrite::~CMsrpPayloadFormatWrite ()
+ {
+
+ if ( iStateMachine )
+ {
+ iStateMachine->Cancel();
+ delete iStateMachine;
+ }
+
+ if(iTimer)
+ {
+ iTimer->Cancel();
+ delete iTimer;
+ }
+
+
+ iRtpMediaClock = NULL;
+ iClip = NULL;
+
+ delete iSourceBuffer;
+ delete iSinkBuffer;
+ delete iRedData;
+ delete iUserBuffer;
+ delete iBuf;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkThreadLogon
+// Passes the logon command to the sink clip
+// -----------------------------------------------------------------------------
+//
+TInt CMsrpPayloadFormatWrite::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkThreadLogon");
+ iClip->SinkThreadLogon( aEventHandler );
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkThreadLogoff
+// Passes the logoff command to the sink clip
+// -----------------------------------------------------------------------------
+void CMsrpPayloadFormatWrite::SinkThreadLogoff()
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkThreadLogoff");
+ iClip->SinkThreadLogoff();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::CreateSinkBufferL
+// Create a sink buffer
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CMsrpPayloadFormatWrite::CreateSinkBufferL( TMediaId /*aMediaId*/,
+ TBool &aReference )
+ {
+
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::CreateSinkBufferL" );
+
+ /* TODO: Remove me when platform supports
+ if ( KUidMediaTypeText != aMediaId.iMediaType )
+ {
+ User::Leave( KErrNotSupported );
+ }
+ */
+ aReference = ETrue;
+ return CreateSinkBufferOfSizeL( KMaxRTTChunkSize + KRedHeaderSize );
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::CreateSinkBufferOfSizeL
+// Create a sink buffer of the given size.
+// -----------------------------------------------------------------------------
+//
+CMMFDataBuffer* CMsrpPayloadFormatWrite::CreateSinkBufferOfSizeL( TUint aSize )
+ {
+
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::CreateSinkBufferOfSizeL" );
+
+ if ( !iSourceBuffer )
+ {
+ iSourceBuffer = CMMFDataBuffer::NewL( aSize );
+ iSourceBuffer->Data().FillZ( aSize );
+ iSourceBuffer->SetRequestSizeL( aSize );
+ }
+
+ return iSourceBuffer;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::EmptyBufferL
+// Empty the given source buffer
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::EmptyBufferL( CMMFBuffer* aBuffer,
+ MDataSource* aSupplier,
+ TMediaId /*aMediaId*/ )
+ {
+
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::EmptyBufferL");
+
+ __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) );
+ __ASSERT_ALWAYS ( aBuffer == iSourceBuffer, User::Leave( KErrArgument ) );
+ __ASSERT_ALWAYS( aSupplier, User::Leave( KErrArgument ) );
+
+ // TODO: Remove me when platform supports
+ // __ASSERT_ALWAYS( KUidMediaTypeAudio == aMediaId.iMediaType,
+ // User::Leave( KErrNotSupported ) );
+
+ // Cancel timer, so timer does not interrupt our current sending.
+ // Timer enables empty blocks to be appended when redundancy is on.
+ iTimer->Cancel();
+
+ iDataPath = aSupplier;
+ iSourceBuffer = static_cast<CMMFDataBuffer*>( aBuffer );
+
+ if ( !iSinkBuffer )
+ {
+ iStateMachine->ChangeState( ESourceBufferEmptied );
+ return;
+ }
+
+ if ( !iSinkBuffer->Data().Length() )
+ {
+ //User::LeaveIfError( iRtpMediaClock->GetTimeStamp( iKey, iCurrentTimestamp ) );
+ iSinkBuffer->SetTimeToPlay( TInt64( iCurrentTimestamp ) );
+ iSinkBuffer->SetFrameNumber( aBuffer->FrameNumber() );
+ }
+
+
+ // We signal StateMachine to ChangeState()
+ // this calls back EmptySourceBufferL
+ iStateMachine->ChangeState( EEmptySourceBuffer );
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SetSinkDataTypeCode
+// Set the sink data type to the given four CC code for the given media
+// -----------------------------------------------------------------------------
+//
+TInt CMsrpPayloadFormatWrite::SetSinkDataTypeCode( TFourCC aSinkFourCC,
+ TMediaId /*aMediaId*/ )
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SetSinkDataTypeCode");
+ /* TODO: Remove me when platform supports
+ if ( KUidMediaTypeText != aMediaId.iMediaType )
+ {
+ User::Leave( KErrNotSupported );
+ }
+ */
+ iFourCC = aSinkFourCC;
+ return KErrNone;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkDataTypeCode
+// Return the sink data type (four CC code) for the given media ID
+// -----------------------------------------------------------------------------
+//
+TFourCC CMsrpPayloadFormatWrite::SinkDataTypeCode( TMediaId /*aMediaId*/ )
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkDataTypeCode");
+ /* TODO: Remove me when platform supports
+ if ( KUidMediaTypeText == aMediaId.iMediaType )
+ {
+ return iFourCC;
+ }
+ else
+ {
+ return TFourCC(); //defaults to 'NULL' fourCC
+ }
+ */
+ return iFourCC;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::BufferEmptiedL
+// Called after payload buffer is completely emptied by RtpDataSink.
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ )
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::BufferEmptiedL" );
+ // nothing to be done
+
+ //NOTE: 14.12.2007 - LeaveScan causes warning, but this is a interface method
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::FrameTimeInterval
+// Return the frame time interval for the given media
+// Return allways 0
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds
+ CMsrpPayloadFormatWrite::FrameTimeInterval( TMediaId /*aMediaId*/ ) const
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::FrameTimeInterval" );
+ return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::Duration
+// Return the frame time interval for the given media
+// NOT SUPPORTED
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds
+ CMsrpPayloadFormatWrite::Duration( TMediaId /*aMediaType*/ ) const
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::Duration" );
+ return TTimeIntervalMicroSeconds( TInt64( 0 ) );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::EmptySourceBufferL
+// Empty the given sourcebuffer
+// Sourcebuffer is given in iSourceBuffer
+// Called by StateMachine
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::EmptySourceBufferL()
+ {
+
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::EmptySourceBufferL" );
+
+ const TDesC8& srcDes( iSourceBuffer->Data() );
+ const TUint8* srcPtr = srcDes.Ptr();
+ TInt length = iSourceBuffer->Data().Length();
+
+ if ( iSourceBuffer->Data().Length() )
+ {
+
+ if( KMaxRTTChunkSize < length )
+ {
+ DP_MSRP_WRITE( "ERR - RTT Payload Length exceeded MaxChunkSize" );
+ User::Leave(KErrArgument);
+ }
+
+ TBuf16<KMaxRTTChunkSize> unicode;
+ User::LeaveIfError(
+ CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode, TPtrC8(srcPtr)));
+
+ //buffer the user data
+ TStringElement buffer;
+ buffer.iData = unicode;
+ iUserBuffer->AppendL(buffer);
+
+ FormUserDataL();
+ ForwardDataL();
+
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::TimerExpiredL()
+// Sends Redundant data after buffer period, if no user data
+// appeared before that.
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::TimerExpiredL()
+{
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::TimerExpiredL" );
+
+ // Because timer expired, we must send redundant data anyway
+ TStringElement nullData;
+ iUserBuffer->AppendL(nullData);
+
+ FormUserDataL();
+ //TODO:Handle other Errors if any
+ TInt err = SendRedundantDataL();
+ if ( err != KErrNone )
+ {
+ GotoIdleL();
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::ForwardDataL()
+// Sends Redundant data after buffer period, if no user data
+// appeared before that.
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::ForwardDataL()
+{
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::ForwardDataL" );
+
+ // Just Send Data
+ TInt err = SendRedundantDataL();
+
+ if ( err == KErrNone )
+ {
+ iStateMachine->ChangeState( ESourceBufferEmptied );
+ }
+}
+
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SendRedundantDataL()
+// A Method that sends the redundant buffer to Sink
+// Calls CMsrpPayloadFormatWrite::DeliverPacketL
+// -----------------------------------------------------------------------------
+//
+TInt CMsrpPayloadFormatWrite::SendRedundantDataL()
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SendRedundantDataL" );
+
+ TStringElement zero = iRedData->At(0);
+ TStringElement one = iRedData->At(1);
+ TStringElement two = iRedData->At(2);
+
+ DP_MSRP_WRITE( "******************");
+ DP_MSRP_WRITE2( "SendRedundantDataL - Zero Lenght: %d", zero.iData.Length() );
+ DP_MSRP_WRITE2( "SendRedundantDataL - R1 Lenght: %d", one.iData.Length() );
+ DP_MSRP_WRITE2( "SendRedundantDataL - R2 lenght: %d", two.iData.Length() );
+
+ if ( zero.iData.Length() == 0 && one.iData.Length() == 0 && two.iData.Length() == 0 )
+ {
+ DP_MSRP_WRITE( "ERR - SendRedundantDataL - All Data is 0 lenght returning, KErrArgument!");
+ return KErrArgument;
+ }
+
+ TDes8& destDes( iSinkBuffer->Data() );
+
+ // Assemble redundant data
+ AssembleRedPacket();
+ // Append current data to buffer
+ TPtr8 ptr = iBuf->Des();
+ destDes.Append( ptr );
+
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite HeapData size: %d", ptr.Size() );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite HeapData Length: %d", ptr.Length() );
+ DP_MSRP_WRITE ("CMsrpPayloadFormatWrite::DeliverPacketL, Packet Assembled" );
+ DP_MSRP_WRITE( "******************");
+
+ DeliverPacketL( *iSinkBuffer );
+ return KErrNone;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::FormUserDataL()
+//
+// A function that refreshes the RedundantData Buffer, so that
+// We just can send data that is there.
+// -----------------------------------------------------------------------------
+//
+TInt CMsrpPayloadFormatWrite::FormUserDataL()
+{
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SendRedundantDataL" );
+
+ TStringElement primary;
+
+ // if there is data
+ if ( iUserBuffer->Count() )
+ {
+ primary = iUserBuffer->At(0);
+ }
+
+ //set timestamp to primary data, this is used to calculate offset
+ primary.iTimestamp = iSinkBuffer->TimeToPlay().Int64();
+
+ // can now reset user buffer
+ iUserBuffer->Reset();
+
+ // get current redundants
+ TStringElement zero = iRedData->At(0);
+ TStringElement one = iRedData->At(1);
+
+ // we can now reset old redundant also
+ iRedData->Reset();
+
+ // re-order redundant data, this must be always present,
+ // if redundancy changes on-fly from e.g 0 to 2
+ iRedData->AppendL(primary);
+ iRedData->AppendL(zero);
+ iRedData->AppendL(one);
+
+ return KErrNone;
+}
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::GoToIdleL()
+//
+// When there is no data to send, we must go to idle mode
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::GotoIdleL()
+ {
+
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::GoToIdleL()");
+ //reset redundancy buffer
+ iRedData->Reset();
+ //add default data
+ TStringElement empty;
+ iRedData->AppendL(empty);
+ iRedData->AppendL(empty);
+ iRedData->AppendL(empty);
+ iIdleMode = ETrue;
+
+ //Set State that we are waiting for Data
+ iStateMachine->ChangeState( EWaitForSourceData );
+
+ // Cancel the Timer also
+ iTimer->Cancel();
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::AssembleRedPacket()
+//
+// In AssembleRedPacket we must assemble right kind of
+// payload. We switch between redundant and plain data.
+// If redundancy is used a redundant datapacket is generated!
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::AssembleRedPacket()
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::AssembleRedPacket" );
+ switch( iCodecInfo.iRedundancyCount )
+ {
+ case 0:
+ // just append the primary data and no headers
+ iBuf->Des().Append( iRedData->At(0).iData );
+ break;
+
+ case 2:
+ TInt err = GenerateRedPacket();
+ //TODO: Handle Errors in Creating packet
+ break;
+
+ }
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::GenerateRedPacket()
+//
+// In GenerateRedPacket we must assemble right kind of
+// payload according to RFC 4103. Level 2 redundancy is used.
+// -----------------------------------------------------------------------------
+//
+TInt CMsrpPayloadFormatWrite::GenerateRedPacket()
+{
+
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::GenerateRedPacket()" );
+
+ TStringElement primary = iRedData->At(0);
+ TStringElement r1 = iRedData->At(1);
+ TStringElement r2 = iRedData->At(2);
+
+ DP_MSRP_WRITE( "*******************************");
+ DP_MSRP_WRITE2("CMsrpPayloadFormatWrite::GenerateRedPacket PR Length: %d", primary.iData.Length() );
+ DP_MSRP_WRITE2("CMsrpPayloadFormatWrite::GenerateRedPacket R1 Length: %d", r1.iData.Length() );
+ DP_MSRP_WRITE2("CMsrpPayloadFormatWrite::GenerateRedPacket R2 Length: %d", r2.iData.Length() );
+
+ // pointer to data
+ TUint8* dataP = iData;
+ TInt count(0);
+ //Fill Data with binary zeroes and zero old
+ Mem::FillZ( dataP, KRedHeaderSize + KDataSize );
+ iBuf->Des().Zero();
+
+
+ /*************
+ data[0] = 8 bit
+ 1 bit - redundancy marker bit 1
+ 7 bit - payloadtype
+ ***************/
+
+ iData[0] |= ( 1 << 7 );
+ iData[0] |= iCodecInfo.iRedundantPayload;
+ //iData[0] |= 106;
+ dataP += 1;
+ count ++;
+
+
+ /**************
+ data[1-3] = 24 bit
+ 14 bit - timestamp offset of R2
+ 10 bit - length of R2
+ ***************/
+
+ TUint32 temp(0);
+ temp |= ( SetTimeOffset(primary.iTimestamp, r2.iTimestamp ) << 10 );
+
+ TUint16 size(r2.iData.Length());
+ temp |= size;
+
+ Write24(dataP, temp);
+ dataP += 3;
+ count += 3;
+
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[0]: %x", iData[0] );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[1]: %x", iData[1] );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[2]: %x", iData[2] );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[3]: %x", iData[3] );
+
+
+ /**************
+ data[4] = 8 bit
+ 1 bit - redundancy marker bit 1
+ 7 bit - payloadtype
+ ***************/
+
+ iData[4] |= ( 1 << 7 );
+ iData[4] |= iCodecInfo.iRedundantPayload;
+ //iData[4] |= 106;
+ dataP += 1;
+ count ++;
+
+ /**************
+ data[5-7] = 24 bit
+ 14 bit - timestamp offset of R1
+ 10 bit - length of R1
+ ***************/
+
+ temp = 0;
+ temp |= ( SetTimeOffset(primary.iTimestamp, r1.iTimestamp ) << 10 );
+
+ size = r1.iData.Length();
+ temp |= size;
+
+ Write24(dataP, temp);
+ dataP += 3;
+ count += 3;
+
+ /**************
+ data[8] = 8 bit
+ 1 bit - normal marker bit 0
+ 7 bit - payloadtype
+ ***************/
+ iData[8] |= ( 0 << 7 );
+ iData[8] |= iCodecInfo.iPayloadType;
+ //iData[8] |= 105;
+ dataP += 1;
+ count ++;
+
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[4]: %x", iData[4] );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[5]: %x", iData[5] );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[6]: %x", iData[6] );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[7]: %x", iData[7] );
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[8]: %x", iData[8] );
+ DP_MSRP_WRITE( "*******************************");
+
+ //TODO: When IOP-Tests Are done, Write me properly using Append, or some other method
+ TInt forHere = count+r2.iData.Length();
+ TInt index(0);
+ if ( r2.iData.Length() )
+ {
+ for ( TInt i = count; i < forHere; i++ )
+ {
+ iData[i] = r2.iData[index];
+ index++,
+ RDebug::Print( _L(" X Writing R2 DATA[i]: %x"), iData[i] );
+ }
+
+ dataP += r2.iData.Length();
+ count += r2.iData.Length();
+ }
+
+
+ forHere = count+r1.iData.Length();
+ index = 0;
+ if ( r1.iData.Length() )
+ {
+ for ( TInt i = count; i < forHere; i++ )
+ {
+ iData[i] = r1.iData[index];
+ index++;
+ RDebug::Print( _L(" X Writing R1 DATA[i]: %x"), iData[i] );
+ }
+
+ dataP += r1.iData.Length();
+ count += r1.iData.Length();
+ }
+
+
+ forHere = count+primary.iData.Length();
+ index = 0;
+ if ( primary.iData.Length() )
+ {
+ for ( TInt i = count; i < forHere; i++ )
+ {
+ iData[i] = primary.iData[index];
+ index++;
+ RDebug::Print( _L(" X Writing PRIMARY DATA[i]: %x"), iData[i] );
+ }
+
+ dataP += primary.iData.Length();
+ count += primary.iData.Length();
+ }
+
+
+ DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket Writing Lenght: %d", count );
+ iBuf->Des().Append( iData, count );
+ return KErrNone;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::DeliverPacketL
+// Prepare the packet header and deliver the packet to the datasink.
+// -----------------------------------------------------------------------------
+void CMsrpPayloadFormatWrite::DeliverPacketL( CMMFDataBuffer& aPayload )
+ {
+
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::DeliverPacketL");
+
+ if ( !iClip )
+ {
+ User::Leave( KErrNotReady );
+ }
+ const TMediaId mediaId( KUidMediaTypeAudio );
+ const TInt dataSize( aPayload.Data().Size() );
+ DP_MSRP_WRITE2( "MSRP Payload SIZE : %d", dataSize );
+
+ if ( dataSize )
+ {
+ if (iIsMsrpSink)
+ {
+ iMsrpDataSink->EmptyBufferL( &aPayload, this, mediaId );
+ }
+ }
+ aPayload.Data().Zero();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SourceBufferEmptiedL
+// Handle the event that sourcebuffer has been emptied.
+// Sourcebuffer is given in "iSourceBuffer".
+// Called by the statemachine.
+// -----------------------------------------------------------------------------
+void CMsrpPayloadFormatWrite::SourceBufferEmptiedL()
+ {
+
+
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SourceBufferEmptiedL" );
+
+ //Empty all
+ iSourceBuffer->Data().FillZ();
+ iSourceBuffer->Data().Zero();
+ iSinkBuffer->Data().FillZ();
+ iSinkBuffer->Data().Zero();
+ iBuf->Des().FillZ();
+ iBuf->Des().Zero();
+ iDataPath->BufferEmptiedL( iSourceBuffer );
+
+ //Finally we set the timer if we are in red mode
+ switch( iCodecInfo.iRedundancyCount )
+ {
+ case 0:
+ // do nothing
+ break;
+
+ case 2:
+ if ( iIdleMode )
+ {
+ iTimer->Cancel();
+ iTimer->Start();
+ }
+ break;
+ }
+
+ // we are no more in idle,
+ iIdleMode = EFalse;
+
+}
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkPrimeL
+// Prime the sink
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::SinkPrimeL()
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPrimeL()");
+ iClip->SinkPrimeL();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkPrimeL
+// Prime the sink
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::CancelUlRequest()
+ {
+
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::CancelUlRequest()" );
+ iStateMachine->Cancel();
+ iStateMachine->ChangeState( EEncodeIdle );
+
+ // Reset the payload buffer
+ if ( iSinkBuffer )
+ {
+ TDes8& dataDes = static_cast<CMMFDataBuffer*>( iSinkBuffer )->Data();
+ dataDes.SetLength( 0 );
+ }
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkPlayL
+// Start playing.
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::SinkPlayL()
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPlayL" );
+ // Allocate buffer for data transfer between
+ // FormatWrite - MDataSink
+ delete iSinkBuffer;
+ iSinkBuffer = NULL;
+ iSinkBuffer = CMMFDataBuffer::NewL( KRedHeaderSize + KDataSize );
+
+ // Start state machine
+ iStateMachine->ChangeState( EWaitForSourceData );
+
+ iFirstPacketFinished = EFalse;
+
+ // Start a new cycle of frame collecting
+ if ( iSinkBuffer )
+ {
+ iSinkBuffer->SetLastBuffer( EFalse );
+ }
+
+ iClip->SinkPlayL();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkPauseL
+// Pause sink
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::SinkPauseL()
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPauseL" );
+ this->CancelUlRequest();
+ iClip->SinkPauseL();
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SinkStopL
+// Stop sink
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::SinkStopL()
+ {
+ DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPauseL" );
+ // Stop state machine
+ this->CancelUlRequest();
+ iClip->SinkStopL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::ConfigurePayloadFormatL
+// Configure payload encoding parameters
+// ---------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::ConfigurePayloadFormatL( const TDesC8& aConfigParams,
+ CMccRtpMediaClock& /*aClock*/ )
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::ConfigurePayloadFormatL()" );
+
+ //Check that buffer is same size, so we can assume data is correct type
+ __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
+ User::Leave( KErrArgument ) );
+
+ //instantiate correct CodecInfo Structure
+ TMccCodecInfoBuffer infoBuffer;
+ infoBuffer.Copy( aConfigParams );
+ TMccCodecInfo codecInfo( infoBuffer() );
+
+ if ( !codecInfo.iIsUpdate )
+ {
+
+ //iCodecInfo = codecInfo;
+ //iRtpMediaClock = &aClock;
+ //iKey = iRtpMediaClock->RegisterMediaFormat( KDefaultSampleRate, iCodecInfo.iHwFrameTime );
+ }
+ else
+ {
+ UpdateConfigurationL( aConfigParams );
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::UpdateConfigurationL
+// Update payload encoding parameters
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::UpdateConfigurationL( const TDesC8& aConfigParams )
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::UpdateConfigurationL" );
+ __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
+ User::Leave( KErrArgument ) );
+
+ TMccCodecInfoBuffer infoBuffer;
+ infoBuffer.Copy( aConfigParams );
+ TMccCodecInfo codecInfo = infoBuffer();
+
+ iCodecInfo = codecInfo;
+ //iCodecInfo.iPtime = codecInfo.iPtime;
+ //iCodecInfo.iRedundancyCount = 0;
+
+ //iCodecInfo.iPayloadType = codecInfo.iPayloadType;
+ //iCodecInfo.iRedundancyCount = codecInfo.iRedundancyCount;
+ //iCodecInfo.iCodecMode = codecInfo.iCodecMode;
+
+ //TODO: move me to right variable and update buffering time
+ //iTimer->Cancel();
+ //iTimer->SetTimeOut( iCodecInfo.iCodecMode * 1000);
+
+ // Allocate buffer for data transfer between
+ // FormatWrite - MDataSink
+ delete iSinkBuffer;
+ iSinkBuffer = NULL;
+ iSinkBuffer = CMMFDataBuffer::NewL( KRedHeaderSize + KDataSize );
+
+ }
+
+
+
+// ========================== HELPER FUNCTIONS =========================
+// ========================== =========================
+// ========================== =========================
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::Write24
+// Simple helper function, that writes a 24-bit value to databuffer,
+// using pointer
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::Write24( TUint8* const aPointer, TUint32 aValue )
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::Write24" );
+ aPointer[0] = static_cast<TUint8>( ( aValue & 0xFF0000 ) >> 16 );
+ aPointer[1] = static_cast<TUint8>( ( aValue & 0x00FF00 ) >> 8 );
+ aPointer[2] = static_cast<TUint8>( aValue & 0x0000FF );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::Write32
+// Simple helper function, that writes a 32-bit value to databuffer,
+// using pointer
+// -----------------------------------------------------------------------------
+//
+void CMsrpPayloadFormatWrite::Write32( TUint8* const aPointer, TUint32 aValue )
+ {
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::Write32" );
+ aPointer[0] = static_cast<TUint8>( ( aValue & 0xFF000000 ) >> 24 );
+ aPointer[1] = static_cast<TUint8>( ( aValue & 0x00FF0000 ) >> 16 );
+ aPointer[2] = static_cast<TUint8>( ( aValue & 0x0000FF00 ) >> 8 );
+ aPointer[3] = static_cast<TUint8>( aValue & 0x000000FF );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMsrpPayloadFormatWrite::SetTimeOffset
+// Calculates TimeOffset to RedundancyHeader according to
+// RFC 4103. Actually RFC 4103 does not accurately state how ( and where )
+// timeoffset should be calculated. This calculation is based conversations
+// with authors of RFC 4103
+// -----------------------------------------------------------------------------
+//
+TUint16 CMsrpPayloadFormatWrite::SetTimeOffset( TInt64& aPrim, TInt64& aSecond )
+{
+ DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SetTimeOffset" );
+ TInt pOffset = aPrim - aSecond;
+ TUint16 aRet = TUint16(pOffset) & KHighestTimeStampOffset;
+ if( aRet > KHighestTimeStampOffset )
+ {
+ aRet = KHighestTimeStampOffset;
+ }
+ return aRet;
+}
+
+
+TStringElement::TStringElement()
+{
+}
+
+
+// End of File