multimediacommscontroller/mmccsubcontroller/src/mccrtpkeepalive.cpp
changeset 0 1bce908db942
child 32 f2ed1fc4c163
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2007-2008 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:    RTP Keepalive mechanism
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include <e32math.h>
       
    23 #include "mccrtpkeepalive.h"
       
    24 #include "mccdef.h"
       
    25 #include "mccinternaldef.h"
       
    26 #include "mccsubcontrollerlogs.h"
       
    27 #include "mccinternalevents.h"
       
    28 #include "mccrtpinterface.h"
       
    29 #include "mccrtpmediaclock.h"
       
    30 
       
    31 
       
    32 // EXTERNAL DATA STRUCTURES
       
    33 
       
    34 // EXTERNAL FUNCTION PROTOTYPES  
       
    35 
       
    36 // CONSTANTS
       
    37 
       
    38 // MACROS
       
    39 
       
    40 // LOCAL CONSTANTS AND MACROS
       
    41 
       
    42 // MODULE DATA STRUCTURES
       
    43 
       
    44 // LOCAL FUNCTION PROTOTYPES
       
    45 
       
    46 // FORWARD DECLARATIONS
       
    47 
       
    48 
       
    49 // ============================= LOCAL FUNCTIONS =============================
       
    50 
       
    51 
       
    52 // ============================ MEMBER FUNCTIONS =============================
       
    53 
       
    54 
       
    55 // ---------------------------------------------------------------------------
       
    56 // CMccRtpKeepalive::NewL
       
    57 // Two-phased constructor.
       
    58 // ---------------------------------------------------------------------------
       
    59 //
       
    60 CMccRtpKeepalive* CMccRtpKeepalive::NewL( 
       
    61     MAsyncEventHandler& aEventHandler, 
       
    62     CRtpAPI& aRtpAPI,
       
    63     TRtpId aRtpSessionId,
       
    64     TUint8 aKeepalivePayloadType,
       
    65     TUint8 aKeepaliveInterval,
       
    66     const TDesC8& aKeepaliveData,
       
    67     TBool aRemoteAddressSet )
       
    68     {
       
    69     CMccRtpKeepalive* self = 
       
    70         new( ELeave ) CMccRtpKeepalive( aEventHandler, aRtpAPI, 
       
    71                                         aRtpSessionId, aRemoteAddressSet );
       
    72     CleanupStack::PushL( self );
       
    73     self->ConstructL( aKeepalivePayloadType, aKeepaliveInterval, 
       
    74                       aKeepaliveData );
       
    75     CleanupStack::Pop( self );
       
    76     return self;
       
    77     }
       
    78 
       
    79 // ---------------------------------------------------------------------------
       
    80 // CMccRtpKeepalive::~CMccRtpKeepalive
       
    81 // Destructor
       
    82 // ---------------------------------------------------------------------------
       
    83 //
       
    84 CMccRtpKeepalive::~CMccRtpKeepalive()
       
    85     {
       
    86     __SUBCONTROLLER( "CMccRtpKeepalive::~CMccRtpKeepalive()" )
       
    87     
       
    88     Cancel();
       
    89     
       
    90     if ( KNullId != iRtpStreamId && !iRtpSinkExists )
       
    91         {
       
    92         iRtpAPI.CloseStream( iRtpStreamId );
       
    93         }
       
    94     
       
    95     iTimer.Close();
       
    96     
       
    97     delete iKeepaliveData;
       
    98     
       
    99     iUsers.Reset();
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // CMccRtpKeepalive::StartKeepaliveL
       
   104 // ---------------------------------------------------------------------------
       
   105 //
       
   106 void CMccRtpKeepalive::StartKeepaliveL( MMccRtpInterface& aUser,
       
   107                                         CMccRtpMediaClock& aRtpMediaClock )
       
   108     {
       
   109     __SUBCONTROLLER( "CMccRtpKeepalive::StartKeepaliveL()" )
       
   110     
       
   111     iRtpMediaClock = &aRtpMediaClock;
       
   112 
       
   113     if ( KErrNotFound == iUsers.Find( &aUser ) )
       
   114         {
       
   115         iUsers.AppendL( &aUser );
       
   116         }   
       
   117                    
       
   118     User::LeaveIfError( ToggleKeepaliveSending( ResolveActivity() ) ); 
       
   119     
       
   120     __SUBCONTROLLER( "CMccRtpKeepalive::StartKeepaliveL(), exit" )
       
   121     }
       
   122 
       
   123 // ---------------------------------------------------------------------------
       
   124 // CMccRtpKeepalive::StopKeepalive
       
   125 // ---------------------------------------------------------------------------
       
   126 //       
       
   127 TInt CMccRtpKeepalive::StopKeepalive( MMccRtpInterface& aUser, 
       
   128                                       TInt& aRefCount )
       
   129     {
       
   130     __SUBCONTROLLER( "CMccRtpKeepalive::StopKeepalive()" )
       
   131     
       
   132     TInt err( KErrNotFound );
       
   133     TInt index = iUsers.Find( &aUser );
       
   134     if ( KErrNotFound != index)
       
   135         {
       
   136         iUsers.Remove( index );
       
   137 
       
   138         err = ToggleKeepaliveSending( ResolveActivity() );
       
   139         if ( err )
       
   140             {
       
   141             SendErrorToClient( err );
       
   142             }
       
   143         }
       
   144         
       
   145     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::StopKeepalive(), exit with err:", err )
       
   146     
       
   147     aRefCount = iUsers.Count();
       
   148     
       
   149     return err;
       
   150     }
       
   151     
       
   152 // ---------------------------------------------------------------------------
       
   153 // CMccRtpKeepalive::ResetKeepaliveTimer
       
   154 // ---------------------------------------------------------------------------
       
   155 //       
       
   156 void CMccRtpKeepalive::ResetKeepaliveTimer( )
       
   157     {
       
   158     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::ResetKeepaliveTimer() active:", 
       
   159         IsActive() )
       
   160         
       
   161     Cancel();
       
   162     StartSending();
       
   163     }    
       
   164 
       
   165 // ---------------------------------------------------------------------------
       
   166 // CMccRtpKeepalive::StreamId
       
   167 // ---------------------------------------------------------------------------
       
   168 //    
       
   169 TRtpId CMccRtpKeepalive::StreamId() const
       
   170     {
       
   171     return iRtpStreamId;
       
   172     }
       
   173 
       
   174 // -----------------------------------------------------------------------------
       
   175 // CMccRtpKeepalive::PayloadType
       
   176 // -----------------------------------------------------------------------------
       
   177 //    
       
   178 TUint8 CMccRtpKeepalive::PayloadType() const
       
   179     {
       
   180     return iRtpHeaderInfo.iPayloadType;
       
   181     }
       
   182 
       
   183 // ---------------------------------------------------------------------------
       
   184 // CMccRtpKeepalive::RemoteAddressSet
       
   185 // ---------------------------------------------------------------------------
       
   186 //    
       
   187 TInt CMccRtpKeepalive::RemoteAddressSet()
       
   188     {
       
   189     __SUBCONTROLLER( "CMccRtpKeepalive::RemoteAddressSet()" )
       
   190     
       
   191     TInt err( KErrNone );
       
   192     iRemoteAddressSet = ETrue;
       
   193     if ( iCurrentState == ESendingPending )
       
   194         {
       
   195         err = StartSending();
       
   196         }
       
   197         
       
   198     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::RemoteAddressSet(), exit with err:", 
       
   199         err )
       
   200     return err;
       
   201     }
       
   202     
       
   203 // ---------------------------------------------------------------------------
       
   204 // CMccRtpKeepalive::IsForSink
       
   205 // ---------------------------------------------------------------------------
       
   206 //   
       
   207 TBool CMccRtpKeepalive::IsForSink()
       
   208     {
       
   209     TBool sinkFound = EFalse;
       
   210     TInt count = iUsers.Count();
       
   211     for ( TInt i = 0; i < count && !sinkFound; i++ )
       
   212         {
       
   213         sinkFound = iUsers[i]->IsSink();
       
   214         }
       
   215     return sinkFound;    
       
   216     }    
       
   217 
       
   218 // ---------------------------------------------------------------------------
       
   219 // CMccRtpKeepalive::UpdateParamsL
       
   220 // ---------------------------------------------------------------------------
       
   221 //   
       
   222 void CMccRtpKeepalive::UpdateParamsL( TUint8 aKeepalivePT, 
       
   223     TUint8 aKeepaliveInterval, const TDesC8& aKeepaliveData )
       
   224     {
       
   225     __SUBCONTROLLER_INT1( 
       
   226         "CMccRtpKeepalive::UpdateParamsL(), PT:", aKeepalivePT )
       
   227     __SUBCONTROLLER_INT1( 
       
   228         "CMccRtpKeepalive::UpdateParamsL(), INT:", aKeepaliveInterval )
       
   229 
       
   230     __ASSERT_ALWAYS( aKeepalivePT < KMccPayloadTypeMax, 
       
   231         User::Leave( KErrArgument ) );
       
   232     
       
   233     iRtpHeaderInfo.iPayloadType = aKeepalivePT;
       
   234     
       
   235     HBufC8* tmp = aKeepaliveData.AllocL();
       
   236     delete iKeepaliveData;
       
   237     iKeepaliveData = tmp;    
       
   238     
       
   239     const TUint KMccSecsToMicroSecs = 1000000;
       
   240     iKeepaliveInterval = aKeepaliveInterval * KMccSecsToMicroSecs;
       
   241     }
       
   242 
       
   243 // ---------------------------------------------------------------------------
       
   244 // CMccRtpKeepalive::RunL
       
   245 // ---------------------------------------------------------------------------
       
   246 //
       
   247 void CMccRtpKeepalive::RunL()
       
   248     {
       
   249     TInt status = iStatus.Int();
       
   250     
       
   251     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::RunL(), status:", status )
       
   252     
       
   253     User::LeaveIfError( status );
       
   254     
       
   255     switch ( iCurrentState )
       
   256         {
       
   257         case EWaitingTimer:
       
   258             {
       
   259             // Timer completed, send again
       
   260             User::LeaveIfError( Send() );
       
   261             break;
       
   262             }
       
   263         case ESending:
       
   264             {
       
   265             // Send completed, start timer again
       
   266             iSequenceNum++;
       
   267             User::LeaveIfError( StartSending() );
       
   268             break;
       
   269             }
       
   270         default:
       
   271             {
       
   272             User::Leave( KErrArgument );
       
   273             break;
       
   274             }
       
   275         }
       
   276     }
       
   277 
       
   278 // ---------------------------------------------------------------------------
       
   279 // CMccRtpKeepalive::DoCancel
       
   280 // ---------------------------------------------------------------------------
       
   281 //        
       
   282 void CMccRtpKeepalive::DoCancel()
       
   283     {
       
   284     if ( EWaitingTimer == iCurrentState )
       
   285         {
       
   286         __SUBCONTROLLER( "Keepalive: Cancel Timer !!!" )
       
   287         iTimer.Cancel();
       
   288         }
       
   289     else if ( ESending == iCurrentState )
       
   290         {
       
   291         __SUBCONTROLLER( "Keepalive: Cancel Sending !!!" )
       
   292         iRtpAPI.CancelSend( iRtpSessionId );
       
   293         }
       
   294     
       
   295     iCurrentState = EIdle;
       
   296     }
       
   297 
       
   298 // ---------------------------------------------------------------------------
       
   299 // CMccRtpKeepalive::RunError
       
   300 // ---------------------------------------------------------------------------
       
   301 //        
       
   302 TInt CMccRtpKeepalive::RunError( TInt aError )
       
   303     {
       
   304     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::RunError(), err:", aError )
       
   305     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::RunError(), at state:", iCurrentState )
       
   306     
       
   307     SendErrorToClient( aError );
       
   308     
       
   309     if ( aError != KErrNoMemory )
       
   310         {
       
   311         return KErrNone;
       
   312         }
       
   313     return aError;
       
   314     }
       
   315 
       
   316 // ---------------------------------------------------------------------------
       
   317 // CMccRtpKeepalive::ResolveActivity
       
   318 // ---------------------------------------------------------------------------
       
   319 //
       
   320 TBool CMccRtpKeepalive::ResolveActivity()
       
   321     {
       
   322     __SUBCONTROLLER( "CMccRtpKeepalive::ResolveActivity()" )
       
   323     
       
   324     // Keepalive is always active if there's only rtpsource.
       
   325     iRtpSinkExists = EFalse;
       
   326     TBool rtpSourceExists( EFalse );
       
   327     for ( TInt i = 0; i < iUsers.Count(); i++ )
       
   328         {
       
   329         if ( iUsers[ i ]->IsSink() )
       
   330             {
       
   331             iRtpSinkExists = ETrue;
       
   332             iRtpSinkIndex = i;
       
   333             }
       
   334         else
       
   335             {
       
   336             rtpSourceExists = ETrue;
       
   337             }
       
   338         }
       
   339     
       
   340     TBool keepAliveActive = ( iRtpSinkExists ) || 
       
   341                             ( !iRtpSinkExists && rtpSourceExists );
       
   342     
       
   343     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::ResolveActivity(), active:", 
       
   344         keepAliveActive )
       
   345        
       
   346     return keepAliveActive;
       
   347     }
       
   348 
       
   349 // ---------------------------------------------------------------------------
       
   350 // CMccRtpKeepalive::ToggleKeepaliveSending
       
   351 // ---------------------------------------------------------------------------
       
   352 //   
       
   353 TInt CMccRtpKeepalive::ToggleKeepaliveSending( TBool aIsActive )
       
   354     {
       
   355     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::ToggleKeepaliveSending(), active", 
       
   356         aIsActive )
       
   357     
       
   358     TInt err( KErrNone );
       
   359     if ( aIsActive )
       
   360         {
       
   361         if ( iRtpStreamId == KNullId )
       
   362             {
       
   363             __SUBCONTROLLER( "CMccRtpKeepalive::ToggleKeepaliveSending(), create rtp transmit stream" )
       
   364             
       
   365             TTranStreamParams transParams;
       
   366             transParams.iPayloadType = iRtpHeaderInfo.iPayloadType;
       
   367 
       
   368             if ( !iRtpSinkExists )
       
   369                 {
       
   370                 TRAP( err, iRtpStreamId = 
       
   371                     iRtpAPI.CreateTransmitStreamL( iRtpSessionId, 
       
   372                                                    transParams, 
       
   373                                                    iSSRC ) ); 
       
   374                 }
       
   375             else
       
   376                 {
       
   377                 // get rtp sink id
       
   378                 iRtpStreamId = iUsers[iRtpSinkIndex]->RtpStreamId();
       
   379                 }    
       
   380                                
       
   381             if ( iRtpStreamId == KNullId )
       
   382                 {
       
   383                 err = KErrCouldNotConnect;
       
   384                 }
       
   385             }
       
   386         
       
   387         if ( !err && iCurrentState == EIdle )
       
   388             {
       
   389             err = StartSending();
       
   390             }
       
   391         }
       
   392     else
       
   393         {
       
   394         Cancel();
       
   395         }
       
   396         
       
   397     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::ToggleKeepaliveSending(), exit with err:", 
       
   398         err )
       
   399     
       
   400     return err;
       
   401     }
       
   402 
       
   403 // ---------------------------------------------------------------------------
       
   404 // CMccRtpKeepalive::StartSending
       
   405 // ---------------------------------------------------------------------------
       
   406 //   
       
   407 TInt CMccRtpKeepalive::StartSending()
       
   408     {
       
   409     __SUBCONTROLLER( "CMccRtpKeepalive::StartSending()" )
       
   410     
       
   411     TInt err( KErrNone );
       
   412         
       
   413     if ( !IsActive() && ( 0 < iKeepaliveInterval ) )
       
   414         {
       
   415         if ( iRemoteAddressSet )
       
   416             {
       
   417             __SUBCONTROLLER( "CMccRtpKeepalive::StartSending(), issue send timer" )
       
   418             
       
   419             if ( iPreAudioPacketSent || !iRtpSinkExists  )
       
   420                 {
       
   421                 iTimer.After( iStatus, iKeepaliveInterval );
       
   422                 SetActive();
       
   423                 iCurrentState = EWaitingTimer;
       
   424                 }
       
   425             else
       
   426                 {
       
   427                 // Send firewall punching packet before possibly later 
       
   428                 // starting audio.
       
   429                 Send();
       
   430                 iPreAudioPacketSent = ETrue;
       
   431                 }
       
   432             }
       
   433         else
       
   434             {
       
   435             iCurrentState = ESendingPending;
       
   436             }
       
   437         }
       
   438     
       
   439     return err;
       
   440     }
       
   441 
       
   442 // ---------------------------------------------------------------------------
       
   443 // CMccRtpKeepalive::Send
       
   444 // ---------------------------------------------------------------------------
       
   445 //    
       
   446 TInt CMccRtpKeepalive::Send()
       
   447     {
       
   448     TInt err( KErrInUse );
       
   449     if ( !IsActive() )
       
   450         {
       
   451         // not called if rtpsink exists
       
   452         if ( !iRtpSinkExists )
       
   453             {
       
   454             __SUBCONTROLLER( "CMccRtpKeepalive::StartSending() - No RtpSink Exists" )
       
   455             iCurrentTime.UniversalTime();
       
   456             TTimeIntervalMicroSeconds interval = 
       
   457                 iCurrentTime.MicroSecondsFrom( iInitialTime );
       
   458             iRtpHeaderInfo.iTimestamp = interval.Int64();
       
   459             
       
   460             err = iRtpAPI.SendRtpPacket( iRtpStreamId, 
       
   461                                          iSequenceNum,
       
   462                                          iRtpHeaderInfo, 
       
   463                                          *iKeepaliveData,
       
   464                                          iStatus );                           
       
   465             }
       
   466         else
       
   467             {
       
   468             __SUBCONTROLLER_INT1( "CMccRtpKeepalive::Send() PT:", iRtpHeaderInfo.iPayloadType )        
       
   469             __SUBCONTROLLER_INT1( "CMccRtpKeepalive::Send() Data:", iKeepaliveData->Length() )
       
   470             iRtpMediaClock->GetLatestConsumedTS( iRtpHeaderInfo.iTimestamp );        
       
   471             err = iRtpAPI.SendRtpPacket( iRtpStreamId,
       
   472                                          iRtpHeaderInfo,
       
   473                                          *iKeepaliveData,
       
   474                                          iStatus );
       
   475             }              
       
   476         if ( !err )
       
   477             {
       
   478             __SUBCONTROLLER( "CMccRtpKeepalive::StartSending - Sending" )              
       
   479             SetActive();    
       
   480             iCurrentState = ESending;
       
   481             }
       
   482         }
       
   483     return err;
       
   484     }
       
   485 
       
   486 // ---------------------------------------------------------------------------
       
   487 // CMccRtpKeepalive::Random
       
   488 // ---------------------------------------------------------------------------
       
   489 //
       
   490 TUint16 CMccRtpKeepalive::Random() const
       
   491     {
       
   492     const TInt KRandMax = 0x7fff;
       
   493     TTime tmp_time;
       
   494     tmp_time.HomeTime();
       
   495     TInt64 seed = tmp_time.Int64();
       
   496     TInt32 rand = Math::Rand( seed );
       
   497     return static_cast<TUint16>( Abs( rand ) % KRandMax );
       
   498     }
       
   499 
       
   500 // ---------------------------------------------------------------------------
       
   501 // CMccRtpKeepalive::SendErrorToClient
       
   502 // ---------------------------------------------------------------------------
       
   503 //    
       
   504 void CMccRtpKeepalive::SendErrorToClient( TInt aError )
       
   505     {
       
   506     __SUBCONTROLLER( "CMccRtpKeepalive::SendErrorToClient()" )
       
   507     
       
   508     TMccEvent event;
       
   509     event.iErrorCode = aError;
       
   510     event.iEventCategory = KMccEventCategoryRtp;
       
   511     event.iEventType = KMccStreamError;
       
   512     
       
   513     // Use whatever internal uid
       
   514     TMccInternalEvent internalEvent( KMccRtpSourceUid, 
       
   515                              EMccInternalEventNone,
       
   516                              event );
       
   517                              
       
   518     iEventHandler.SendEventToClient( internalEvent );
       
   519     
       
   520     __SUBCONTROLLER( "CMccRtpKeepalive::SendErrorToClient(), exit" )
       
   521     }
       
   522         
       
   523 // ---------------------------------------------------------------------------
       
   524 // CMccRtpKeepalive::CMccRtpKeepalive
       
   525 // C++ default constructor can NOT contain any code, that
       
   526 // might leave.
       
   527 // ---------------------------------------------------------------------------
       
   528 //
       
   529 CMccRtpKeepalive::CMccRtpKeepalive( 
       
   530     MAsyncEventHandler& aEventHandler, 
       
   531     CRtpAPI& aRtpAPI,
       
   532     TRtpId aRtpSessionId,
       
   533     TBool aRemoteAddressSet ) : 
       
   534     CActive( EPriorityStandard ),
       
   535     iEventHandler( aEventHandler ), 
       
   536     iRtpAPI( aRtpAPI ),
       
   537     iRtpSessionId( aRtpSessionId ),
       
   538     iRtpStreamId( KNullId ),
       
   539     iRemoteAddressSet( aRemoteAddressSet )
       
   540     {  
       
   541     CActiveScheduler::Add( this );
       
   542     }
       
   543       
       
   544 // ---------------------------------------------------------------------------
       
   545 // CMccRtpKeepalive::ConstructL
       
   546 // Symbian 2nd phase constructor can leave.
       
   547 // ---------------------------------------------------------------------------
       
   548 //
       
   549 void CMccRtpKeepalive::ConstructL( 
       
   550     TUint8 aKeepalivePayloadType,
       
   551     TUint8 aKeepaliveInterval,
       
   552     const TDesC8& aKeepaliveData )
       
   553     {
       
   554     __SUBCONTROLLER( "CMccRtpKeepalive::ConstructL()" )
       
   555     
       
   556     User::LeaveIfError( iTimer.CreateLocal() );
       
   557     
       
   558     __ASSERT_ALWAYS( aKeepalivePayloadType < KMccPayloadTypeMax, 
       
   559                      User::Leave( KErrArgument ) );
       
   560     
       
   561     iRtpHeaderInfo.iMarker = 0;
       
   562     
       
   563     UpdateParamsL( aKeepalivePayloadType, aKeepaliveInterval, 
       
   564         aKeepaliveData );
       
   565     
       
   566     iSequenceNum = Random();
       
   567     
       
   568     iInitialTime.UniversalTime();
       
   569     
       
   570     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::ConstructL(), keepalive pt:", 
       
   571                           aKeepalivePayloadType )
       
   572     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::ConstructL(), keepalive interval (microsecs):", 
       
   573                           iKeepaliveInterval )
       
   574     __SUBCONTROLLER_INT1( "CMccRtpKeepalive::ConstructL(), keepalive data len:", 
       
   575                           iKeepaliveData->Length() )
       
   576     __SUBCONTROLLER( "CMccRtpKeepalive::ConstructL(), exit" )
       
   577     }
       
   578     
       
   579 
       
   580 
       
   581        
       
   582 // ========================== OTHER EXPORTED FUNCTIONS =======================
       
   583 
       
   584 //  End of File