multimediacommscontroller/mmccMsrppayloadformat/src/Msrppayloadformatwrite.cpp
branchrcs
changeset 49 64c62431ac08
child 50 1d8943dd8be6
equal deleted inserted replaced
44:fb024d5e35fa 49:64c62431ac08
       
     1 /*
       
     2 * Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    Provides a comfort noise generator class
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 
       
    20 #include    <rtpheader.h> 
       
    21 #include 	<e32cmn.h>
       
    22 #include 	<utf.h> // charconv.lib
       
    23  
       
    24 #include    "msrppayloadformatwrite.h" 
       
    25 #include    "mccrtpdatasink.h"
       
    26 #include 	"Mccrtpinterface.h"
       
    27 
       
    28 #include    "mccmsrpformatlogs.h"
       
    29 #include    "mccuids.hrh"
       
    30 #include    "mccdef.h"
       
    31 #include    "mccrtpmediaclock.h"
       
    32 #include    "mccinternaldef.h"
       
    33 #include 	"msrppayloadformatdefs.h"
       
    34 #include    "mmccinterfacedef.h"
       
    35 #include    "mccmsrpsink.h"
       
    36 
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CMsrpPayloadFormatRead::CMsrpPayloadFormatRead
       
    40 // C++ default constructor can NOT contain any code, that
       
    41 // might leave.
       
    42 // 
       
    43 // iIdleMode is set to ETrue, because when starting we are in IdleMode
       
    44 // -----------------------------------------------------------------------------
       
    45 //
       
    46 CMsrpPayloadFormatWrite::CMsrpPayloadFormatWrite(): iIdleMode(ETrue)
       
    47     {    
       
    48     }
       
    49     
       
    50 // -----------------------------------------------------------------------------
       
    51 // CMsrpPayloadFormatWrite::ConstructL
       
    52 // Symbian 2nd phase constructor can leave.
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 void CMsrpPayloadFormatWrite::ConstructL ( MDataSink* aSink )
       
    56     {
       
    57      
       
    58     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::ConstructL");
       
    59     
       
    60     // Set default values
       
    61     iFourCC = KMccFourCCIdMSRP ;
       
    62     //iFourCC.Set( TFourCC( 'T','1','4','0' ) );
       
    63 
       
    64 	//we are going upstream, so our source is the datapath and
       
    65 	// sink is the clip. If we use RTP, which  we do, 
       
    66 	// our sink is of cource the RTPSink
       
    67     iClip = aSink;    
       
    68     iIsRtpSink = ( KMccRtpSinkUid  == aSink->DataSinkType() );
       
    69     iIsMsrpSink = (KMccMsrpSinkUid == aSink->DataSinkType() );
       
    70     
       
    71     // two levels of redundancy is allways assumed, not necessarily used
       
    72     // RFC4103 RECOMMENDED
       
    73     iRedData = new(ELeave)CArrayFixFlat<TStringElement>(3);
       
    74     
       
    75     //userBuffer, handles all data put in by user
       
    76     iUserBuffer = new(ELeave)CArrayFixFlat<TStringElement>(3);
       
    77     
       
    78     // init data to null
       
    79     TStringElement one;
       
    80     TStringElement two;
       
    81     TStringElement three;
       
    82     iRedData->AppendL(one);
       
    83     iRedData->AppendL(two); 
       
    84     iRedData->AppendL(three);
       
    85      
       
    86     // maxsize of the packet
       
    87     iBuf = HBufC8::NewL( KRedHeaderSize + KDataSize );
       
    88     iData = const_cast<TUint8*>( iBuf->Des().Ptr() );
       
    89   	
       
    90     if ( iIsRtpSink )
       
    91         {
       
    92         CMccRtpDataSink* tmp = static_cast<CMccRtpDataSink*>( aSink );
       
    93         iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp );
       
    94         }
       
    95     else if(iIsMsrpSink)
       
    96         {
       
    97         CMccMsrpSink *tmp = static_cast<CMccMsrpSink*>( aSink );
       
    98         iMsrpDataSink = static_cast<CMccMsrpSink*>( tmp );
       
    99         }
       
   100     else
       
   101         {
       
   102     	DP_MSRP_WRITE("CMsrpPayloadFormatWrite::ConstructL Leaving: No RTPSink!");
       
   103     	User::Leave(KErrNotSupported);	
       
   104         }
       
   105 
       
   106     // Initialize state machine
       
   107     iStateMachine = CFormatEncodeStateMachine::NewL( this );
       
   108     
       
   109     //init state machine to idle state
       
   110     iStateMachine->ChangeState( EEncodeIdle );
       
   111     
       
   112     // Construct Timer for redundant generations.
       
   113     iTimer = CSendStateMachine::NewL( this ); 
       
   114     
       
   115     }
       
   116 
       
   117     
       
   118 // -----------------------------------------------------------------------------
       
   119 // CMsrpPayloadFormatWrite::NewL
       
   120 // Two-phased constructor.
       
   121 // -----------------------------------------------------------------------------
       
   122 //
       
   123 CMsrpPayloadFormatWrite* CMsrpPayloadFormatWrite::NewL ( MDataSink* aSink )
       
   124     {
       
   125  	
       
   126  	
       
   127  	DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::NewL" );
       
   128     __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
       
   129     
       
   130     CMsrpPayloadFormatWrite* self = new (ELeave) CMsrpPayloadFormatWrite;
       
   131     CleanupStack::PushL( self );
       
   132     self->ConstructL( aSink );
       
   133     CleanupStack::Pop( self );
       
   134     return self;
       
   135     
       
   136     }
       
   137 
       
   138 // Destructor 
       
   139 CMsrpPayloadFormatWrite::~CMsrpPayloadFormatWrite ()
       
   140     {
       
   141     
       
   142     if ( iStateMachine )
       
   143         {
       
   144         iStateMachine->Cancel();
       
   145         delete iStateMachine;
       
   146         }
       
   147     
       
   148     if(iTimer) 
       
   149 	    {
       
   150 	    	iTimer->Cancel();
       
   151 	    	delete iTimer;	
       
   152 	    }
       
   153 	   
       
   154     
       
   155     iRtpMediaClock = NULL;
       
   156     iClip = NULL;
       
   157     
       
   158     delete iSourceBuffer;
       
   159     delete iSinkBuffer;
       
   160     delete iRedData;
       
   161     delete iUserBuffer;
       
   162     delete iBuf;
       
   163    
       
   164     }
       
   165 
       
   166 
       
   167 // -----------------------------------------------------------------------------
       
   168 // CMsrpPayloadFormatWrite::SinkThreadLogon
       
   169 // Passes the logon command to the sink clip
       
   170 // -----------------------------------------------------------------------------
       
   171 //
       
   172 TInt CMsrpPayloadFormatWrite::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
       
   173     {
       
   174     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkThreadLogon");
       
   175     iClip->SinkThreadLogon( aEventHandler );
       
   176     return KErrNone;
       
   177     }
       
   178 
       
   179 
       
   180 // -----------------------------------------------------------------------------
       
   181 // CMsrpPayloadFormatWrite::SinkThreadLogoff
       
   182 // Passes the logoff command to the sink clip
       
   183 // -----------------------------------------------------------------------------
       
   184 void CMsrpPayloadFormatWrite::SinkThreadLogoff()
       
   185     {   
       
   186     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkThreadLogoff");
       
   187     iClip->SinkThreadLogoff();
       
   188     }
       
   189 
       
   190 
       
   191 // -----------------------------------------------------------------------------
       
   192 // CMsrpPayloadFormatWrite::CreateSinkBufferL
       
   193 // Create a sink buffer
       
   194 // -----------------------------------------------------------------------------
       
   195 //
       
   196 CMMFBuffer* CMsrpPayloadFormatWrite::CreateSinkBufferL( TMediaId /*aMediaId*/,
       
   197                                                         TBool &aReference )
       
   198     { 
       
   199     	
       
   200    	DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::CreateSinkBufferL" );
       
   201 
       
   202 	/* TODO: Remove me when platform supports
       
   203     if ( KUidMediaTypeText != aMediaId.iMediaType ) 
       
   204     {
       
   205     User::Leave( KErrNotSupported ); 
       
   206     }
       
   207     */    
       
   208     aReference = ETrue;
       
   209     return CreateSinkBufferOfSizeL( KMaxRTTChunkSize + KRedHeaderSize );
       
   210     
       
   211     }
       
   212 
       
   213 // -----------------------------------------------------------------------------
       
   214 // CMsrpPayloadFormatWrite::CreateSinkBufferOfSizeL
       
   215 // Create a sink buffer of the given size.
       
   216 // -----------------------------------------------------------------------------
       
   217 //
       
   218 CMMFDataBuffer* CMsrpPayloadFormatWrite::CreateSinkBufferOfSizeL( TUint aSize )
       
   219     {
       
   220 	
       
   221 	DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::CreateSinkBufferOfSizeL" );
       
   222   
       
   223     if ( !iSourceBuffer )
       
   224 	    {
       
   225 	    iSourceBuffer = CMMFDataBuffer::NewL( aSize );
       
   226     	iSourceBuffer->Data().FillZ( aSize );
       
   227     	iSourceBuffer->SetRequestSizeL( aSize );
       
   228 	    }
       
   229 	    
       
   230     return iSourceBuffer;
       
   231     
       
   232     }
       
   233 
       
   234 // -----------------------------------------------------------------------------
       
   235 // CMsrpPayloadFormatWrite::EmptyBufferL
       
   236 // Empty the given source buffer
       
   237 // -----------------------------------------------------------------------------
       
   238 //
       
   239 void CMsrpPayloadFormatWrite::EmptyBufferL( CMMFBuffer* aBuffer, 
       
   240                                             MDataSource* aSupplier, 
       
   241                                             TMediaId /*aMediaId*/ )
       
   242     {
       
   243     
       
   244     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::EmptyBufferL");
       
   245   
       
   246     __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) );
       
   247     __ASSERT_ALWAYS ( aBuffer == iSourceBuffer, User::Leave( KErrArgument ) );
       
   248     __ASSERT_ALWAYS( aSupplier, User::Leave( KErrArgument ) );
       
   249     
       
   250    	// TODO: Remove me when platform supports
       
   251 	// __ASSERT_ALWAYS( KUidMediaTypeAudio == aMediaId.iMediaType,
       
   252 	// User::Leave( KErrNotSupported ) );
       
   253     
       
   254     // Cancel timer, so timer does not interrupt our current sending.
       
   255     // Timer enables empty blocks to be appended when redundancy is on.
       
   256     iTimer->Cancel();
       
   257        
       
   258     iDataPath = aSupplier;
       
   259     iSourceBuffer = static_cast<CMMFDataBuffer*>( aBuffer );
       
   260     
       
   261     if ( !iSinkBuffer )
       
   262         {        
       
   263         iStateMachine->ChangeState( ESourceBufferEmptied );
       
   264         return;
       
   265         }
       
   266         
       
   267 	if ( !iSinkBuffer->Data().Length() ) 
       
   268 	    {
       
   269 		//User::LeaveIfError( iRtpMediaClock->GetTimeStamp( iKey, iCurrentTimestamp ) );
       
   270    		iSinkBuffer->SetTimeToPlay( TInt64( iCurrentTimestamp ) );
       
   271    		iSinkBuffer->SetFrameNumber( aBuffer->FrameNumber() );	
       
   272 	    }
       
   273        
       
   274        
       
   275       // We signal StateMachine to ChangeState() 
       
   276       // this calls back EmptySourceBufferL 
       
   277       iStateMachine->ChangeState( EEmptySourceBuffer );
       
   278    
       
   279     } 
       
   280 
       
   281 
       
   282 // -----------------------------------------------------------------------------
       
   283 // CMsrpPayloadFormatWrite::SetSinkDataTypeCode
       
   284 // Set the sink data type to the given four CC code for the given media
       
   285 // -----------------------------------------------------------------------------
       
   286 //
       
   287 TInt CMsrpPayloadFormatWrite::SetSinkDataTypeCode( TFourCC aSinkFourCC,
       
   288                                                    TMediaId /*aMediaId*/ )
       
   289     {
       
   290     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SetSinkDataTypeCode");
       
   291 	/* TODO: Remove me when platform supports
       
   292     if ( KUidMediaTypeText != aMediaId.iMediaType )
       
   293     {
       
   294     User::Leave( KErrNotSupported );
       
   295     }
       
   296     */
       
   297     iFourCC = aSinkFourCC;
       
   298     return KErrNone;
       
   299     
       
   300     }
       
   301 
       
   302 
       
   303 // -----------------------------------------------------------------------------
       
   304 // CMsrpPayloadFormatWrite::SinkDataTypeCode
       
   305 // Return the sink data type (four CC code) for the given media ID
       
   306 // -----------------------------------------------------------------------------
       
   307 //
       
   308 TFourCC CMsrpPayloadFormatWrite::SinkDataTypeCode( TMediaId /*aMediaId*/ )
       
   309     {
       
   310     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkDataTypeCode");
       
   311   	/* TODO: Remove me when platform supports
       
   312     if ( KUidMediaTypeText == aMediaId.iMediaType )
       
   313         {
       
   314         return iFourCC;
       
   315         }
       
   316     else
       
   317         {
       
   318         return TFourCC(); //defaults to 'NULL' fourCC
       
   319         }
       
   320         */
       
   321 	return iFourCC;
       
   322         
       
   323     }
       
   324 
       
   325 // -----------------------------------------------------------------------------
       
   326 // CMsrpPayloadFormatWrite::BufferEmptiedL
       
   327 // Called after payload buffer is completely emptied by RtpDataSink.
       
   328 // -----------------------------------------------------------------------------
       
   329 //
       
   330 void CMsrpPayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ )
       
   331     {
       
   332     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::BufferEmptiedL" );
       
   333 	// nothing to be done
       
   334 	
       
   335 	//NOTE: 14.12.2007 - LeaveScan causes warning, but this is a interface method
       
   336     }
       
   337 
       
   338 
       
   339 // -----------------------------------------------------------------------------
       
   340 // CMsrpPayloadFormatWrite::FrameTimeInterval
       
   341 // Return the frame time interval for the given media
       
   342 // Return allways 0
       
   343 // -----------------------------------------------------------------------------
       
   344 //
       
   345 TTimeIntervalMicroSeconds 
       
   346     CMsrpPayloadFormatWrite::FrameTimeInterval( TMediaId /*aMediaId*/ ) const
       
   347     {
       
   348     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::FrameTimeInterval" );
       
   349     return TTimeIntervalMicroSeconds( TInt64( 0 ) );
       
   350     }
       
   351 
       
   352 // -----------------------------------------------------------------------------
       
   353 // CMsrpPayloadFormatWrite::Duration
       
   354 // Return the frame time interval for the given media
       
   355 // NOT SUPPORTED
       
   356 // -----------------------------------------------------------------------------
       
   357 //
       
   358 TTimeIntervalMicroSeconds 
       
   359     CMsrpPayloadFormatWrite::Duration( TMediaId /*aMediaType*/ ) const
       
   360     {
       
   361     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::Duration" );
       
   362     return TTimeIntervalMicroSeconds( TInt64( 0 ) );
       
   363     }
       
   364 
       
   365 
       
   366 // -----------------------------------------------------------------------------
       
   367 // CMsrpPayloadFormatWrite::EmptySourceBufferL
       
   368 // Empty the given sourcebuffer
       
   369 // Sourcebuffer is given in iSourceBuffer
       
   370 // Called by StateMachine
       
   371 // -----------------------------------------------------------------------------
       
   372 //
       
   373 void CMsrpPayloadFormatWrite::EmptySourceBufferL()
       
   374 	{
       
   375 				
       
   376 	  	DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::EmptySourceBufferL" );
       
   377 	 
       
   378 	  	const TDesC8& srcDes( iSourceBuffer->Data() );
       
   379     	const TUint8* srcPtr = srcDes.Ptr();
       
   380   		TInt length = iSourceBuffer->Data().Length();
       
   381   		
       
   382   		if ( iSourceBuffer->Data().Length() ) 
       
   383 	  		{
       
   384 	  		
       
   385 		  		if( KMaxRTTChunkSize < length )
       
   386 				  	{
       
   387 				  		DP_MSRP_WRITE( "ERR - RTT Payload Length exceeded MaxChunkSize" );
       
   388 				  		User::Leave(KErrArgument);
       
   389 				  	}
       
   390 			  	
       
   391 		  		TBuf16<KMaxRTTChunkSize> unicode;
       
   392 		    	User::LeaveIfError(
       
   393 		    			CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode, TPtrC8(srcPtr)));			
       
   394 					
       
   395 				//buffer the user data
       
   396 				TStringElement buffer;
       
   397 				buffer.iData = unicode;
       
   398 				iUserBuffer->AppendL(buffer);
       
   399 				
       
   400 				FormUserDataL();
       
   401 				ForwardDataL();
       
   402 					
       
   403 			}
       
   404 }   
       
   405 
       
   406 
       
   407 // -----------------------------------------------------------------------------
       
   408 // CMsrpPayloadFormatWrite::TimerExpiredL()
       
   409 // Sends Redundant data after buffer period, if no user data 
       
   410 // appeared before that.
       
   411 // -----------------------------------------------------------------------------
       
   412 //
       
   413 void CMsrpPayloadFormatWrite::TimerExpiredL()
       
   414 {		
       
   415 	DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::TimerExpiredL" );
       
   416 	
       
   417 	// Because timer expired, we must send redundant data anyway
       
   418 	TStringElement nullData;
       
   419 	iUserBuffer->AppendL(nullData);
       
   420 	
       
   421 	FormUserDataL();
       
   422 	//TODO:Handle other Errors if any
       
   423 	TInt err = SendRedundantDataL();
       
   424 	if ( err != KErrNone )
       
   425 		{
       
   426 			GotoIdleL(); 
       
   427 		}
       
   428 }
       
   429  
       
   430 
       
   431 // -----------------------------------------------------------------------------
       
   432 // CMsrpPayloadFormatWrite::ForwardDataL()
       
   433 // Sends Redundant data after buffer period, if no user data 
       
   434 // appeared before that.
       
   435 // -----------------------------------------------------------------------------
       
   436 //
       
   437 void CMsrpPayloadFormatWrite::ForwardDataL()
       
   438 {
       
   439     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::ForwardDataL" );
       
   440     
       
   441     // Just Send Data
       
   442     TInt err = SendRedundantDataL();
       
   443     
       
   444     if ( err == KErrNone )
       
   445         {
       
   446             iStateMachine->ChangeState( ESourceBufferEmptied ); 
       
   447         }
       
   448 } 
       
   449 
       
   450 
       
   451 
       
   452 // -----------------------------------------------------------------------------
       
   453 // CMsrpPayloadFormatWrite::SendRedundantDataL()
       
   454 // A Method that sends the redundant buffer to Sink
       
   455 // Calls CMsrpPayloadFormatWrite::DeliverPacketL
       
   456 // -----------------------------------------------------------------------------
       
   457 //
       
   458 TInt CMsrpPayloadFormatWrite::SendRedundantDataL()
       
   459 	{
       
   460     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SendRedundantDataL" );
       
   461     
       
   462 	TStringElement zero = iRedData->At(0);
       
   463 	TStringElement one = iRedData->At(1);
       
   464 	TStringElement two = iRedData->At(2);
       
   465  	
       
   466  	DP_MSRP_WRITE( "******************");
       
   467  	DP_MSRP_WRITE2( "SendRedundantDataL - Zero Lenght: %d", zero.iData.Length() ); 
       
   468  	DP_MSRP_WRITE2( "SendRedundantDataL - R1 Lenght: %d", one.iData.Length() );
       
   469  	DP_MSRP_WRITE2( "SendRedundantDataL - R2 lenght: %d", two.iData.Length() );
       
   470  	
       
   471 	if ( zero.iData.Length() == 0 && one.iData.Length() == 0 && two.iData.Length() == 0 )
       
   472 	 {
       
   473 	 	DP_MSRP_WRITE( "ERR - SendRedundantDataL - All Data is 0 lenght returning, KErrArgument!"); 
       
   474 	 	return KErrArgument;
       
   475 	 }
       
   476 		 
       
   477 	TDes8& destDes( iSinkBuffer->Data() );
       
   478 	
       
   479  	// Assemble redundant data
       
   480     AssembleRedPacket();
       
   481     // Append current data to buffer
       
   482     TPtr8 ptr = iBuf->Des();
       
   483     destDes.Append(  ptr );
       
   484     
       
   485     DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite HeapData size: %d", ptr.Size() );
       
   486     DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite HeapData Length: %d", ptr.Length() );
       
   487     DP_MSRP_WRITE ("CMsrpPayloadFormatWrite::DeliverPacketL, Packet Assembled" );
       
   488 	DP_MSRP_WRITE( "******************");
       
   489 	
       
   490     DeliverPacketL( *iSinkBuffer );	
       
   491 	return KErrNone;
       
   492 		
       
   493 	}
       
   494 
       
   495 
       
   496 // -----------------------------------------------------------------------------
       
   497 // CMsrpPayloadFormatWrite::FormUserDataL()
       
   498 //
       
   499 // A function that refreshes the RedundantData Buffer, so that
       
   500 // We just can send data that is there.
       
   501 // -----------------------------------------------------------------------------
       
   502 //
       
   503 TInt CMsrpPayloadFormatWrite::FormUserDataL()
       
   504 {
       
   505     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SendRedundantDataL" );
       
   506 	
       
   507     TStringElement primary;
       
   508 
       
   509     // if there is data
       
   510     if ( iUserBuffer->Count() )
       
   511         {
       
   512             primary = iUserBuffer->At(0);
       
   513         }
       
   514         
       
   515     //set timestamp to primary data, this is used to calculate offset
       
   516     primary.iTimestamp = iSinkBuffer->TimeToPlay().Int64();
       
   517     
       
   518     // can now reset user buffer
       
   519     iUserBuffer->Reset();
       
   520     
       
   521     // get current redundants
       
   522     TStringElement zero = iRedData->At(0);
       
   523     TStringElement one = iRedData->At(1); 
       
   524     
       
   525     // we can now reset old redundant also
       
   526     iRedData->Reset();
       
   527     
       
   528     // re-order redundant data, this must be always present, 
       
   529     // if redundancy changes on-fly from e.g 0 to 2
       
   530     iRedData->AppendL(primary);
       
   531     iRedData->AppendL(zero);
       
   532     iRedData->AppendL(one);
       
   533     
       
   534     return KErrNone;
       
   535 }
       
   536 
       
   537 
       
   538 // -----------------------------------------------------------------------------
       
   539 // CMsrpPayloadFormatWrite::GoToIdleL()
       
   540 //
       
   541 // When there is no data to send, we must go to idle mode
       
   542 // -----------------------------------------------------------------------------
       
   543 //
       
   544 void CMsrpPayloadFormatWrite::GotoIdleL()
       
   545 	{
       
   546 	
       
   547     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::GoToIdleL()");
       
   548     //reset redundancy buffer
       
   549     iRedData->Reset();
       
   550     //add default data  
       
   551     TStringElement empty;
       
   552     iRedData->AppendL(empty);
       
   553     iRedData->AppendL(empty);
       
   554     iRedData->AppendL(empty);
       
   555     iIdleMode = ETrue;
       
   556     
       
   557     //Set State that we are waiting for Data
       
   558     iStateMachine->ChangeState( EWaitForSourceData );
       
   559     
       
   560     // Cancel the Timer also
       
   561     iTimer->Cancel();
       
   562 		 	
       
   563 	}
       
   564  
       
   565 
       
   566 // -----------------------------------------------------------------------------
       
   567 // CMsrpPayloadFormatWrite::AssembleRedPacket()
       
   568 //
       
   569 // In AssembleRedPacket we must assemble right kind of
       
   570 // payload. We switch between redundant and plain data.
       
   571 // If redundancy is used a redundant datapacket is generated!
       
   572 // -----------------------------------------------------------------------------
       
   573 //
       
   574 void CMsrpPayloadFormatWrite::AssembleRedPacket()
       
   575 	{
       
   576     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::AssembleRedPacket" );
       
   577     switch( iCodecInfo.iRedundancyCount )
       
   578     {
       
   579         case 0:
       
   580             // just append the primary data and no headers
       
   581             iBuf->Des().Append( iRedData->At(0).iData );
       
   582         break;
       
   583         
       
   584         case 2:
       
   585              TInt err = GenerateRedPacket(); 
       
   586              //TODO: Handle Errors in Creating packet
       
   587         break;
       
   588         
       
   589     }
       
   590 
       
   591 	}
       
   592 
       
   593 	
       
   594 // -----------------------------------------------------------------------------
       
   595 // CMsrpPayloadFormatWrite::GenerateRedPacket() 
       
   596 //
       
   597 // In GenerateRedPacket we must assemble right kind of
       
   598 // payload according to RFC 4103. Level 2 redundancy is used.
       
   599 // -----------------------------------------------------------------------------
       
   600 //
       
   601 TInt CMsrpPayloadFormatWrite::GenerateRedPacket() 
       
   602 {
       
   603 		
       
   604 		DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::GenerateRedPacket()" );
       
   605 		
       
   606 		TStringElement primary = iRedData->At(0);
       
   607 		TStringElement r1 = iRedData->At(1);
       
   608 		TStringElement r2 = iRedData->At(2);
       
   609 
       
   610 		DP_MSRP_WRITE( "*******************************");
       
   611 		DP_MSRP_WRITE2("CMsrpPayloadFormatWrite::GenerateRedPacket PR Length: %d", primary.iData.Length() );
       
   612 		DP_MSRP_WRITE2("CMsrpPayloadFormatWrite::GenerateRedPacket R1 Length: %d", r1.iData.Length() );
       
   613 		DP_MSRP_WRITE2("CMsrpPayloadFormatWrite::GenerateRedPacket R2 Length: %d", r2.iData.Length() );
       
   614 
       
   615 		// pointer to data
       
   616 		TUint8* dataP = iData;
       
   617 		TInt count(0);
       
   618 		//Fill Data with binary zeroes and zero old
       
   619 		Mem::FillZ( dataP, KRedHeaderSize + KDataSize ); 
       
   620 		iBuf->Des().Zero();
       
   621     
       
   622     	
       
   623 		/*************
       
   624 		data[0] = 8 bit
       
   625 		1 bit - redundancy marker bit 1
       
   626 		7 bit - payloadtype
       
   627 		***************/
       
   628 		
       
   629 		iData[0] |= ( 1 << 7 );
       
   630 		iData[0] |= iCodecInfo.iRedundantPayload; 
       
   631 		//iData[0] |= 106; 
       
   632 		dataP += 1;
       
   633 		count ++;
       
   634 			
       
   635 			
       
   636 		/**************
       
   637 		data[1-3] = 24 bit
       
   638 		14 bit - timestamp offset of R2
       
   639 		10 bit - length of  R2
       
   640 		***************/
       
   641 		
       
   642 		TUint32 temp(0);
       
   643 		temp |= ( SetTimeOffset(primary.iTimestamp, r2.iTimestamp ) << 10  ); 
       
   644 		
       
   645 		TUint16 size(r2.iData.Length()); 
       
   646 		temp |= size; 
       
   647 			
       
   648 		Write24(dataP, temp); 
       
   649 		dataP += 3;
       
   650 		count += 3; 
       
   651 		
       
   652 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[0]: %x", iData[0] );
       
   653 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[1]: %x", iData[1] );
       
   654 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[2]: %x", iData[2] );
       
   655 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[3]: %x", iData[3] );
       
   656 		
       
   657 			
       
   658 		/**************
       
   659 		data[4] = 8 bit
       
   660 		1 bit - redundancy marker bit 1
       
   661 		7 bit - payloadtype
       
   662 		***************/
       
   663 		
       
   664 		iData[4] |= ( 1 << 7 );
       
   665 		iData[4] |= iCodecInfo.iRedundantPayload;
       
   666 		//iData[4] |= 106;
       
   667 		dataP += 1; 
       
   668 		count ++;
       
   669 	
       
   670 		/**************
       
   671 		data[5-7] = 24 bit
       
   672 		14 bit - timestamp offset of R1
       
   673 		10 bit - length of  R1
       
   674 		***************/			
       
   675 		
       
   676 		temp = 0;
       
   677 		temp |= ( SetTimeOffset(primary.iTimestamp, r1.iTimestamp ) << 10  );
       
   678 	
       
   679 		size = r1.iData.Length();  
       
   680 		temp |= size; 
       
   681 			
       
   682 		Write24(dataP, temp);
       
   683 		dataP += 3;
       
   684 		count += 3;
       
   685 				
       
   686 		/**************
       
   687 		data[8] = 8 bit
       
   688 		1 bit - normal marker bit 0
       
   689 		7 bit - payloadtype 
       
   690 		***************/
       
   691 		iData[8] |= ( 0 << 7 );
       
   692 		iData[8] |= iCodecInfo.iPayloadType;
       
   693 		//iData[8] |= 105;
       
   694 		dataP += 1;
       
   695 		count ++;
       
   696 	
       
   697 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[4]: %x", iData[4] );
       
   698 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[5]: %x", iData[5] );
       
   699 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[6]: %x", iData[6] );
       
   700 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[7]: %x", iData[7] );
       
   701 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket DATA[8]: %x", iData[8] );
       
   702 		DP_MSRP_WRITE( "*******************************");
       
   703 		
       
   704 		//TODO: When IOP-Tests Are done, Write me properly using Append, or some other method
       
   705 		TInt forHere = count+r2.iData.Length();
       
   706 		TInt index(0);
       
   707 		if ( r2.iData.Length() )
       
   708 		{
       
   709 			for ( TInt i = count; i < forHere; i++ )
       
   710 			  	{
       
   711 				iData[i] = r2.iData[index];
       
   712 				index++,
       
   713 				RDebug::Print( _L("	X Writing R2 DATA[i]: %x"), iData[i] );
       
   714 				}
       
   715 			
       
   716 		dataP += r2.iData.Length();
       
   717 		count += r2.iData.Length();		
       
   718 		}
       
   719 			
       
   720 			
       
   721 		forHere = count+r1.iData.Length();
       
   722 		index = 0;
       
   723 		if ( r1.iData.Length() )
       
   724 		{
       
   725 			for ( TInt i = count; i < forHere; i++ )
       
   726 			  	{
       
   727 				iData[i] = r1.iData[index];
       
   728 				index++;
       
   729 				RDebug::Print( _L("	X Writing R1 DATA[i]: %x"), iData[i] );
       
   730 				}
       
   731 			
       
   732 		dataP += r1.iData.Length();		
       
   733 		count += r1.iData.Length();
       
   734 		}
       
   735  
       
   736 		
       
   737 		forHere = count+primary.iData.Length();
       
   738 		index = 0;
       
   739 		if ( primary.iData.Length() )
       
   740 		{
       
   741 			for ( TInt i = count; i < forHere; i++ )
       
   742 			  	{
       
   743 				iData[i] = primary.iData[index];
       
   744 				index++;
       
   745 				RDebug::Print( _L("	X Writing PRIMARY DATA[i]: %x"), iData[i] );
       
   746 				}
       
   747 			
       
   748 		dataP += primary.iData.Length();		
       
   749 		count += primary.iData.Length();
       
   750 		}
       
   751 				
       
   752 				
       
   753 		DP_MSRP_WRITE2( "CMsrpPayloadFormatWrite::GenerateRedPacket Writing Lenght: %d", count );
       
   754 		iBuf->Des().Append( iData, count );
       
   755 		return KErrNone;
       
   756 		
       
   757 }
       
   758 
       
   759 
       
   760 // -----------------------------------------------------------------------------
       
   761 // CMsrpPayloadFormatWrite::DeliverPacketL
       
   762 // Prepare the packet header and deliver the packet to the datasink.
       
   763 // -----------------------------------------------------------------------------
       
   764 void CMsrpPayloadFormatWrite::DeliverPacketL( CMMFDataBuffer& aPayload )
       
   765     {
       
   766     
       
   767     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::DeliverPacketL"); 
       
   768    
       
   769     if ( !iClip )
       
   770         {
       
   771         User::Leave( KErrNotReady ); 
       
   772         }
       
   773     const TMediaId mediaId( KUidMediaTypeAudio );
       
   774     const TInt dataSize( aPayload.Data().Size() );
       
   775     DP_MSRP_WRITE2( "MSRP Payload SIZE : %d", dataSize );
       
   776     
       
   777     if ( dataSize )
       
   778         {           
       
   779         if (iIsMsrpSink)
       
   780             {
       
   781             iMsrpDataSink->EmptyBufferL( &aPayload, this, mediaId );
       
   782             }
       
   783         }       
       
   784     aPayload.Data().Zero();
       
   785     }
       
   786 
       
   787 
       
   788 // -----------------------------------------------------------------------------
       
   789 // CMsrpPayloadFormatWrite::SourceBufferEmptiedL
       
   790 // Handle the event that sourcebuffer has been emptied.
       
   791 // Sourcebuffer is given in "iSourceBuffer".
       
   792 // Called by the statemachine.
       
   793 // -----------------------------------------------------------------------------
       
   794 void CMsrpPayloadFormatWrite::SourceBufferEmptiedL()
       
   795     { 
       
   796     
       
   797     
       
   798     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SourceBufferEmptiedL" ); 
       
   799     
       
   800     //Empty all
       
   801     iSourceBuffer->Data().FillZ();  
       
   802 	iSourceBuffer->Data().Zero();
       
   803 	iSinkBuffer->Data().FillZ();  
       
   804 	iSinkBuffer->Data().Zero();
       
   805     iBuf->Des().FillZ();
       
   806     iBuf->Des().Zero();
       
   807     iDataPath->BufferEmptiedL( iSourceBuffer );
       
   808 
       
   809 	//Finally we set the timer if we are in red mode 	
       
   810 	switch( iCodecInfo.iRedundancyCount )
       
   811 	{
       
   812 		case 0:
       
   813 				// do nothing 
       
   814 		break;
       
   815 		
       
   816 		case 2:
       
   817 			if ( iIdleMode )
       
   818 				{
       
   819 				iTimer->Cancel();
       
   820 				iTimer->Start();	
       
   821 				}
       
   822 		break;
       
   823 	}
       
   824 	
       
   825 	// we are no more in idle,
       
   826 	iIdleMode = EFalse;
       
   827 	
       
   828 }
       
   829 
       
   830 
       
   831 // -----------------------------------------------------------------------------
       
   832 // CMsrpPayloadFormatWrite::SinkPrimeL
       
   833 // Prime the sink
       
   834 // -----------------------------------------------------------------------------
       
   835 //
       
   836 void CMsrpPayloadFormatWrite::SinkPrimeL()
       
   837     {
       
   838 	DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPrimeL()");
       
   839 	iClip->SinkPrimeL();
       
   840     }
       
   841 
       
   842 
       
   843 // -----------------------------------------------------------------------------
       
   844 // CMsrpPayloadFormatWrite::SinkPrimeL
       
   845 // Prime the sink
       
   846 // -----------------------------------------------------------------------------
       
   847 //
       
   848 void CMsrpPayloadFormatWrite::CancelUlRequest() 
       
   849     {
       
   850     
       
   851 	DP_MSRP_WRITE("CMsrpPayloadFormatWrite::CancelUlRequest()" );
       
   852     iStateMachine->Cancel();
       
   853     iStateMachine->ChangeState( EEncodeIdle );
       
   854 
       
   855     // Reset the payload buffer
       
   856     if ( iSinkBuffer )
       
   857         {
       
   858         TDes8& dataDes = static_cast<CMMFDataBuffer*>( iSinkBuffer )->Data();
       
   859         dataDes.SetLength( 0 );
       
   860         }
       
   861         
       
   862     }
       
   863     
       
   864     
       
   865 // -----------------------------------------------------------------------------
       
   866 // CMsrpPayloadFormatWrite::SinkPlayL
       
   867 // Start playing.
       
   868 // -----------------------------------------------------------------------------
       
   869 //
       
   870 void CMsrpPayloadFormatWrite::SinkPlayL()
       
   871     {
       
   872     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPlayL" );
       
   873     // Allocate buffer for data transfer between 
       
   874     // FormatWrite - MDataSink
       
   875     delete iSinkBuffer;
       
   876     iSinkBuffer = NULL;
       
   877     iSinkBuffer = CMMFDataBuffer::NewL( KRedHeaderSize + KDataSize );
       
   878     
       
   879     // Start state machine
       
   880     iStateMachine->ChangeState( EWaitForSourceData );
       
   881     
       
   882     iFirstPacketFinished = EFalse;
       
   883 
       
   884     // Start a new cycle of frame collecting
       
   885     if ( iSinkBuffer )
       
   886         {
       
   887         iSinkBuffer->SetLastBuffer( EFalse );
       
   888         }
       
   889 
       
   890     iClip->SinkPlayL();
       
   891     }
       
   892 
       
   893 
       
   894 // -----------------------------------------------------------------------------
       
   895 // CMsrpPayloadFormatWrite::SinkPauseL
       
   896 // Pause sink
       
   897 // -----------------------------------------------------------------------------
       
   898 //
       
   899 void CMsrpPayloadFormatWrite::SinkPauseL()
       
   900     {
       
   901     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPauseL" );
       
   902 	this->CancelUlRequest();
       
   903     iClip->SinkPauseL();
       
   904     
       
   905     }
       
   906 
       
   907 // -----------------------------------------------------------------------------
       
   908 // CMsrpPayloadFormatWrite::SinkStopL
       
   909 // Stop sink
       
   910 // -----------------------------------------------------------------------------
       
   911 //
       
   912 void CMsrpPayloadFormatWrite::SinkStopL()
       
   913     {
       
   914     DP_MSRP_WRITE("CMsrpPayloadFormatWrite::SinkPauseL" ); 
       
   915     // Stop state machine
       
   916    	this->CancelUlRequest();
       
   917     iClip->SinkStopL(); 
       
   918     }
       
   919 
       
   920 
       
   921 // ---------------------------------------------------------------------------
       
   922 // CMsrpPayloadFormatWrite::ConfigurePayloadFormatL
       
   923 // Configure payload encoding parameters
       
   924 // ---------------------------------------------------------------------------
       
   925 //
       
   926 void CMsrpPayloadFormatWrite::ConfigurePayloadFormatL( const TDesC8& aConfigParams, 
       
   927     CMccRtpMediaClock& /*aClock*/  )
       
   928     {
       
   929     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::ConfigurePayloadFormatL()" );
       
   930    	
       
   931    //Check that buffer is same size, so we can assume data is correct type
       
   932     __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
       
   933         User::Leave( KErrArgument ) );
       
   934      
       
   935     //instantiate correct CodecInfo Structure
       
   936     TMccCodecInfoBuffer infoBuffer;
       
   937     infoBuffer.Copy( aConfigParams );
       
   938     TMccCodecInfo codecInfo( infoBuffer() ); 
       
   939     
       
   940 	if ( !codecInfo.iIsUpdate )
       
   941 		{
       
   942 
       
   943 		//iCodecInfo = codecInfo;
       
   944 		//iRtpMediaClock = &aClock;  
       
   945 		//iKey = iRtpMediaClock->RegisterMediaFormat( KDefaultSampleRate, iCodecInfo.iHwFrameTime );
       
   946 		}
       
   947 	else
       
   948 		{
       
   949 		UpdateConfigurationL( aConfigParams );
       
   950 		} 
       
   951 
       
   952     }
       
   953 
       
   954 // -----------------------------------------------------------------------------
       
   955 // CMsrpPayloadFormatWrite::UpdateConfigurationL
       
   956 // Update payload encoding parameters
       
   957 // -----------------------------------------------------------------------------
       
   958 //
       
   959 void CMsrpPayloadFormatWrite::UpdateConfigurationL( const TDesC8& aConfigParams )
       
   960     { 
       
   961     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::UpdateConfigurationL" );
       
   962     __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
       
   963         User::Leave( KErrArgument ) );
       
   964     
       
   965     TMccCodecInfoBuffer infoBuffer;
       
   966     infoBuffer.Copy( aConfigParams );
       
   967     TMccCodecInfo codecInfo = infoBuffer();
       
   968     
       
   969     iCodecInfo = codecInfo;
       
   970     //iCodecInfo.iPtime = codecInfo.iPtime;
       
   971     //iCodecInfo.iRedundancyCount = 0;
       
   972     
       
   973     //iCodecInfo.iPayloadType = codecInfo.iPayloadType;
       
   974     //iCodecInfo.iRedundancyCount = codecInfo.iRedundancyCount;
       
   975     //iCodecInfo.iCodecMode = codecInfo.iCodecMode;
       
   976     
       
   977     //TODO: move me to right variable and update buffering time
       
   978     //iTimer->Cancel();
       
   979     //iTimer->SetTimeOut( iCodecInfo.iCodecMode * 1000);
       
   980     
       
   981     // Allocate buffer for data transfer between 
       
   982     // FormatWrite - MDataSink
       
   983     delete iSinkBuffer;
       
   984     iSinkBuffer = NULL;
       
   985     iSinkBuffer = CMMFDataBuffer::NewL( KRedHeaderSize + KDataSize );
       
   986     
       
   987     }
       
   988 
       
   989 
       
   990 
       
   991 // ==========================    HELPER FUNCTIONS    =========================
       
   992 // ========================== 						 =========================
       
   993 // ========================== 						 =========================
       
   994 
       
   995 // -----------------------------------------------------------------------------
       
   996 // CMsrpPayloadFormatWrite::Write24
       
   997 // Simple helper function, that writes a 24-bit value to databuffer, 
       
   998 // using pointer
       
   999 // -----------------------------------------------------------------------------
       
  1000 //
       
  1001 void CMsrpPayloadFormatWrite::Write24( TUint8* const aPointer, TUint32 aValue )
       
  1002     {
       
  1003     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::Write24" );
       
  1004     aPointer[0] = static_cast<TUint8>( ( aValue & 0xFF0000 ) >> 16 );
       
  1005     aPointer[1] = static_cast<TUint8>( ( aValue & 0x00FF00 ) >> 8 );
       
  1006     aPointer[2] = static_cast<TUint8>( aValue & 0x0000FF );
       
  1007     }
       
  1008     
       
  1009 
       
  1010 // -----------------------------------------------------------------------------
       
  1011 // CMsrpPayloadFormatWrite::Write32
       
  1012 // Simple helper function, that writes a 32-bit value to databuffer, 
       
  1013 // using pointer
       
  1014 // -----------------------------------------------------------------------------
       
  1015 //    
       
  1016 void CMsrpPayloadFormatWrite::Write32( TUint8* const aPointer, TUint32 aValue )
       
  1017 	{
       
  1018     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::Write32" );
       
  1019 	aPointer[0] = static_cast<TUint8>( ( aValue & 0xFF000000 ) >> 24 );
       
  1020 	aPointer[1] = static_cast<TUint8>( ( aValue & 0x00FF0000 ) >> 16 );
       
  1021 	aPointer[2] = static_cast<TUint8>( ( aValue & 0x0000FF00 ) >> 8 );
       
  1022 	aPointer[3] = static_cast<TUint8>( aValue & 0x000000FF );
       
  1023 	}
       
  1024 
       
  1025 
       
  1026 // -----------------------------------------------------------------------------
       
  1027 // CMsrpPayloadFormatWrite::SetTimeOffset
       
  1028 // Calculates TimeOffset to RedundancyHeader according to 
       
  1029 // RFC 4103. Actually RFC 4103 does not accurately state how ( and where )
       
  1030 // timeoffset should be calculated. This calculation is based conversations
       
  1031 // with authors of RFC 4103
       
  1032 // -----------------------------------------------------------------------------
       
  1033 //
       
  1034 TUint16 CMsrpPayloadFormatWrite::SetTimeOffset( TInt64& aPrim, TInt64& aSecond  )
       
  1035 {	
       
  1036     DP_MSRP_WRITE( "CMsrpPayloadFormatWrite::SetTimeOffset" );
       
  1037 	TInt pOffset = aPrim - aSecond; 
       
  1038 	TUint16 aRet = TUint16(pOffset) & KHighestTimeStampOffset;
       
  1039 	if( aRet > KHighestTimeStampOffset )
       
  1040 	{
       
  1041 		aRet = KHighestTimeStampOffset;
       
  1042 	}
       
  1043 	return aRet; 
       
  1044 }
       
  1045 
       
  1046 
       
  1047 TStringElement::TStringElement()
       
  1048 {
       
  1049 }
       
  1050 
       
  1051 
       
  1052 //  End of File