multimediacommscontroller/mmccMsrppayloadformat/src/Msrppayloadformatwrite.cpp
author vnuitven <>
Mon, 06 Sep 2010 19:02:58 +0530
branchrcs
changeset 51 a13dcee59a62
parent 50 1d8943dd8be6
permissions -rw-r--r--
modifications in the copyright for these files

/*
* Copyright (c) 2010 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