--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsharing/mmshengine/src/musengmcesession.cpp Thu Dec 17 08:44:37 2009 +0200
@@ -0,0 +1,1458 @@
+/*
+* Copyright (c) 2005 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
+#include "mussettings.h"
+#include "musengmcesession.h"
+#include "musengsessiondurationtimer.h"
+#include "musengsessionobserver.h"
+#include "musengmceutils.h"
+#include "musuid.hrh"
+#include "musenglogger.h"
+#include "musengclipsessionobserver.h"
+#include "mussipprofilehandler.h"
+
+// SYSTEM
+#include <mcedefs.h>
+#include <mcemanager.h>
+#include <mceinsession.h>
+#include <mcevideostream.h>
+#include <mceaudiostream.h>
+#include <mcertpsink.h>
+#include <mcedisplaysink.h>
+#include <mcespeakersink.h>
+#include <mcefilesource.h>
+#include <mcertpsource.h>
+#include <mceaudiocodec.h>
+#include <mcevideocodec.h>
+#include <AudioPreference.h>
+
+
+const TInt KMusEngTimerInterval = 1000000; // 1 second
+const TInt KMusEngRtcpInactivityThreshold = 20; // seconds
+const TInt KMusEngArrayGranularity3 = 3;
+
+const TInt KMusEngSipReasonCodeOk = 200;
+const TInt KMusEngSipReasonCodeBusyHere = 486;
+_LIT8( KMusEngSipReasonPhraseBusyHere, "Busy Here" );
+_LIT8( KMusEngSipReasonPhraseBusy, "Busy" );
+
+const TUint KMusEngDedicatedVideoPort = 49152;
+const TUint KMusEngDedicatedAudioPort = 57344;
+
+#define MUS_CODEC_ARR_CONST_CAST( codecArr ) \
+( const_cast< RPointerArray< CMceVideoCodec >& >( codecArr ) )
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMusEngMceSession::~CMusEngMceSession()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::~CMusEngMceSession()" )
+ delete iSipProfileHandler;
+ delete iSession;
+ delete iManager;
+ delete iUpdateTimer;
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::~CMusEngMceSession()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::TerminateL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::TerminateL()" )
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+ iSession->TerminateL();
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::TerminateL()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// Returns estabilished session time. If not established return
+// value is < 0
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TTimeIntervalSeconds CMusEngMceSession::GetSessionTime() const
+ {
+ if ( iSession && iSession->State() == CMceSession::EEstablished )
+ {
+ TTime time;
+ TTimeIntervalSeconds seconds;
+ time.HomeTime();
+
+ time.SecondsFrom( iStartTime, seconds );
+
+ return seconds;
+ }
+
+ return TTimeIntervalSeconds( KErrNotReady );
+
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMusEngMceSession::ConnectionActive() const
+ {
+ if ( iSession )
+ {
+ return iSession->ConnectionActive();
+ }
+ return EFalse;
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMusEngMceSession::ContainsAudioL()
+ {
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ for ( TInt i = 0; i < iSession->Streams().Count(); ++i )
+ {
+ if ( iSession->Streams()[i]->Type() == KMceAudio )
+ {
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMusEngMceSession::IsMutedL()
+ {
+ // Precondition checked in ContainsAudioL
+
+ if ( ContainsAudioL() && !iExplicitlyMuted )
+ {
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMusEngMceSession::TDisplayOrientation
+ CMusEngMceSession::OrientationL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::RotationL()" )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ CMceDisplaySink* display = MusEngMceUtils::GetDisplayL( *iSession );
+
+ TDisplayOrientation displayOrientation;
+ CMceDisplaySink::TRotation rotation( display->RotationL() );
+
+ MUS_LOG1( "mus: [ENGINE] MCE rotation is %d", rotation )
+
+ if ( rotation == CMceDisplaySink::ENone )
+ {
+ displayOrientation = CMusEngMceSession::EPortrait;
+ }
+ else
+ {
+ displayOrientation = CMusEngMceSession::ELandscape;
+ }
+
+ MUS_LOG1( "mus: [ENGINE] <- CMusEngMceSession::RotationL() %d",
+ displayOrientation )
+
+ return displayOrientation;
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::SetOrientationL(
+ TDisplayOrientation aOrientation )
+ {
+ MUS_LOG1( "mus: [ENGINE] -> CMusEngMceSession::SetOrientationL() %d",
+ aOrientation )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ CMceDisplaySink* display = MusEngMceUtils::GetDisplayL( *iSession );
+
+ if ( aOrientation == EPortrait )
+ {
+ display->SetRotationL( CMceDisplaySink::ENone );
+ }
+ else
+ {
+ display->SetRotationL( CMceDisplaySink::EClockwise90Degree );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::SetOrientationL()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::VolumeUpL()
+ {
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ CMusEngSession::VolumeUpL();
+
+ SetSpeakerVolumeL( VolumeL() );
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::VolumeDownL()
+ {
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ CMusEngSession::VolumeDownL();
+
+ SetSpeakerVolumeL( VolumeL() );
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::SetVolumeL( TInt aVal )
+ {
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ CMusEngSession::SetVolumeL( aVal );
+
+ SetSpeakerVolumeL( VolumeL() );
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::EnableDisplayL( TBool aEnable )
+ {
+ MUS_LOG1( "mus: [ENGINE] -> CMusEngMceSession::EnableDisplay() %d",
+ aEnable )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ CMceDisplaySink* display = MusEngMceUtils::GetDisplayL( *iSession );
+
+ if ( aEnable )
+ {
+ if ( !display->IsEnabled() )
+ {
+ display->EnableL();
+ MUS_LOG( " Display enabled" )
+ if ( !iExplicitlyMuted )
+ {
+ // Since speaker is not explicitly muted, but disabled as
+ // a consequence of disabling bundled display, it must be
+ // unmuted.
+ DoMuteSpeakerL( EFalse );
+ MUS_LOG( " Bundled speaker enabled" )
+ }
+ }
+ else
+ {
+ MUS_LOG( " Display already enabled, ignore" )
+ }
+ }
+ else
+ {
+ if ( display->IsEnabled() )
+ {
+ display->DisableL();
+ MUS_LOG( " Display disabled" )
+ if ( !iExplicitlyMuted )
+ {
+ // Speaker will not be explicitly muted, but disabled as
+ // a consequence of disabling bundled display.
+ DoMuteSpeakerL( ETrue );
+ MUS_LOG( " Bundled speaker disabled" )
+ }
+ }
+ else
+ {
+ MUS_LOG( " Display already disabled, ignore" )
+ }
+ }
+
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::EnableDisplay()")
+ }
+
+
+// -----------------------------------------------------------------------------
+// Mutes playback of sended audio streams. Audio data is still streamed.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::MuteL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::Mute()" )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ DoMuteSpeakerL( ETrue );
+
+ // Mark speaker as explicitly muted instead of muted because of disabling
+ // bundled display
+ iExplicitlyMuted = ETrue;
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::Mute()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// Unmutes playback of sended audio streams.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMusEngMceSession::UnmuteL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::Unmute()" )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ DoMuteSpeakerL( EFalse );
+
+ // Mark speaker as explicitly unmuted instead of unmuted because of
+ // enabling bundled display
+ iExplicitlyMuted = EFalse;
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::Unmute()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+CMusEngMceSession::CMusEngMceSession( const TRect& aRect,
+ MMusEngSessionObserver& aSessionObserver )
+ : CMusEngSession( aRect ),
+ iSessionObserver( aSessionObserver ),
+ iSecondsFromLastRtcpReport ( 0 ),
+ // Although speaker is constructed as muted, it is not explicitly muted
+ iExplicitlyMuted( EFalse )
+ {
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::ConstructL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::ConstructL()" )
+ CMusEngSession::ConstructL(); // Base class ConstructL -first
+
+ // Creating new MCE Manager and set all needed observers to this class.
+ iManager = CMceManager::NewL( TUid::Uid( KMusUiUid ),
+ &iTransactionDataContainer );
+
+ iManager->SetSessionObserver( this );
+ iManager->SetInSessionObserver( this );
+ iManager->SetMediaObserver( this );
+ iManager->SetRtpObserver( this );
+
+ // Check if operator specific behavior is expected
+ iOperatorVariant = ( MultimediaSharingSettings::OperatorVariantSettingL() ==
+ MusSettingsKeys::EOperatorSpecific );
+
+ // Update timer initialization
+ iUpdateTimer = CMusEngSessionDurationTimer::NewL( *this );
+
+ iSipProfileHandler = CMusSipProfileHandler::NewL( *this );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::ConstructL()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::RectChangedL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::RectChangedL()" )
+
+ // If session is not yet created, do nothing
+ if ( iSession && iSession->State() != CMceSession::ETerminated )
+ {
+ // Rely on having just one display
+ CMceDisplaySink* display = MusEngMceUtils::GetDisplayL( *iSession );
+ display->SetDisplayRectL( Rect() );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::RectChangedL()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// Setting session level sdp lines. Bandwith attribute is always used in
+// operator variant mode and at receiver side (using force).
+// However, bandwidth attribute is preferred to be used at media level
+// (see SetMediaSdpLinesL method). It is set to session level only if other
+// side is using also session level bandwidth. Media level preference exists
+// because some other manufacturer's videosharing does not understand session
+// level bandwidth attribute.
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SetSessionSdpLinesL(
+ CMceSession& aSession,
+ TBool aForceBandwidthLine )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::SetSessionSdpLinesL()" )
+
+ MDesC8Array* oldSessionSdpLines = aSession.SessionSDPLinesL();
+ CleanupDeletePushL( oldSessionSdpLines );
+ TBool bandwidthAtSessionLevel( ContainsText( oldSessionSdpLines,
+ KMusEngSessionSdpLineBandwidthLine() ) );
+ CleanupStack::PopAndDestroy( oldSessionSdpLines );
+
+ CDesC8Array* newSessionSDPLines =
+ new ( ELeave ) CDesC8ArrayFlat( KMusEngArrayGranularity3 );
+ CleanupStack::PushL( newSessionSDPLines );
+
+ if ( iOperatorVariant )
+ {
+ newSessionSDPLines->AppendL( KMusEngSessionSdpLineApplication() );
+ newSessionSDPLines->AppendL( KMusEngSessionSdpLineType() );
+ }
+ else
+ {
+ newSessionSDPLines->AppendL( KMusEngSessionSdpLineXApplication() );
+ }
+
+ if ( bandwidthAtSessionLevel && ( iOperatorVariant || aForceBandwidthLine ) )
+ {
+ MUS_LOG( "mus: [ENGINE] setting bandwidth to session level" )
+ newSessionSDPLines->AppendL( KMusEngSessionSdpLineBandwidthField() );
+ }
+
+ aSession.SetSessionSDPLinesL( newSessionSDPLines );
+
+ CleanupStack::Pop( newSessionSDPLines );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::SetSessionSdpLinesL()" )
+ }
+
+// -----------------------------------------------------------------------------
+// Setting media level sdp lines. Bandwidth is not set to media level if
+// it is used already at session level.
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SetMediaSdpLinesL(
+ CMceMediaStream& aStream,
+ TBool aForceBandwidthLine )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::SetMediaSdpLinesL()" )
+
+ MDesC8Array* sessionSdpLines = aStream.Session()->SessionSDPLinesL();
+ CleanupDeletePushL( sessionSdpLines );
+ TBool bandwidthAtSessionLevel( ContainsText( sessionSdpLines,
+ KMusEngSessionSdpLineBandwidthLine() ) );
+ CleanupStack::PopAndDestroy( sessionSdpLines );
+
+ if ( !bandwidthAtSessionLevel && ( iOperatorVariant || aForceBandwidthLine ) )
+ {
+ MUS_LOG( "mus: [ENGINE] setting bandwidth to media level" )
+
+ //Add media attribute to sdp
+ const TInt KMusMediaSdpLinesGranularity = 1;
+ CDesC8Array* headers =
+ new ( ELeave ) CDesC8ArrayFlat( KMusMediaSdpLinesGranularity );
+ CleanupStack::PushL( headers );
+ headers->AppendL( KMusEngSessionSdpLineBandwidthField() );
+ aStream.SetMediaAttributeLinesL( headers );
+ CleanupStack::Pop( headers );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::SetMediaSdpLinesL()" )
+ }
+
+// -----------------------------------------------------------------------------
+// Changes volume of all speaker sinks in the session structure
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SetSpeakerVolumeL( TInt aNewVolume )
+ {
+ TInt sessionState = iSession->State();
+
+ if ( sessionState != CMceSession::EIdle &&
+ sessionState != CMceSession::EIncoming )
+ {
+ for ( TInt i = 0; i < iSession->Streams().Count(); ++i )
+ {
+ CMceSpeakerSink* speaker =
+ MusEngMceUtils::GetSpeaker( *( iSession->Streams()[i] ) );
+
+ if ( speaker &&
+ aNewVolume >= 1 &&
+ aNewVolume <= KMusEngMaxVolume )
+ {
+ // MCE might have different scale for volume than MUS
+ // so adjust MUS volume to MCE scale before setting.
+ TInt maxVol = speaker->MaxVolumeL();
+ TInt setVol = maxVol * aNewVolume / KMusEngMaxVolume;
+ setVol = Max(setVol, 1);
+
+ MUS_LOG2(
+"mus: [ENGINE] -> CMusEngMceSession::SetSpeakerVolumeL() orig:%d, adjusted:%d",
+aNewVolume, setVol );
+
+ if ( setVol <= maxVol )
+ {
+ speaker->SetVolumeL( setVol );
+ }
+ }
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::AdjustStreamsAndCodecsL()
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::AdjustStreamsAndCodecsL" )
+
+ __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) );
+
+ const RPointerArray<CMceMediaStream>& streams = iSession->Streams();
+
+ for ( TInt i = 0; i < streams.Count(); ++i )
+ {
+ if ( streams[i]->Type() == KMceVideo )
+ {
+ CMceVideoStream* videoStream =
+ static_cast<CMceVideoStream*>( streams[i] );
+
+ AdjustVideoStreamL( *videoStream );
+
+ if ( videoStream->BoundStream() )
+ {
+ AdjustVideoStreamL( static_cast<CMceVideoStream&>
+ ( videoStream->BoundStreamL() ) );
+ }
+
+ }
+ else // audio
+ {
+ CMceAudioStream* audioStream =
+ static_cast<CMceAudioStream*>( streams[i] );
+
+ AdjustAudioStreamL( *audioStream );
+
+ if ( audioStream->BoundStream() )
+ {
+ AdjustAudioStreamL( static_cast<CMceAudioStream&>
+ ( audioStream->BoundStreamL() ) );
+ }
+
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::AdjustStreamsAndCodecsL" )
+
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::AdjustVideoStreamL( CMceVideoStream& aVideoStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::AdjustVideoStreamL" )
+
+ aVideoStream.SetLocalMediaPortL( KMusEngDedicatedVideoPort );
+
+ DoCodecSelectionL( aVideoStream );
+
+ const RPointerArray<CMceVideoCodec>& codecs = aVideoStream.Codecs();
+
+ for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
+ {
+ AdjustVideoCodecL( *codecs[codecIndex] );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::AdjustVideoStreamL" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::AdjustAudioStreamL( CMceAudioStream& aAudioStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::AdjustAudioStreamL" )
+
+ aAudioStream.SetLocalMediaPortL( KMusEngDedicatedAudioPort );
+
+ const RPointerArray<CMceAudioCodec> codecs = aAudioStream.Codecs();
+
+ for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
+ {
+ AdjustAudioCodecL( *codecs[codecIndex] );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::AdjustAudioStreamL" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// Calls CMceInSession::RejectL() inside TRAP_IGNORE
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::Reject( CMceInSession& aSession,
+ const TDesC8& aReason,
+ TUint32 aCode )
+ {
+ if ( aCode != 0 || aReason != KNullDesC8() )
+ {
+ TRAP_IGNORE( aSession.RejectL( aReason, aCode, NULL, NULL, NULL ) )
+ }
+ else
+ {
+ if ( iOperatorVariant )
+ {
+ // In operator variant, session is rejected with 486 instead of 603.
+ // Also the reason phrase is supposed to be "Busy".
+ TRAP_IGNORE( aSession.RejectL( KMusEngSipReasonPhraseBusy(),
+ KMusEngSipReasonCodeBusyHere ) )
+ }
+ else
+ {
+ // Normal case
+ TRAP_IGNORE( aSession.RejectL() )
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// By default rejects all incoming sessions immediately without notifying UI
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::IncomingSession(
+ CMceInSession* aSession,
+ TMceTransactionDataContainer* /*aContainer*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::IncomingSession()" )
+
+ Reject( *aSession,
+ KMusEngSipReasonPhraseBusyHere(),
+ KMusEngSipReasonCodeBusyHere );
+
+ delete aSession;
+ aSession = NULL;
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::IncomingSession()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// By default rejects all incoming updates immediately without notifying UI
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::IncomingUpdate(
+ CMceSession& aOrigSession,
+ CMceInSession* aUpdatedSession,
+ TMceTransactionDataContainer* /*aContainer*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::IncomingUpdate()" )
+
+ if ( iSession &&
+ iSession == &aOrigSession )
+ {
+ // Old session is useless from now on
+ delete iSession;
+ iSession = aUpdatedSession;
+ MUS_LOG( "mus: [ENGINE] Unexpected update, reject" )
+ Reject( *aUpdatedSession );
+ }
+ else
+ {
+ // This should never happen
+ MUS_LOG( "mus: [ENGINE] Unknown update, reject and delete" )
+ Reject( *aUpdatedSession );
+ delete aUpdatedSession;
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::IncomingUpdate()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::StreamStateChanged( CMceMediaStream& aStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::StreamStateChanged()" )
+
+ if ( !iSession )
+ {
+ return; // We cannot do anything
+ }
+
+ MUS_ENG_LOG_STREAM_STATE( aStream )
+
+ switch ( aStream.State() )
+ {
+ case CMceMediaStream::EUninitialized: // Stream is created
+ {
+ // Unexpected state change
+ break;
+ }
+ case CMceMediaStream::EInitialized: // Stream is initialized
+ {
+ // Should be handled in sibling classes if needed
+ break;
+ }
+ case CMceMediaStream::EBuffering: // Stream is buffering
+ {
+ // Should be handled in sibling classes if needed
+ break;
+ }
+ case CMceMediaStream::EIdle: // Stream is not receiving RTP
+ {
+ // NOP
+ break;
+ }
+ case CMceMediaStream::EStreaming: // Stream is streaming
+ {
+ // If streaming stream is complete video out- or instream, inform UI
+ if ( aStream.Type() == KMceVideo &&
+ aStream.Source() &&
+ aStream.Sinks().Count() >= 0 &&
+ ( aStream.Source()->Type() == KMceRTPSource ||
+ aStream.Sinks()[0]->Type() == KMceRTPSink ) )
+ {
+ iSessionObserver.StreamStreaming();
+ }
+ break;
+ }
+ case CMceMediaStream::EDisabled: // Stream is explicitly disabled
+ {
+ break;
+ }
+ case CMceMediaStream::ENoResources:
+ {
+ // Stream has no needed resources to stream
+ break;
+ }
+ case CMceMediaStream::ETranscodingRequired:
+ {
+ // Stream requires non-realtime transcoding
+ // Should be handled in sibling classes
+ break;
+ }
+ case CMceMediaStream::ETranscoding:
+ {
+ // Stream is transcoding in non-realtime
+ // Should be handled in sibling classes
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::StreamStateChanged()" )
+
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::StreamStateChanged( CMceMediaStream& aStream,
+ CMceMediaSource& /*aSource*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::StreamStateChanged( src )" )
+ // Use default logic
+ StreamStateChanged( aStream );
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::StreamStateChanged( src )" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::StreamStateChanged( CMceMediaStream& aStream,
+ CMceMediaSink& /*aSink*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::StreamStateChanged( sink )" )
+ // Use default logic
+ StreamStateChanged( aStream );
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::StreamStateChanged( sink )" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SessionStateChanged(
+ CMceSession& aSession,
+ TMceTransactionDataContainer* aContainer )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::SessionStateChanged()" )
+
+ if ( !aContainer )
+ {
+ // Container should never be NULL, but if it is, handle as
+ // internal error
+ iSessionObserver.SessionFailed();
+ return;
+ }
+
+ // This is the only point to get statuscode and reasonphrase. With this call
+ // they are zeroed and thus cannot be got anymore.
+ TInt statusCode = aContainer->GetStatusCode();
+ HBufC8* reasonPhrase = aContainer->GetReasonPhrase();
+
+ if ( reasonPhrase )
+ {
+ HandleSessionStateChanged( aSession, statusCode, *reasonPhrase );
+ delete reasonPhrase ;
+ }
+ else
+ {
+ HandleSessionStateChanged( aSession, statusCode, KNullDesC8() );
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::SessionStateChanged()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SessionConnectionStateChanged( CMceSession& aSession,
+ TBool aActive )
+ {
+ MUS_LOG1( "mus: [ENGINE] CMusEngMceSession::\
+ SessionConnectionStateChanged() active = %b", aActive )
+
+ if ( iSession && iSession == &aSession )
+ {
+ if ( !aActive )
+ {
+ MUS_LOG( "mus: [ENGINE] CMusEngMceSession::\
+ SessionConnectionStateChanged: Notify observer" )
+ iSessionObserver.SessionConnectionLost();
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::\
+ SessionConnectionStateChanged()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+
+#if ( defined( _DEBUG ) && !defined( UNIT_TESTING ) )
+void CMusEngMceSession::Failed( CMceSession& aSession, TInt aError )
+#else
+void CMusEngMceSession::Failed( CMceSession& aSession, TInt /*aError*/ )
+#endif
+ {
+ MUS_LOG1( "mus: [ENGINE] -> CMusEngMceSession::Failed() error #%d",
+ aError )
+
+ if ( iSession && iSession == &aSession )
+ {
+ MUS_LOG( "mus: [ENGINE] CMusEngMceSession::Failed: Notify observer" )
+ iSessionObserver.SessionFailed();
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::Failed()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::UpdateFailed(
+ CMceSession& aSession,
+ TMceTransactionDataContainer* aContainer )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::UpdateFailed()" )
+
+ if ( !aContainer )
+ {
+ // Container should never be NULL, but if it is, handle as
+ // internal error
+ iSessionObserver.SessionFailed();
+ return;
+ }
+
+ if ( iSession && iSession == &aSession )
+ {
+ MUS_LOG( "mus: [ENGINE] CMusEngMceSession::UpdateFailed: \
+ Notify observer" )
+ iSessionObserver.SessionFailed();
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::UpdateFailed()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SRReceived( CMceSession& aSession,
+ CMceMediaStream& aStream)
+ {
+ // No logging because of amount of reports
+ if ( iSession &&
+ iSession == &aSession )
+ {
+ for ( TInt i = 0; i < iSession->Streams().Count(); ++i )
+ {
+ if ( &aStream == iSession->Streams()[i] )
+ {
+ iSecondsFromLastRtcpReport = 0;
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::RRReceived( CMceSession& aSession,
+ CMceMediaStream& aStream)
+ {
+ // No logging because of amount of reports
+
+ if ( iSession &&
+ iSession == &aSession )
+ {
+ for ( TInt i = 0; i < iSession->Streams().Count(); ++i )
+ {
+ if ( &aStream == iSession->Streams()[i] )
+ {
+ iSecondsFromLastRtcpReport = 0;
+ }
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::InactivityTimeout( CMceMediaStream& aStream,
+ CMceRtpSource& /*aSource*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::InactivityTimeout()" )
+ // This function may be deprecated in future and after that similar
+ // functionality can be obtained by observing stream state EIdle.
+ // Anyway it does not work yet and until then, informing UI about
+ // RTP inactivity is done in this function.
+
+ if ( aStream.Type() == KMceVideo )
+ {
+ iSessionObserver.StreamIdle();
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::InactivityTimeout()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SsrcAdded( CMceMediaStream& /*aStream*/,
+ CMceRtpSource& /*aSource*/,
+ TUint /*aSsrc*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] CMusEngMceSession::SsrcAdded( ... )" )
+ // NOP, We are not at all interested about SSRCs
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::SsrcRemoved( CMceMediaStream& /*aStream*/,
+ CMceRtpSource& /*aSource*/,
+ TUint /*aSsrc*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] CMusEngMceSession::SsrcRemoved(... )" )
+ // NOP, We are not at all interested about SSRCs
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+TBool CMusEngMceSession::IsRoamingBetweenAPsAllowed()
+ {
+ TBool allowed( ETrue );
+ if ( iSession &&
+ iSession->State() != CMceSession::EIdle &&
+ iSession->State() != CMceSession::ETerminated )
+ {
+ allowed = EFalse;
+ }
+ return allowed;
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::HandleSessionStateChanged( CMceSession& aSession,
+ TInt aStatusCode,
+ const TDesC8& aReasonPhrase )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::HandleSessionStateChanged" )
+
+ MUS_ENG_LOG_SESSION_STATE_AND_STATUS( aSession, aStatusCode, aReasonPhrase )
+
+ if ( iSession && iSession == &aSession )
+ {
+ switch ( aSession.State() )
+ {
+ case CMceSession::EIdle:
+ {
+ MUS_LOG( "mus: [ENGINE] Unexpected asynchronous \
+ state transition, consider session as failed." )
+ iSessionObserver.SessionFailed();
+ break;
+ }
+ case CMceSession::EOffering :
+ {
+ break;
+ }
+ case CMceSession::EIncoming:
+ {
+ MUS_LOG( "mus: [ENGINE] Unexpected asynchronous \
+ state transition, consider session as failed." )
+ iSessionObserver.SessionFailed();
+ break;
+ }
+ case CMceSession::EReserving :
+ {
+ // UpdateL called to incoming session during
+ // session establishment
+ break;
+ }
+ case CMceSession::EAnswering : // Answering an incoming call
+ {
+ break;
+ }
+ case CMceSession::EProceeding :
+ {
+ break;
+ }
+ case CMceSession::EEstablished:
+ {
+ // Check that session timer is not already running, which is
+ // the case when refreshing the session with session timer
+ if ( !iUpdateTimer->IsActive() )
+ {
+ iStartTime.HomeTime(); // Start counting session duration
+ iUpdateTimer->Start( KMusEngTimerInterval );
+ iSessionObserver.SessionEstablished();
+ }
+
+ break;
+ }
+ case CMceSession::ECancelling:
+ {
+ // MCE has for some reason started to cancel session
+ break;
+ }
+ case CMceSession::ETerminating:
+ {
+ // MCE has for some reason started to terminate session
+ break;
+ }
+ case CMceSession::ETerminated:
+ {
+ HandleTermination( aStatusCode, aReasonPhrase );
+ break;
+ }
+ default:
+ {
+ MUS_LOG( "mus: [ENGINE] CMusEngMceSession::SessionStateChanged(), \
+ default case" )
+ break;
+ }
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::HandleSessionStateChanged" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// This function should be called only if sibling classes cannot handle
+// termination reason by themselves.
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::HandleTermination( TInt aStatusCode,
+ const TDesC8& /*aReasonPhrase*/ )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::HandleTermination()" )
+
+ iSipProfileHandler->RefreshIapAvailabilities();
+
+ switch ( aStatusCode )
+ {
+ case 0:
+ {
+ // Normal session termination or session by another end.
+ iSessionObserver.SessionTerminated();
+ break;
+ }
+ case KMusEngSipReasonCodeOk:
+ {
+ // Normal session termination by this end: We have sent BYE
+ // and now received 200 OK to it.
+ iSessionObserver.SessionTerminated();
+ break;
+ }
+ default:
+ {
+ // Termination reason cannot be determined, handle as internal
+ // error.
+ iSessionObserver.SessionFailed();
+ break;
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::HandleTermination()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::AdjustVideoCodecL()" )
+
+ aVideoCodec.SetMMFPriorityL( KAudioPrioritySwisPlayback );
+ aVideoCodec.SetMMFPriorityPreferenceL( KAudioPrefSwisPlayback );
+ MUS_LOG( "mus: [ENGINE] Video MMF priority and preference set" )
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::AdjustVideoCodecL()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// 1. Sets MMF audio priority and preference
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::AdjustAudioCodecL( CMceAudioCodec& aAudioCodec )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::AdjustAudioCodecL()" )
+
+ aAudioCodec.SetMMFPriorityL( KAudioPrioritySwisPlayback );
+ aAudioCodec.SetMMFPriorityPreferenceL( KAudioPrefSwisPlayback );
+ MUS_LOG( "mus: [ENGINE] Audio MMF priority and preference set" )
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::AdjustAudioCodecL()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+// Remove multiples of H.263 codec, prefer H263-2000 over H263-1998.
+// Additionally select just the one with best quality from selected mode.
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::DoCodecSelectionL( CMceVideoStream& aVideoStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::DoCodecSelectionL()" )
+
+ const RPointerArray<CMceVideoCodec>& codecs = aVideoStream.Codecs();
+ TBool codecModeBasedRemovalNeeded( EFalse );
+ // Label:H263
+ TBool H2632000CodecFound( EFalse );
+ TBool H2631998CodecFound( EFalse );
+ for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex )
+ {
+ const CMceVideoCodec& currentCodec = *codecs[codecIndex];
+ if ( currentCodec.SdpName().FindF( KMceSDPNameH263 ) != KErrNotFound )
+ {
+ if ( !currentCodec.SdpName().CompareF( KMceSDPNameH2632000 ) )
+ {
+ H2632000CodecFound = ETrue;
+ codecModeBasedRemovalNeeded = H2631998CodecFound;
+ }
+ else if ( !currentCodec.SdpName().CompareF( KMceSDPNameH2631998 ) )
+ {
+ H2631998CodecFound = ETrue;
+ codecModeBasedRemovalNeeded = H2632000CodecFound;
+ }
+ else
+ {
+ // NOP
+ }
+ }
+ }
+ if ( codecModeBasedRemovalNeeded )
+ {
+ DoCodecModeBasedRemovalL( aVideoStream );
+ }
+
+ const RPointerArray<CMceVideoCodec>& codecs2 = aVideoStream.Codecs();
+ const CMceVideoCodec* bestBitrateCodec( NULL );
+ for ( TInt codecIndex = 0; codecIndex < codecs2.Count(); ++codecIndex )
+ {
+ const CMceVideoCodec& currentCodec = *codecs2[codecIndex];
+ if ( currentCodec.SdpName().FindF( KMceSDPNameH263 ) != KErrNotFound )
+ {
+ if ( !bestBitrateCodec ||
+ currentCodec.MaxBitRate() > bestBitrateCodec->MaxBitRate() )
+ {
+ bestBitrateCodec = ¤tCodec;
+ }
+ }
+ }
+ if ( bestBitrateCodec != NULL )
+ {
+ DoBitrateBasedRemovalL( aVideoStream, *bestBitrateCodec );
+ }
+
+ /* Codec removal based on configuration */
+ DoCodecConfigurationBasedRemovalL( aVideoStream );
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::DoCodecSelectionL()" )
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::UpdateTimerEvent()
+ {
+ // Update timer is used also to detect RTCP inactivity
+ ++iSecondsFromLastRtcpReport;
+
+ iSessionObserver.SessionTimeChanged( GetSessionTime() );
+
+ if ( iSecondsFromLastRtcpReport >= KMusEngRtcpInactivityThreshold )
+ {
+ iSessionObserver.InactivityTimeout();
+ // Disable calling multiple times by reseting timer
+ iSecondsFromLastRtcpReport = 0;
+ }
+
+ iUpdateTimer->Start( KMusEngTimerInterval );
+ }
+
+
+// -----------------------------------------------------------------------------
+// Enables or disables all the speaker sinks of all the audio streams
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::DoMuteSpeakerL( TBool aMute )
+ {
+ MUS_LOG1( "mus: [ENGINE] -> CMusEngMceSession::MuteL( %d )", aMute )
+
+ const RPointerArray<CMceMediaStream>& streams = iSession->Streams();
+
+ for ( TInt i = 0; i < streams.Count(); ++i )
+ {
+ CMceSpeakerSink* speaker =
+ MusEngMceUtils::GetSpeaker( *streams[i] );
+
+ if ( speaker )
+ {
+ if( aMute )
+ {
+ if ( speaker->IsEnabled() )
+ {
+ speaker->DisableL();
+ }
+ else
+ {
+ MUS_LOG( "mus: [ENGINE] Speaker already muted, NOP" )
+ }
+ }
+ else
+ {
+ if ( !speaker->IsEnabled() )
+ {
+ speaker->EnableL();
+ }
+ else
+ {
+ MUS_LOG( "mus: [ENGINE] Speaker already unmuted, NOP" )
+ }
+ }
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::MuteL( TBool aMute )" )
+ }
+
+// -----------------------------------------------------------------------------
+// Checks if some of array items contains specific text
+// (exact match not required)
+// -----------------------------------------------------------------------------
+//
+TBool CMusEngMceSession::ContainsText( MDesC8Array* aArray, const TDesC8& aItem )
+ {
+ for ( TInt i = 0; aArray && i < aArray->MdcaCount(); i++ )
+ {
+ if ( aArray->MdcaPoint( i ).FindF( aItem ) != KErrNotFound )
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::DoBitrateBasedRemovalL(
+ CMceVideoStream& aVideoStream,
+ const CMceVideoCodec& aBestBitrateVideoCodec )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::DoBitrateBasedRemovalL()" )
+
+ RPointerArray<CMceVideoCodec>& codecs =
+ MUS_CODEC_ARR_CONST_CAST( aVideoStream.Codecs() );
+
+ TInt codecIndex = 0;
+ while ( codecIndex < codecs.Count() )
+ {
+ CMceVideoCodec& currentCodec = *codecs[codecIndex++];
+ if ( currentCodec.SdpName().FindF( KMceSDPNameH263 ) != KErrNotFound &&
+ ¤tCodec != &aBestBitrateVideoCodec )
+ {
+ MUS_LOG( "mus: [ENGINE] removing" )
+ aVideoStream.RemoveCodecL( currentCodec );
+ codecs = MUS_CODEC_ARR_CONST_CAST( aVideoStream.Codecs() );
+ codecIndex = 0;
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::DoBitrateBasedRemovalL()" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::DoCodecModeBasedRemovalL( CMceVideoStream& aVideoStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::DoCodecModeBasedRemovalL()" )
+
+ RPointerArray<CMceVideoCodec>& codecs =
+ MUS_CODEC_ARR_CONST_CAST( aVideoStream.Codecs() );
+
+ TInt codecIndex = 0;
+ while ( codecIndex < codecs.Count() )
+ {
+ CMceVideoCodec& currentCodec = *codecs[codecIndex++];
+ if ( !currentCodec.SdpName().CompareF( KMceSDPNameH2631998 ) )
+ {
+ MUS_LOG( "mus: [ENGINE] removing" )
+ aVideoStream.RemoveCodecL( currentCodec );
+ codecs = MUS_CODEC_ARR_CONST_CAST( aVideoStream.Codecs() );
+ codecIndex = 0;
+ }
+ }
+
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::DoCodecModeBasedRemovalL()" )
+ }
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CMusEngMceSession::DoCodecConfigurationBasedRemovalL( CMceVideoStream& aVideoStream )
+ {
+ MUS_LOG( "mus: [ENGINE] -> CMusEngMceSession::DoCodecConfigurationBasedRemovalL()" )
+ if( MultimediaSharingSettings::IsAvcDisabled())
+ {
+ RPointerArray<CMceVideoCodec>& codecs =
+ MUS_CODEC_ARR_CONST_CAST( aVideoStream.Codecs() );
+ TInt codecIndex = 0;
+ while ( codecIndex < codecs.Count() )
+ {
+ CMceVideoCodec& currentCodec = *codecs[codecIndex++];
+ if ( !currentCodec.SdpName().CompareF( KMceSDPNameH264 ) )
+ {
+ MUS_LOG( "mus: [ENGINE] - Removing avc from supported codec list" )
+ aVideoStream.RemoveCodecL( currentCodec );
+ codecs = MUS_CODEC_ARR_CONST_CAST( aVideoStream.Codecs() );
+ codecIndex = 0;
+ }
+ }
+ }
+ MUS_LOG( "mus: [ENGINE] <- CMusEngMceSession::DoCodecConfigurationBasedRemovalL()" )
+ }