mmsharing/mmshengine/src/musengreceivesession.cpp
changeset 22 496ad160a278
equal deleted inserted replaced
15:ccd8e69b5392 22:496ad160a278
       
     1 /*
       
     2 * Copyright (c) 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: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // USER INCLUDES
       
    21 #include "musengreceivesession.h"
       
    22 #include "musengmceutils.h"
       
    23 #include "musenglogger.h"
       
    24 #include "mussipprofilehandler.h"
       
    25 #include "mussessionproperties.h"
       
    26 #include "musengremotevideoplayer.h"
       
    27 
       
    28 // SYSTEM INCLUDES
       
    29 #include <lcsessionobserver.h>
       
    30 #include <mcemanager.h>
       
    31 #include <mceinsession.h>
       
    32 #include <mcestreambundle.h>
       
    33 #include <mceaudiostream.h>
       
    34 #include <mcevideostream.h>
       
    35 #include <mcemediasource.h>
       
    36 #include <mcertpsource.h>
       
    37 #include <mcedisplaysink.h>
       
    38 #include <mcespeakersink.h>
       
    39 #include <mceaudiocodec.h>
       
    40 #include <mceavccodec.h>
       
    41 #include <e32property.h>
       
    42 
       
    43 #include <utf.h>
       
    44 
       
    45 const TInt KMusEngJitterBufferLength = 51; //Must be bigger than treshold
       
    46 // Using following value increases treshold buffer to 1 second from 
       
    47 // default 100 ms
       
    48 const TInt KMusEngJitterBufferTreshold = 50;
       
    49 const TInt KMusEngTresholdToSecondsFactor = 20;
       
    50 const TInt KMusEngTwoSecondInMilliSeconds = 2000; 
       
    51 // Use inactivity timer value that is a little bigger than treshold in seconds
       
    52 const TUint KMusEngInactivityTimer = KMusEngTresholdToSecondsFactor * 
       
    53                                      KMusEngJitterBufferTreshold + 
       
    54                                      KMusEngTwoSecondInMilliSeconds;
       
    55 
       
    56 _LIT8( KMusEngSwisIdentifier, "Require: precondition" );
       
    57 _LIT8( KMusEngAssertedIdentity, "P-Asserted-Identity" );
       
    58 _LIT8( KMusEngBiggerSign, ">" );
       
    59 
       
    60 const TInt KMusEngSipReasonCodeBusyHere = 486;
       
    61 _LIT8( KMusEngSipReasonPhraseBusy, "Busy" );
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 //
       
    65 // -----------------------------------------------------------------------------
       
    66 //
       
    67 CMusEngReceiveSession* CMusEngReceiveSession::NewL()
       
    68     {
       
    69     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::NewL(...)" )
       
    70 
       
    71     CMusEngReceiveSession* self = new( ELeave )CMusEngReceiveSession();
       
    72     CleanupStack::PushL( self );
       
    73     self->ConstructL();
       
    74     CleanupStack::Pop( self );
       
    75 
       
    76     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::NewL(...)" )
       
    77     return self;
       
    78     }
       
    79 
       
    80 // -----------------------------------------------------------------------------
       
    81 //
       
    82 // -----------------------------------------------------------------------------
       
    83 //
       
    84 CMusEngReceiveSession::CMusEngReceiveSession()
       
    85     : CMusEngMceSession()
       
    86     {
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 // -----------------------------------------------------------------------------
       
    92 //
       
    93 void CMusEngReceiveSession::ConstructL()
       
    94     {
       
    95     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::ConstructL()" )
       
    96 
       
    97     CMusEngMceSession::ConstructL();
       
    98     
       
    99     iOriginator = HBufC8::NewL( KMaxUriLength );
       
   100     
       
   101     iRemoteDisplayName = HBufC::NewL( KMaxUriLength );
       
   102 
       
   103     iRemoteVideoPlayer = CMusEngRemoteVideoPlayer::NewL( *this, *this );
       
   104     
       
   105     iReceivingInactivityTimeout = KMusEngInactivityTimer;
       
   106     
       
   107     iKeepaliveTimer = KMusEngRtpKeepAliveTimer;
       
   108     
       
   109     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::ConstructL()" )
       
   110     }
       
   111 
       
   112 // -----------------------------------------------------------------------------
       
   113 //
       
   114 // -----------------------------------------------------------------------------
       
   115 //
       
   116 CMusEngReceiveSession::~CMusEngReceiveSession()
       
   117     {
       
   118     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::~CMusEngReceiveSession()" )
       
   119     
       
   120     if ( iOriginator )
       
   121         {
       
   122         TRAP_IGNORE( SaveContactL( *iOriginator ) )
       
   123         }
       
   124     delete iOriginator;
       
   125     
       
   126     delete iRemoteDisplayName;
       
   127     
       
   128     delete iRemoteVideoPlayer;
       
   129     
       
   130     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::~CMusEngReceiveSession()" )
       
   131     }
       
   132 
       
   133 // -----------------------------------------------------------------------------
       
   134 // From MLcSession
       
   135 // -----------------------------------------------------------------------------
       
   136 //
       
   137 MLcSession::TLcSessionState CMusEngReceiveSession::LcSessionState() const
       
   138     {
       
   139     TLcSessionState state = CMusEngMceSession::LcSessionState();
       
   140     if ( !iSession && state == MLcSession::EUninitialized )
       
   141         {
       
   142         state = MLcSession::EReceived;
       
   143         }
       
   144     return state;
       
   145     }
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // From MLcSession
       
   149 // -----------------------------------------------------------------------------
       
   150 //
       
   151 void CMusEngReceiveSession::EstablishLcSessionL()
       
   152     {
       
   153     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::EstablishLcSessionL" )
       
   154 
       
   155     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   156     InSession()->AcceptL();
       
   157     
       
   158     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::EstablishLcSessionL" )
       
   159     }
       
   160 
       
   161 // -----------------------------------------------------------------------------
       
   162 // From MLcSession
       
   163 // -----------------------------------------------------------------------------
       
   164 //
       
   165 void CMusEngReceiveSession::TerminateLcSessionL()
       
   166     {
       
   167     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::EstablishLcSessionL" )
       
   168 
       
   169     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   170 
       
   171     if ( iSession->State() == CMceSession::EIncoming ||
       
   172          iSession->State() == CMceSession::EProceeding )
       
   173         {
       
   174         // Reject
       
   175         if ( iOperatorVariant )
       
   176             {
       
   177             // In operator variant, session is rejected with 486 instead of 603.
       
   178             // Also the reason phrase is supposed to be "Busy".
       
   179             InSession()->RejectL( KMusEngSipReasonPhraseBusy(), 
       
   180                                   KMusEngSipReasonCodeBusyHere );
       
   181             }
       
   182         else
       
   183             {
       
   184             InSession()->RejectL();
       
   185             }
       
   186         }
       
   187     else
       
   188         {
       
   189         iSession->TerminateL();
       
   190         }
       
   191     
       
   192     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::EstablishLcSessionL" )
       
   193     }
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // From MLcSession
       
   197 // -----------------------------------------------------------------------------
       
   198 //
       
   199 MLcVideoPlayer* CMusEngReceiveSession::RemoteVideoPlayer()
       
   200     {
       
   201     return iRemoteVideoPlayer;
       
   202     }
       
   203     
       
   204 // -----------------------------------------------------------------------------
       
   205 // From MLcSession
       
   206 // -----------------------------------------------------------------------------
       
   207 //
       
   208 const TDesC& CMusEngReceiveSession::RemoteDisplayName()
       
   209     {
       
   210     TBuf<RProperty::KMaxPropertySize> buffer;
       
   211 
       
   212     TInt error = RProperty::Get( NMusSessionApi::KCategoryUid,
       
   213                                  NMusSessionApi::KContactName,
       
   214                                  buffer );
       
   215     if ( error == KErrNone && buffer.Length() )
       
   216         {
       
   217         iRemoteDisplayName->Des().Copy( buffer );
       
   218         }
       
   219     
       
   220     else if ( iOriginator )
       
   221         {
       
   222         iRemoteDisplayName->Des().Copy(*iOriginator);   
       
   223         }
       
   224     return *iRemoteDisplayName;
       
   225     }
       
   226 
       
   227 // -----------------------------------------------------------------------------
       
   228 // When reserving resources is ready, this function reports observer about
       
   229 // incoming session and signals this also to other end terminal ( 180 ringing ).
       
   230 // -----------------------------------------------------------------------------
       
   231 //
       
   232 void CMusEngReceiveSession::HandleSessionStateChanged(
       
   233                                         CMceSession& aSession,
       
   234                                         TInt aStatusCode,
       
   235                                         const TDesC8& aReasonPhrase )
       
   236     {
       
   237     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::\
       
   238              HandleSessionStateChanged()" )
       
   239 
       
   240     MUS_ENG_LOG_SESSION_STATE_AND_STATUS( aSession, aStatusCode, aReasonPhrase )
       
   241 
       
   242     if ( iSession && 
       
   243          iSession == &aSession &&
       
   244          aSession.State() == CMceSession::EProceeding )
       
   245         {
       
   246         // Indicates that resource reservation is ready, user can be notified
       
   247         // if we do not have to wait for PRACK
       
   248         
       
   249         if ( !iRingLCalled )
       
   250             {
       
   251             // Notify other end terminal
       
   252             TRAP_IGNORE( InSession()->RingL() )
       
   253             iRingLCalled = ETrue;
       
   254             TPtr8 ptrOriginator( iOriginator->Des() );
       
   255             ptrOriginator.Copy( iSession->Originator() );
       
   256             InformObserverAboutSessionStateChange();
       
   257             }
       
   258         else
       
   259             {
       
   260             MUS_LOG( "mus: [ENGINE]     User and remote end already notified." )
       
   261             }
       
   262             
       
   263         }
       
   264     else
       
   265         {
       
   266         // Forward all other session state changes to base class
       
   267         CMusEngMceSession::HandleSessionStateChanged( aSession,
       
   268                                                       aStatusCode,
       
   269                                                       aReasonPhrase );
       
   270         }
       
   271 
       
   272     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::\
       
   273              HandleSessionStateChanged()" )
       
   274     }
       
   275 
       
   276 // -----------------------------------------------------------------------------
       
   277 // Sets keepalive timer for video and calls base class variant of this function
       
   278 // -----------------------------------------------------------------------------
       
   279 //
       
   280 void CMusEngReceiveSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec,
       
   281                                                TMceSourceType aSourceType )
       
   282     {
       
   283     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::AdjustVideoCodecL()" )
       
   284     
       
   285     CMusEngMceSession::AdjustVideoCodecL( aVideoCodec, aSourceType );
       
   286     
       
   287     MUS_LOG1( "mus: [ENGINE]     Keepalive timer:%d", iKeepaliveTimer )
       
   288     aVideoCodec.SetKeepAliveTimerL( iKeepaliveTimer );
       
   289     if ( aVideoCodec.SdpName() == KMceSDPNameH263() ||
       
   290          aVideoCodec.SdpName() == KMceSDPNameH2632000() )
       
   291         {
       
   292         aVideoCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeVideoH263 );
       
   293         }
       
   294     else if ( aVideoCodec.SdpName() == KMceSDPNameH264() )
       
   295         {
       
   296         aVideoCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeVideoAvc );
       
   297         }
       
   298     else
       
   299         {
       
   300         // NOP
       
   301         }
       
   302     
       
   303     aVideoCodec.SetKeepAliveDataL( KNullDesC8() );
       
   304     
       
   305     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::AdjustVideoCodecL()" )
       
   306     }
       
   307         
       
   308 // -----------------------------------------------------------------------------
       
   309 // Sets keepalive timer for audio and calls base class variant of this function
       
   310 // -----------------------------------------------------------------------------
       
   311 //        
       
   312 void CMusEngReceiveSession::AdjustAudioCodecL( CMceAudioCodec& aAudioCodec )
       
   313     {
       
   314     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::AdjustAudioCodecL()" )
       
   315 
       
   316     CMusEngMceSession::AdjustAudioCodecL( aAudioCodec );
       
   317     
       
   318     aAudioCodec.SetKeepAliveTimerL( iKeepaliveTimer );
       
   319     aAudioCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeAudio );
       
   320     aAudioCodec.SetKeepAliveDataL( KNullDesC8() );
       
   321     
       
   322     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::AdjustAudioCodecL()" )
       
   323     }
       
   324 
       
   325 // -----------------------------------------------------------------------------
       
   326 // 
       
   327 // -----------------------------------------------------------------------------
       
   328 //
       
   329 void CMusEngReceiveSession::DoCodecSelectionL( CMceVideoStream& aVideoStream )
       
   330     {
       
   331     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::DoCodecSelectionL()" )
       
   332     
       
   333     const RPointerArray<CMceVideoCodec>& codecs = aVideoStream.Codecs();
       
   334     
       
   335     const CMceVideoCodec* avcSingleNal = NULL;
       
   336     const CMceVideoCodec* avcNonInterleaved = NULL;
       
   337     
       
   338     for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
       
   339         {
       
   340         if ( codecs[codecIndex]->SdpName() == KMceSDPNameH264() )
       
   341             { 
       
   342             if ( codecs[codecIndex]->CodecMode() == KMceAvcModeSingleNal )
       
   343                 {
       
   344                 // Store a pointer to the Single NAL codec with best bitrate
       
   345                 if ( !avcSingleNal || 
       
   346                      ( avcSingleNal && codecs[codecIndex]->MaxBitRate() > 
       
   347                                        avcSingleNal->MaxBitRate() ) )
       
   348                     {
       
   349                     avcSingleNal = codecs[codecIndex];
       
   350                     }
       
   351                 }  
       
   352             else if ( codecs[codecIndex]->CodecMode() == 
       
   353                                                 KMceAvcModeNonInterleaved )
       
   354                 {
       
   355                 // Store a pointer to the Non-Interleaved codec with best bitrate
       
   356                 if ( !avcNonInterleaved || 
       
   357                      ( avcNonInterleaved && codecs[codecIndex]->MaxBitRate() > 
       
   358                                             avcNonInterleaved->MaxBitRate() ) )
       
   359                     {
       
   360                     avcNonInterleaved = codecs[codecIndex];
       
   361                     }
       
   362                 }
       
   363             else 
       
   364                 {
       
   365                 // NOP, we do not care about interleaved AVC
       
   366                 }
       
   367             }
       
   368         }
       
   369     
       
   370     const CMceVideoCodec* selectedCodec = NULL;
       
   371     
       
   372     if ( avcNonInterleaved )
       
   373         {
       
   374         selectedCodec = avcNonInterleaved;
       
   375         }
       
   376     else
       
   377         {
       
   378         selectedCodec = avcSingleNal;
       
   379         }
       
   380    
       
   381     if ( selectedCodec )
       
   382         {
       
   383         // Remove all other codecs
       
   384         for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
       
   385             {
       
   386             if ( codecs[codecIndex] != selectedCodec )
       
   387                 {
       
   388                 aVideoStream.RemoveCodecL( *codecs[codecIndex] );
       
   389                 // Since succesfull removal of a codec has decreased the amount
       
   390                 // of codecs in array by one, we have to reset the index
       
   391                 codecIndex = 0;
       
   392                 }
       
   393             }   
       
   394         }
       
   395     else
       
   396         {
       
   397         // Let the base class do H.263 selection
       
   398         CMusEngMceSession::DoCodecSelectionL( aVideoStream );
       
   399         }
       
   400                
       
   401     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::DoCodecSelectionL()" )
       
   402     }
       
   403 
       
   404 // -----------------------------------------------------------------------------
       
   405 // If incoming session does not have valid structure and cannot be reconstructed
       
   406 // as such, session is rejected automatically.
       
   407 // -----------------------------------------------------------------------------
       
   408 //
       
   409 void CMusEngReceiveSession::IncomingSession(
       
   410     CMceInSession* aSession,
       
   411     TMceTransactionDataContainer* aContainer )
       
   412     {
       
   413     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::IncomingSession(...)" )
       
   414 
       
   415     if ( !aContainer || 
       
   416          ( iSession &&
       
   417            iSession->State() != CMceSession::ETerminated ) )
       
   418         {
       
   419         // We already have one session ongoing, or do not have container. 
       
   420         // Reject new session.
       
   421         Reject( *aSession );
       
   422         delete aSession;
       
   423         aSession = NULL;
       
   424         MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::IncomingSession( \
       
   425                  session already exists. New session rejected and deleted. )" )
       
   426         return;
       
   427         }
       
   428 
       
   429     delete iSession; // possibly existing terminated session
       
   430     iSession = aSession;
       
   431     
       
   432     if ( iOperatorVariant )
       
   433         {
       
   434         ParseAssertedIdentity( aContainer );    
       
   435         }
       
   436     
       
   437     // Reset variable defined for preparing for multiple state changes to
       
   438     // EProceeding. This might happen if we set 100rel to be required. 
       
   439     iRingLCalled = EFalse;
       
   440     
       
   441     // If preparing fails, session setup with VS2.2 will fail later
       
   442     TRAP_IGNORE( PrepareToRequire100RelL( aContainer ) )
       
   443         
       
   444     TRAPD( error, CompleteSessionStructureL() );
       
   445 
       
   446     if ( error != KErrNone )
       
   447         {
       
   448         Reject( *InSession() );
       
   449         }
       
   450 
       
   451     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::IncomingSession()" )
       
   452     }
       
   453 
       
   454 // -----------------------------------------------------------------------------
       
   455 //
       
   456 // -----------------------------------------------------------------------------
       
   457 //
       
   458 void CMusEngReceiveSession::IncomingUpdate(
       
   459     CMceSession& aOrigSession,
       
   460     CMceInSession* aUpdatedSession,
       
   461     TMceTransactionDataContainer* aContainer )
       
   462     {
       
   463     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::IncomingUpdate(...)" )
       
   464 
       
   465     if ( iSession &&
       
   466          iSession == &aOrigSession )
       
   467         {
       
   468         // Old session is useless from now on
       
   469         delete iSession;
       
   470         iSession = aUpdatedSession;
       
   471 
       
   472         TRAPD( error, CompleteSessionStructureL() );
       
   473 
       
   474         if ( error != KErrNone )
       
   475             {
       
   476             MUS_LOG( "mus: [ENGINE]  Cannot handle update, reject" )
       
   477             Reject( *aUpdatedSession );
       
   478             }
       
   479         }
       
   480     else
       
   481         {
       
   482         // Cannot handle, forward to a base class
       
   483         CMusEngMceSession::IncomingUpdate( aOrigSession,
       
   484                                            aUpdatedSession,
       
   485                                            aContainer );
       
   486         }
       
   487 
       
   488     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::IncomingUpdate(...)" )
       
   489     }
       
   490 
       
   491 // -----------------------------------------------------------------------------
       
   492 //
       
   493 // -----------------------------------------------------------------------------
       
   494 //
       
   495 void CMusEngReceiveSession::StreamStateChanged( CMceMediaStream& aStream )
       
   496     {
       
   497     MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::StreamStateChanged()" )
       
   498 
       
   499     MUS_ENG_LOG_STREAM_STATE( aStream )
       
   500 
       
   501     if ( !iSession )
       
   502         {
       
   503         return;
       
   504         }
       
   505 
       
   506     if ( aStream.Type() == KMceVideo &&
       
   507          aStream.Source() &&
       
   508          aStream.Source()->Type() == KMceRTPSource )
       
   509         {
       
   510         if ( aStream.State() == CMceMediaStream::EBuffering )
       
   511             {
       
   512             iBuffered = ETrue;
       
   513             InformObserverAboutPlayerStateChange( iRemoteVideoPlayer );
       
   514             }
       
   515         else if ( aStream.State() == CMceMediaStream::EStreaming )
       
   516             {
       
   517             ReceivingStarted();          
       
   518             }
       
   519         else
       
   520             {
       
   521             // Cannot handle, forward to CMusEngMceSession
       
   522             CMusEngMceSession::StreamStateChanged( aStream );
       
   523             }
       
   524         }
       
   525     else
       
   526         {
       
   527         // Cannot handle, forward to CMusEngMceSession
       
   528         CMusEngMceSession::StreamStateChanged( aStream );
       
   529         }
       
   530 
       
   531     MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::StreamStateChanged()" )
       
   532     }
       
   533 
       
   534 // -----------------------------------------------------------------------------
       
   535 //
       
   536 // -----------------------------------------------------------------------------
       
   537 //
       
   538 CMceInSession* CMusEngReceiveSession::InSession()
       
   539     {
       
   540     return static_cast<CMceInSession*>(iSession);
       
   541     }
       
   542 
       
   543 // -----------------------------------------------------------------------------
       
   544 // Check if incoming session is originated from VideoSharing 2.2 client, 
       
   545 // which sends PRACK for 180 Ringing whether it is required or not. In 
       
   546 // order to let MCE handle the PRACK correctly, force 180 Ringing to be 
       
   547 // sent reliably.
       
   548 // -----------------------------------------------------------------------------
       
   549 //
       
   550 void CMusEngReceiveSession::PrepareToRequire100RelL( 
       
   551     TMceTransactionDataContainer* aContainer)
       
   552     {
       
   553     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::PrepareToRequire100RelL()" )
       
   554     
       
   555     __ASSERT_ALWAYS( aContainer, User::Leave( KErrArgument ) );
       
   556     
       
   557     CDesC8Array* headers = aContainer->GetHeaders();
       
   558     CleanupStack::PushL( headers );
       
   559      
       
   560     if ( headers )
       
   561         {
       
   562         for ( TInt i = 0; i < headers->Count(); ++i )
       
   563             {
       
   564             if ( headers->MdcaPoint(i).FindF( KMusEngSwisIdentifier() ) != 
       
   565                  KErrNotFound )
       
   566                 {
       
   567                 iSession->SetModifierL( KMce100Rel, KMce100RelRequired );
       
   568                 MUS_LOG( "mus: [ENGINE]     Forced to require 100rel" )
       
   569                 }   
       
   570             }     
       
   571         }
       
   572     
       
   573     CleanupStack::PopAndDestroy( headers );
       
   574    
       
   575     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::PrepareToRequire100RelL()" )
       
   576     }      
       
   577 
       
   578 // -----------------------------------------------------------------------------
       
   579 // Check that incoming session contains only incoming video and audio
       
   580 // streams. All the other streams will be removed. If there is no
       
   581 // display sinks and speakers, they will be created.
       
   582 // -----------------------------------------------------------------------------
       
   583 //
       
   584 void CMusEngReceiveSession::CompleteSessionStructureL()
       
   585     {
       
   586     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::CompleteSessionStructureL()" )
       
   587 
       
   588     __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
       
   589 
       
   590     // Force bandwidth line usage in sdp as it is mandatory
       
   591     // at MT side based on GSMA VS specification IR.74. Bandwidth is set to
       
   592     // session or to media level based on sender's way of usage. If other end
       
   593     // is not using bandwidth attribute at all, media level is preferred.
       
   594     SetSessionSdpLinesL( *iSession, ETrue );
       
   595 
       
   596     CMceStreamBundle* localBundle =
       
   597                             CMceStreamBundle::NewLC( CMceStreamBundle::ELS );
       
   598 
       
   599     const RPointerArray<CMceMediaStream>& streams = iSession->Streams();
       
   600 
       
   601     CMceMediaStream* videoInStream = NULL;
       
   602 
       
   603     for( TInt i = 0; i < streams.Count(); ++i )
       
   604         {
       
   605         if ( MusEngMceUtils::IsVideoInStream( *streams[i] ) &&
       
   606              !videoInStream )
       
   607             {
       
   608             videoInStream = streams[i];
       
   609             
       
   610             // Disable possible opposite stream to indicate that sendrecv is
       
   611             // not allowed.
       
   612             if ( streams[i]->BoundStream() )
       
   613                 {
       
   614                 MusEngMceUtils::DisableStreamL( streams[i]->BoundStreamL() );
       
   615                 }
       
   616             }
       
   617         else if ( streams[i]->BoundStream() &&
       
   618                   MusEngMceUtils::IsVideoInStream( streams[i]->BoundStreamL() ) &&
       
   619                   !videoInStream )
       
   620             {
       
   621             videoInStream = &streams[i]->BoundStreamL();
       
   622                 
       
   623             // Disable opposite stream to indicate that sendrecv is not allowed.
       
   624             MusEngMceUtils::DisableStreamL( *streams[i] );
       
   625             }
       
   626         else if ( MusEngMceUtils::IsAudioInStream( *streams[i] ) && 
       
   627                   !iOperatorVariant )
       
   628             {
       
   629             MusEngMceUtils::AddSpeakerL( *streams[i] );
       
   630 
       
   631             localBundle->AddStreamL( *streams[i] );
       
   632             
       
   633             // Disable possible opposite stream to indicate that sendrecv is
       
   634             // not allowed.
       
   635             if ( streams[i]->BoundStream() )
       
   636                 {
       
   637                 MusEngMceUtils::DisableStreamL( streams[i]->BoundStreamL() );
       
   638                 }
       
   639             }
       
   640         else if ( streams[i]->BoundStream() &&
       
   641                   MusEngMceUtils::IsAudioInStream( streams[i]->BoundStreamL() ) &&
       
   642                   !iOperatorVariant )
       
   643             {
       
   644             MusEngMceUtils::AddSpeakerL( streams[i]->BoundStreamL() );
       
   645 
       
   646             localBundle->AddStreamL( streams[i]->BoundStreamL() );
       
   647             
       
   648             // Disable opposite stream to indicate that sendrecv is not allowed.
       
   649             MusEngMceUtils::DisableStreamL( *streams[i] );
       
   650             }
       
   651         else
       
   652             {
       
   653             // We remove stream because either it 
       
   654             // 1. Is not and does not contain incoming video or audio, or
       
   655             // 2. We already have one incoming video stream or
       
   656             // 3. Stream is audio and we run operator variant where audio is 
       
   657             //    not allowed.
       
   658             iSession->RemoveStreamL( *streams[i] );
       
   659 
       
   660             // Since succesfull removal of a stream has decreased the amount
       
   661             // of streams in array by one, we have to modify the index
       
   662             --i;
       
   663             }
       
   664         }
       
   665         
       
   666     if ( videoInStream )
       
   667         {
       
   668         SetMediaSdpLinesL( *videoInStream, ETrue );
       
   669         
       
   670         // Complete stream
       
   671         MusEngMceUtils::AddDisplayL( *videoInStream, *iManager, Rect() );
       
   672         
       
   673         static_cast<CMceRtpSource*>(videoInStream->Source())->UpdateL( 
       
   674                                                 KMusEngJitterBufferLength,
       
   675                                                 KMusEngJitterBufferTreshold );
       
   676                                                  
       
   677         localBundle->AddStreamL( *videoInStream );
       
   678         }
       
   679     else
       
   680         {
       
   681         User::Leave( KErrCorrupt );
       
   682         }
       
   683 
       
   684     // Next line is to cause a leave if there were no incoming video streams
       
   685     MusEngMceUtils::GetVideoInStreamL( *iSession );
       
   686 
       
   687     // Destroy bundle if it is not needed or transfer ownership
       
   688     if ( localBundle->Streams().Count() > 1 )
       
   689         {
       
   690         iSession->AddBundleL( localBundle );
       
   691         CleanupStack::Pop( localBundle );
       
   692         }
       
   693     else
       
   694         {
       
   695         CleanupStack::PopAndDestroy( localBundle );
       
   696         }
       
   697 
       
   698     AdjustStreamsAndCodecsL();
       
   699 
       
   700     iSession->UpdateL();
       
   701 
       
   702     // Now session state is right to adjust volume
       
   703     SetSpeakerVolumeL( LcVolumeL() );
       
   704 
       
   705     iSipProfileHandler->CreateProfileL( iSession->Profile() );
       
   706     
       
   707     iRemoteVideoPlayer->SetMceSession( iSession );
       
   708     
       
   709     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::CompleteSessionStructureL()" )
       
   710     }
       
   711     
       
   712 // -----------------------------------------------------------------------------
       
   713 // Parse P-Asserted-Identity Header
       
   714 // -----------------------------------------------------------------------------
       
   715 //
       
   716 void CMusEngReceiveSession::ParseAssertedIdentity( 
       
   717                                 TMceTransactionDataContainer* aContainer )
       
   718     {
       
   719     MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::AssertedIdentity()" )
       
   720     
       
   721     iIdentity.Zero();
       
   722     
       
   723     if ( !aContainer )
       
   724         {
       
   725         MUS_LOG( "mus: [ENGINE]  Data container is NULL" )  
       
   726         MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::AssertedIdentity()" )  
       
   727         return;
       
   728         }
       
   729     
       
   730     CDesC8Array* headers = aContainer->GetHeaders();
       
   731     
       
   732     if ( !headers )
       
   733         {
       
   734         MUS_LOG( "mus: [ENGINE]  No headers" )  
       
   735         MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::AssertedIdentity()" )  
       
   736         return;
       
   737         }    
       
   738     
       
   739     TBool found = EFalse;
       
   740     TInt length = 0;
       
   741     for( TInt i = 0; i < headers->Count() && !found; ++i )
       
   742         {
       
   743         TPtrC8 header = (*headers)[i];
       
   744         if ( header.FindF( KMusEngAssertedIdentity ) != KErrNotFound )
       
   745             {
       
   746             TInt pos = 0;
       
   747             // check for sip url, continue if found because maybe tel url exists
       
   748             if ( ( pos = header.FindF( KMusEngSipPrefix ) ) != KErrNotFound )
       
   749                 {
       
   750                 TInt atPos = header.FindF( KMusEngAtSign );
       
   751                 length = atPos - pos - KMusEngSipPrefix().Length();
       
   752                 if ( length > 0 && length <= KMaxUriLength )
       
   753                     {
       
   754                     iIdentity.Copy( 
       
   755                         header.Mid( pos + KMusEngSipPrefix().Length(), length ) );    
       
   756                     }
       
   757                 }
       
   758             // check for tel url, exit if found
       
   759             else if ( ( pos = header.FindF( KMusEngTelPrefix ) ) != KErrNotFound )
       
   760                 {
       
   761                 length = header.Length() - pos - KMusEngTelPrefix().Length();
       
   762                 if ( length > 0 && length <= KMaxUriLength )
       
   763                     {
       
   764                     iIdentity.Copy( header.Right( length ) );    
       
   765                     }
       
   766                 found = ETrue;
       
   767                 }
       
   768             }
       
   769         }
       
   770 
       
   771     // remove ending '>' if exists and whitespaces
       
   772     if ( iIdentity.Length() > 0 )
       
   773         {
       
   774         iIdentity.Trim();
       
   775         if ( iIdentity.Find( KMusEngBiggerSign ) == iIdentity.Length() - 1 )
       
   776             {
       
   777             iIdentity = iIdentity.Left( iIdentity.Length() - 1 );
       
   778             iIdentity.Trim();
       
   779             }
       
   780         }
       
   781 
       
   782     delete headers;  
       
   783     MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::AssertedIdentity()" )      
       
   784     }
       
   785 
       
   786 // -----------------------------------------------------------------------------
       
   787 // RTP Inactivity timeout event
       
   788 // Once inactivity timeout occurs, state change is notified and receiving
       
   789 // and buffering statuses are cleared. That is safe to do as once receiving
       
   790 // again continues for real, buffering and streaming events will occur always 
       
   791 // sequentially. If buffering status would not be cleared, some unwanted
       
   792 // sreaming events would be passed towards client when it disables/enables
       
   793 // display sink of remote stream while inactivity timer has expired.
       
   794 // -----------------------------------------------------------------------------
       
   795 //
       
   796 void CMusEngReceiveSession::InactivityTimeout( CMceMediaStream& aStream,
       
   797                                                   CMceRtpSource& /*aSource*/ )
       
   798     {
       
   799     MUS_LOG( "mus: [ENGINE]  -> CMusEngTwoWayRecvSession::InactivityTimeout()" )
       
   800     
       
   801     if ( aStream.Type() == KMceVideo && iReceiving )
       
   802         {
       
   803         iReceiving = EFalse;
       
   804         iBuffered = EFalse;
       
   805         InformObserverAboutPlayerStateChange( iRemoteVideoPlayer );
       
   806         }
       
   807     
       
   808     MUS_LOG( "mus: [ENGINE]  <- CMusEngTwoWayRecvSession::InactivityTimeout()" )
       
   809     }
       
   810 
       
   811 // -----------------------------------------------------------------------------
       
   812 //
       
   813 // -----------------------------------------------------------------------------
       
   814 //
       
   815 void CMusEngReceiveSession::ReceivingStarted()
       
   816     {
       
   817     if ( iSession && iBuffered )
       
   818         {
       
   819         MUS_LOG( "mus: [ENGINE]  -> CMusEngReceiveSession::ReceivingStarted()" )
       
   820         
       
   821         TInt err = MusEngMceUtils::EnableInactivityTimer( 
       
   822                 *iSession, iReceivingInactivityTimeout );
       
   823         
       
   824         if ( err != KErrNone )
       
   825             {
       
   826             MUS_LOG1("mus: [ENGINE] ReceivingStarted failed %d", err)
       
   827             InformObserverAboutSessionFailure( err );
       
   828             }
       
   829         else
       
   830             {
       
   831             iReceiving = ETrue;
       
   832             InformObserverAboutPlayerStateChange( iRemoteVideoPlayer );
       
   833             InformUiProviderAboutReceivingStart();
       
   834             }
       
   835         
       
   836         MUS_LOG( "mus: [ENGINE]  <- CMusEngReceiveSession::ReceivingStarted()" )
       
   837         }
       
   838     }
       
   839 
       
   840 // -----------------------------------------------------------------------------
       
   841 // 
       
   842 // -----------------------------------------------------------------------------
       
   843 //
       
   844 TBool CMusEngReceiveSession::IsDisplayActive()
       
   845     {
       
   846     return ( IsDisplayEnabled() && iReceiving );
       
   847     }
       
   848 // End of File