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