--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsharing/mmshengine/src/musengreceivesession.cpp Fri Jun 11 13:36:18 2010 +0300
@@ -0,0 +1,848 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+
+// USER INCLUDES
+#include "musengreceivesession.h"
+#include "musengmceutils.h"
+#include "musenglogger.h"
+#include "mussipprofilehandler.h"
+#include "mussessionproperties.h"
+#include "musengremotevideoplayer.h"
+
+// SYSTEM INCLUDES
+#include <lcsessionobserver.h>
+#include <mcemanager.h>
+#include <mceinsession.h>
+#include <mcestreambundle.h>
+#include <mceaudiostream.h>
+#include <mcevideostream.h>
+#include <mcemediasource.h>
+#include <mcertpsource.h>
+#include <mcedisplaysink.h>
+#include <mcespeakersink.h>
+#include <mceaudiocodec.h>
+#include <mceavccodec.h>
+#include <e32property.h>
+
+#include <utf.h>
+
+const TInt KMusEngJitterBufferLength = 51; //Must be bigger than treshold
+// Using following value increases treshold buffer to 1 second from
+// default 100 ms
+const TInt KMusEngJitterBufferTreshold = 50;
+const TInt KMusEngTresholdToSecondsFactor = 20;
+const TInt KMusEngTwoSecondInMilliSeconds = 2000;
+// Use inactivity timer value that is a little bigger than treshold in seconds
+const TUint KMusEngInactivityTimer = KMusEngTresholdToSecondsFactor *
+ KMusEngJitterBufferTreshold +
+ KMusEngTwoSecondInMilliSeconds;
+
+_LIT8( KMusEngSwisIdentifier, "Require: precondition" );
+_LIT8( KMusEngAssertedIdentity, "P-Asserted-Identity" );
+_LIT8( KMusEngBiggerSign, ">" );
+
+const TInt KMusEngSipReasonCodeBusyHere = 486;
+_LIT8( KMusEngSipReasonPhraseBusy, "Busy" );
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMusEngReceiveSession* CMusEngReceiveSession::NewL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::NewL(...)" )
+
+ CMusEngReceiveSession* self = new( ELeave )CMusEngReceiveSession();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::NewL(...)" )
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMusEngReceiveSession::CMusEngReceiveSession()
+ : CMusEngMceSession()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::ConstructL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::ConstructL()" )
+
+ CMusEngMceSession::ConstructL();
+
+ iOriginator = HBufC8::NewL( KMaxUriLength );
+
+ iRemoteDisplayName = HBufC::NewL( KMaxUriLength );
+
+ iRemoteVideoPlayer = CMusEngRemoteVideoPlayer::NewL( *this, *this );
+
+ iReceivingInactivityTimeout = KMusEngInactivityTimer;
+
+ iKeepaliveTimer = KMusEngRtpKeepAliveTimer;
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::ConstructL()" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMusEngReceiveSession::~CMusEngReceiveSession()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::~CMusEngReceiveSession()" )
+
+ if ( iOriginator )
+ {
+ TRAP_IGNORE( SaveContactL( *iOriginator ) )
+ }
+ delete iOriginator;
+
+ delete iRemoteDisplayName;
+
+ delete iRemoteVideoPlayer;
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::~CMusEngReceiveSession()" )
+ }
+
+// -----------------------------------------------------------------------------
+// From MLcSession
+// -----------------------------------------------------------------------------
+//
+MLcSession::TLcSessionState CMusEngReceiveSession::LcSessionState() const
+ {
+ TLcSessionState state = CMusEngMceSession::LcSessionState();
+ if ( !iSession && state == MLcSession::EUninitialized )
+ {
+ state = MLcSession::EReceived;
+ }
+ return state;
+ }
+
+// -----------------------------------------------------------------------------
+// From MLcSession
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::EstablishLcSessionL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::EstablishLcSessionL" )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+ InSession()->AcceptL();
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::EstablishLcSessionL" )
+ }
+
+// -----------------------------------------------------------------------------
+// From MLcSession
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::TerminateLcSessionL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::EstablishLcSessionL" )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ if ( iSession->State() == CMceSession::EIncoming ||
+ iSession->State() == CMceSession::EProceeding )
+ {
+ // Reject
+ if ( iOperatorVariant )
+ {
+ // In operator variant, session is rejected with 486 instead of 603.
+ // Also the reason phrase is supposed to be "Busy".
+ InSession()->RejectL( KMusEngSipReasonPhraseBusy(),
+ KMusEngSipReasonCodeBusyHere );
+ }
+ else
+ {
+ InSession()->RejectL();
+ }
+ }
+ else
+ {
+ iSession->TerminateL();
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::EstablishLcSessionL" )
+ }
+
+// -----------------------------------------------------------------------------
+// From MLcSession
+// -----------------------------------------------------------------------------
+//
+MLcVideoPlayer* CMusEngReceiveSession::RemoteVideoPlayer()
+ {
+ return iRemoteVideoPlayer;
+ }
+
+// -----------------------------------------------------------------------------
+// From MLcSession
+// -----------------------------------------------------------------------------
+//
+const TDesC& CMusEngReceiveSession::RemoteDisplayName()
+ {
+ TBuf<RProperty::KMaxPropertySize> buffer;
+
+ TInt error = RProperty::Get( NMusSessionApi::KCategoryUid,
+ NMusSessionApi::KContactName,
+ buffer );
+ if ( error == KErrNone && buffer.Length() )
+ {
+ iRemoteDisplayName->Des().Copy( buffer );
+ }
+
+ else if ( iOriginator )
+ {
+ iRemoteDisplayName->Des().Copy(*iOriginator);
+ }
+ return *iRemoteDisplayName;
+ }
+
+// -----------------------------------------------------------------------------
+// When reserving resources is ready, this function reports observer about
+// incoming session and signals this also to other end terminal ( 180 ringing ).
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::HandleSessionStateChanged(
+ CMceSession& aSession,
+ TInt aStatusCode,
+ const TDesC8& aReasonPhrase )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::\
+ HandleSessionStateChanged()" )
+
+ MUS_ENG_LOG_SESSION_STATE_AND_STATUS( aSession, aStatusCode, aReasonPhrase )
+
+ if ( iSession &&
+ iSession == &aSession &&
+ aSession.State() == CMceSession::EProceeding )
+ {
+ // Indicates that resource reservation is ready, user can be notified
+ // if we do not have to wait for PRACK
+
+ if ( !iRingLCalled )
+ {
+ // Notify other end terminal
+ TRAP_IGNORE( InSession()->RingL() )
+ iRingLCalled = ETrue;
+ TPtr8 ptrOriginator( iOriginator->Des() );
+ ptrOriginator.Copy( iSession->Originator() );
+ InformObserverAboutSessionStateChange();
+ }
+ else
+ {
+ MUS_LOG( "mus: [ENGINE] User and remote end already notified." )
+ }
+
+ }
+ else
+ {
+ // Forward all other session state changes to base class
+ CMusEngMceSession::HandleSessionStateChanged( aSession,
+ aStatusCode,
+ aReasonPhrase );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::\
+ HandleSessionStateChanged()" )
+ }
+
+// -----------------------------------------------------------------------------
+// Sets keepalive timer for video and calls base class variant of this function
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec,
+ TMceSourceType aSourceType )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::AdjustVideoCodecL()" )
+
+ CMusEngMceSession::AdjustVideoCodecL( aVideoCodec, aSourceType );
+
+ MUS_LOG1( "mus: [ENGINE] Keepalive timer:%d", iKeepaliveTimer )
+ aVideoCodec.SetKeepAliveTimerL( iKeepaliveTimer );
+ if ( aVideoCodec.SdpName() == KMceSDPNameH263() ||
+ aVideoCodec.SdpName() == KMceSDPNameH2632000() )
+ {
+ aVideoCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeVideoH263 );
+ }
+ else if ( aVideoCodec.SdpName() == KMceSDPNameH264() )
+ {
+ aVideoCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeVideoAvc );
+ }
+ else
+ {
+ // NOP
+ }
+
+ aVideoCodec.SetKeepAliveDataL( KNullDesC8() );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AdjustVideoCodecL()" )
+ }
+
+// -----------------------------------------------------------------------------
+// Sets keepalive timer for audio and calls base class variant of this function
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::AdjustAudioCodecL( CMceAudioCodec& aAudioCodec )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::AdjustAudioCodecL()" )
+
+ CMusEngMceSession::AdjustAudioCodecL( aAudioCodec );
+
+ aAudioCodec.SetKeepAliveTimerL( iKeepaliveTimer );
+ aAudioCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeAudio );
+ aAudioCodec.SetKeepAliveDataL( KNullDesC8() );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AdjustAudioCodecL()" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::DoCodecSelectionL( CMceVideoStream& aVideoStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::DoCodecSelectionL()" )
+
+ const RPointerArray<CMceVideoCodec>& codecs = aVideoStream.Codecs();
+
+ const CMceVideoCodec* avcSingleNal = NULL;
+ const CMceVideoCodec* avcNonInterleaved = NULL;
+
+ for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
+ {
+ if ( codecs[codecIndex]->SdpName() == KMceSDPNameH264() )
+ {
+ if ( codecs[codecIndex]->CodecMode() == KMceAvcModeSingleNal )
+ {
+ // Store a pointer to the Single NAL codec with best bitrate
+ if ( !avcSingleNal ||
+ ( avcSingleNal && codecs[codecIndex]->MaxBitRate() >
+ avcSingleNal->MaxBitRate() ) )
+ {
+ avcSingleNal = codecs[codecIndex];
+ }
+ }
+ else if ( codecs[codecIndex]->CodecMode() ==
+ KMceAvcModeNonInterleaved )
+ {
+ // Store a pointer to the Non-Interleaved codec with best bitrate
+ if ( !avcNonInterleaved ||
+ ( avcNonInterleaved && codecs[codecIndex]->MaxBitRate() >
+ avcNonInterleaved->MaxBitRate() ) )
+ {
+ avcNonInterleaved = codecs[codecIndex];
+ }
+ }
+ else
+ {
+ // NOP, we do not care about interleaved AVC
+ }
+ }
+ }
+
+ const CMceVideoCodec* selectedCodec = NULL;
+
+ if ( avcNonInterleaved )
+ {
+ selectedCodec = avcNonInterleaved;
+ }
+ else
+ {
+ selectedCodec = avcSingleNal;
+ }
+
+ if ( selectedCodec )
+ {
+ // Remove all other codecs
+ for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
+ {
+ if ( codecs[codecIndex] != selectedCodec )
+ {
+ aVideoStream.RemoveCodecL( *codecs[codecIndex] );
+ // Since succesfull removal of a codec has decreased the amount
+ // of codecs in array by one, we have to reset the index
+ codecIndex = 0;
+ }
+ }
+ }
+ else
+ {
+ // Let the base class do H.263 selection
+ CMusEngMceSession::DoCodecSelectionL( aVideoStream );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::DoCodecSelectionL()" )
+ }
+
+// -----------------------------------------------------------------------------
+// If incoming session does not have valid structure and cannot be reconstructed
+// as such, session is rejected automatically.
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::IncomingSession(
+ CMceInSession* aSession,
+ TMceTransactionDataContainer* aContainer )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::IncomingSession(...)" )
+
+ if ( !aContainer ||
+ ( iSession &&
+ iSession->State() != CMceSession::ETerminated ) )
+ {
+ // We already have one session ongoing, or do not have container.
+ // Reject new session.
+ Reject( *aSession );
+ delete aSession;
+ aSession = NULL;
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::IncomingSession( \
+ session already exists. New session rejected and deleted. )" )
+ return;
+ }
+
+ delete iSession; // possibly existing terminated session
+ iSession = aSession;
+
+ if ( iOperatorVariant )
+ {
+ ParseAssertedIdentity( aContainer );
+ }
+
+ // Reset variable defined for preparing for multiple state changes to
+ // EProceeding. This might happen if we set 100rel to be required.
+ iRingLCalled = EFalse;
+
+ // If preparing fails, session setup with VS2.2 will fail later
+ TRAP_IGNORE( PrepareToRequire100RelL( aContainer ) )
+
+ TRAPD( error, CompleteSessionStructureL() );
+
+ if ( error != KErrNone )
+ {
+ Reject( *InSession() );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::IncomingSession()" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::IncomingUpdate(
+ CMceSession& aOrigSession,
+ CMceInSession* aUpdatedSession,
+ TMceTransactionDataContainer* aContainer )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::IncomingUpdate(...)" )
+
+ if ( iSession &&
+ iSession == &aOrigSession )
+ {
+ // Old session is useless from now on
+ delete iSession;
+ iSession = aUpdatedSession;
+
+ TRAPD( error, CompleteSessionStructureL() );
+
+ if ( error != KErrNone )
+ {
+ MUS_LOG( "mus: [ENGINE] Cannot handle update, reject" )
+ Reject( *aUpdatedSession );
+ }
+ }
+ else
+ {
+ // Cannot handle, forward to a base class
+ CMusEngMceSession::IncomingUpdate( aOrigSession,
+ aUpdatedSession,
+ aContainer );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::IncomingUpdate(...)" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::StreamStateChanged( CMceMediaStream& aStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::StreamStateChanged()" )
+
+ MUS_ENG_LOG_STREAM_STATE( aStream )
+
+ if ( !iSession )
+ {
+ return;
+ }
+
+ if ( aStream.Type() == KMceVideo &&
+ aStream.Source() &&
+ aStream.Source()->Type() == KMceRTPSource )
+ {
+ if ( aStream.State() == CMceMediaStream::EBuffering )
+ {
+ iBuffered = ETrue;
+ InformObserverAboutPlayerStateChange( iRemoteVideoPlayer );
+ }
+ else if ( aStream.State() == CMceMediaStream::EStreaming )
+ {
+ ReceivingStarted();
+ }
+ else
+ {
+ // Cannot handle, forward to CMusEngMceSession
+ CMusEngMceSession::StreamStateChanged( aStream );
+ }
+ }
+ else
+ {
+ // Cannot handle, forward to CMusEngMceSession
+ CMusEngMceSession::StreamStateChanged( aStream );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::StreamStateChanged()" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMceInSession* CMusEngReceiveSession::InSession()
+ {
+ return static_cast<CMceInSession*>(iSession);
+ }
+
+// -----------------------------------------------------------------------------
+// Check if incoming session is originated from VideoSharing 2.2 client,
+// which sends PRACK for 180 Ringing whether it is required or not. In
+// order to let MCE handle the PRACK correctly, force 180 Ringing to be
+// sent reliably.
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::PrepareToRequire100RelL(
+ TMceTransactionDataContainer* aContainer)
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::PrepareToRequire100RelL()" )
+
+ __ASSERT_ALWAYS( aContainer, User::Leave( KErrArgument ) );
+
+ CDesC8Array* headers = aContainer->GetHeaders();
+ CleanupStack::PushL( headers );
+
+ if ( headers )
+ {
+ for ( TInt i = 0; i < headers->Count(); ++i )
+ {
+ if ( headers->MdcaPoint(i).FindF( KMusEngSwisIdentifier() ) !=
+ KErrNotFound )
+ {
+ iSession->SetModifierL( KMce100Rel, KMce100RelRequired );
+ MUS_LOG( "mus: [ENGINE] Forced to require 100rel" )
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( headers );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::PrepareToRequire100RelL()" )
+ }
+
+// -----------------------------------------------------------------------------
+// Check that incoming session contains only incoming video and audio
+// streams. All the other streams will be removed. If there is no
+// display sinks and speakers, they will be created.
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::CompleteSessionStructureL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::CompleteSessionStructureL()" )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ // Force bandwidth line usage in sdp as it is mandatory
+ // at MT side based on GSMA VS specification IR.74. Bandwidth is set to
+ // session or to media level based on sender's way of usage. If other end
+ // is not using bandwidth attribute at all, media level is preferred.
+ SetSessionSdpLinesL( *iSession, ETrue );
+
+ CMceStreamBundle* localBundle =
+ CMceStreamBundle::NewLC( CMceStreamBundle::ELS );
+
+ const RPointerArray<CMceMediaStream>& streams = iSession->Streams();
+
+ CMceMediaStream* videoInStream = NULL;
+
+ for( TInt i = 0; i < streams.Count(); ++i )
+ {
+ if ( MusEngMceUtils::IsVideoInStream( *streams[i] ) &&
+ !videoInStream )
+ {
+ videoInStream = streams[i];
+
+ // Disable possible opposite stream to indicate that sendrecv is
+ // not allowed.
+ if ( streams[i]->BoundStream() )
+ {
+ MusEngMceUtils::DisableStreamL( streams[i]->BoundStreamL() );
+ }
+ }
+ else if ( streams[i]->BoundStream() &&
+ MusEngMceUtils::IsVideoInStream( streams[i]->BoundStreamL() ) &&
+ !videoInStream )
+ {
+ videoInStream = &streams[i]->BoundStreamL();
+
+ // Disable opposite stream to indicate that sendrecv is not allowed.
+ MusEngMceUtils::DisableStreamL( *streams[i] );
+ }
+ else if ( MusEngMceUtils::IsAudioInStream( *streams[i] ) &&
+ !iOperatorVariant )
+ {
+ MusEngMceUtils::AddSpeakerL( *streams[i] );
+
+ localBundle->AddStreamL( *streams[i] );
+
+ // Disable possible opposite stream to indicate that sendrecv is
+ // not allowed.
+ if ( streams[i]->BoundStream() )
+ {
+ MusEngMceUtils::DisableStreamL( streams[i]->BoundStreamL() );
+ }
+ }
+ else if ( streams[i]->BoundStream() &&
+ MusEngMceUtils::IsAudioInStream( streams[i]->BoundStreamL() ) &&
+ !iOperatorVariant )
+ {
+ MusEngMceUtils::AddSpeakerL( streams[i]->BoundStreamL() );
+
+ localBundle->AddStreamL( streams[i]->BoundStreamL() );
+
+ // Disable opposite stream to indicate that sendrecv is not allowed.
+ MusEngMceUtils::DisableStreamL( *streams[i] );
+ }
+ else
+ {
+ // We remove stream because either it
+ // 1. Is not and does not contain incoming video or audio, or
+ // 2. We already have one incoming video stream or
+ // 3. Stream is audio and we run operator variant where audio is
+ // not allowed.
+ iSession->RemoveStreamL( *streams[i] );
+
+ // Since succesfull removal of a stream has decreased the amount
+ // of streams in array by one, we have to modify the index
+ --i;
+ }
+ }
+
+ if ( videoInStream )
+ {
+ SetMediaSdpLinesL( *videoInStream, ETrue );
+
+ // Complete stream
+ MusEngMceUtils::AddDisplayL( *videoInStream, *iManager, Rect() );
+
+ static_cast<CMceRtpSource*>(videoInStream->Source())->UpdateL(
+ KMusEngJitterBufferLength,
+ KMusEngJitterBufferTreshold );
+
+ localBundle->AddStreamL( *videoInStream );
+ }
+ else
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // Next line is to cause a leave if there were no incoming video streams
+ MusEngMceUtils::GetVideoInStreamL( *iSession );
+
+ // Destroy bundle if it is not needed or transfer ownership
+ if ( localBundle->Streams().Count() > 1 )
+ {
+ iSession->AddBundleL( localBundle );
+ CleanupStack::Pop( localBundle );
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy( localBundle );
+ }
+
+ AdjustStreamsAndCodecsL();
+
+ iSession->UpdateL();
+
+ // Now session state is right to adjust volume
+ SetSpeakerVolumeL( LcVolumeL() );
+
+ iSipProfileHandler->CreateProfileL( iSession->Profile() );
+
+ iRemoteVideoPlayer->SetMceSession( iSession );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::CompleteSessionStructureL()" )
+ }
+
+// -----------------------------------------------------------------------------
+// Parse P-Asserted-Identity Header
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::ParseAssertedIdentity(
+ TMceTransactionDataContainer* aContainer )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::AssertedIdentity()" )
+
+ iIdentity.Zero();
+
+ if ( !aContainer )
+ {
+ MUS_LOG( "mus: [ENGINE] Data container is NULL" )
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AssertedIdentity()" )
+ return;
+ }
+
+ CDesC8Array* headers = aContainer->GetHeaders();
+
+ if ( !headers )
+ {
+ MUS_LOG( "mus: [ENGINE] No headers" )
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AssertedIdentity()" )
+ return;
+ }
+
+ TBool found = EFalse;
+ TInt length = 0;
+ for( TInt i = 0; i < headers->Count() && !found; ++i )
+ {
+ TPtrC8 header = (*headers)[i];
+ if ( header.FindF( KMusEngAssertedIdentity ) != KErrNotFound )
+ {
+ TInt pos = 0;
+ // check for sip url, continue if found because maybe tel url exists
+ if ( ( pos = header.FindF( KMusEngSipPrefix ) ) != KErrNotFound )
+ {
+ TInt atPos = header.FindF( KMusEngAtSign );
+ length = atPos - pos - KMusEngSipPrefix().Length();
+ if ( length > 0 && length <= KMaxUriLength )
+ {
+ iIdentity.Copy(
+ header.Mid( pos + KMusEngSipPrefix().Length(), length ) );
+ }
+ }
+ // check for tel url, exit if found
+ else if ( ( pos = header.FindF( KMusEngTelPrefix ) ) != KErrNotFound )
+ {
+ length = header.Length() - pos - KMusEngTelPrefix().Length();
+ if ( length > 0 && length <= KMaxUriLength )
+ {
+ iIdentity.Copy( header.Right( length ) );
+ }
+ found = ETrue;
+ }
+ }
+ }
+
+ // remove ending '>' if exists and whitespaces
+ if ( iIdentity.Length() > 0 )
+ {
+ iIdentity.Trim();
+ if ( iIdentity.Find( KMusEngBiggerSign ) == iIdentity.Length() - 1 )
+ {
+ iIdentity = iIdentity.Left( iIdentity.Length() - 1 );
+ iIdentity.Trim();
+ }
+ }
+
+ delete headers;
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AssertedIdentity()" )
+ }
+
+// -----------------------------------------------------------------------------
+// RTP Inactivity timeout event
+// Once inactivity timeout occurs, state change is notified and receiving
+// and buffering statuses are cleared. That is safe to do as once receiving
+// again continues for real, buffering and streaming events will occur always
+// sequentially. If buffering status would not be cleared, some unwanted
+// sreaming events would be passed towards client when it disables/enables
+// display sink of remote stream while inactivity timer has expired.
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::InactivityTimeout( CMceMediaStream& aStream,
+ CMceRtpSource& /*aSource*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngTwoWayRecvSession::InactivityTimeout()" )
+
+ if ( aStream.Type() == KMceVideo && iReceiving )
+ {
+ iReceiving = EFalse;
+ iBuffered = EFalse;
+ InformObserverAboutPlayerStateChange( iRemoteVideoPlayer );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngTwoWayRecvSession::InactivityTimeout()" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngReceiveSession::ReceivingStarted()
+ {
+ if ( iSession && iBuffered )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::ReceivingStarted()" )
+
+ TInt err = MusEngMceUtils::EnableInactivityTimer(
+ *iSession, iReceivingInactivityTimeout );
+
+ if ( err != KErrNone )
+ {
+ MUS_LOG1("mus: [ENGINE] ReceivingStarted failed %d", err)
+ InformObserverAboutSessionFailure( err );
+ }
+ else
+ {
+ iReceiving = ETrue;
+ InformObserverAboutPlayerStateChange( iRemoteVideoPlayer );
+ InformUiProviderAboutReceivingStart();
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::ReceivingStarted()" )
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMusEngReceiveSession::IsDisplayActive()
+ {
+ return ( IsDisplayEnabled() && iReceiving );
+ }
+// End of File