multimediacommscontroller/mmccvideosourcesink/src/mccvideosinkimpl.cpp
changeset 0 1bce908db942
child 8 f9c1f5f9ce0b
child 19 f58ead8cf73c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccvideosourcesink/src/mccvideosinkimpl.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1951 @@
+/*
+* Copyright (c) 2003 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:    
+*
+*/
+
+
+
+
+// INCLUDES FILES
+#include <w32std.h>
+#include <AudioPreference.h> 
+#include <mmcccodecinformationfactory.h>
+#include <mmcccodecinformation.h>
+#include "mccvideosinkimpl.h"
+#include "mmcccodech263.h"
+#include "mccvideosourcesinklogs.h"
+#include "mccinternalevents.h"
+#include "CXPSPacketSink.h"
+#include "mmcccodecamr.h"
+#include "mccvideosinkuser.h"
+#include "mccdef.h"
+#include "mccredrawhandler.h"
+#include "mccinternaldef.h"
+#include <videoplayer2.h>
+
+// CONSTANTS
+
+
+_LIT8( KMccSdpInboundStart,
+"v=0\r\n\
+o=- 63327476467155000 63327476467155000 IN IP4 0.0.0.0\r\n\
+s=-\r\n\
+c=IN IP4 0.0.0.0\r\n\
+t=0 0\r\n" );
+
+_LIT8( KMccSdpInboundAudio,
+"m=audio 25001 RTP/AVP %d\r\n\
+a=rtpmap:%d %S/8000\r\n\
+a=ptime:%d\r\n\
+a=maxptime:%d\r\n\
+a=fmtp:%d octet-align=%d; mode-set=%S\r\n" );
+
+_LIT8( KMccSdpInboundVideo,
+"m=video 25002 RTP/AVP %d\r\n\
+a=rtpmap:%d %S/90000\r\n\
+a=fmtp:%d %S\r\n\
+a=XpsPyldBufSize:integer;%d\r\n\
+a=FrameWidth:integer;%d\r\n\
+a=FrameHeight:integer;%d\r\n" );
+
+_LIT8( KMccSdpInboundPreroll, "a=DisableMinPrerollCheck:integer;1\r\n\
+a=Preroll:integer;%d\r\n" );
+
+_LIT8( KMccSdpInboundDisableVideoClock, "a=DisableVideoClock:integer;1\r\n" );
+
+
+_LIT( KMccWindowGroupName,"32MccVideoWindow" );
+_LIT( KMccHelixSource,"MccDataSource%d");
+// NOTE: filepath separator changed to unix style because of problem at Helix side
+_LIT( KMccPacketSource, "file://c:/notinuse.xps?XPSServer=%S" );
+
+// MACROS
+
+#define MCC_BITRATE_IN_MASK( bitratemask, bitrate ) bitrate == ( bitratemask & bitrate )
+
+// ================= MEMBER FUNCTIONS =======================
+
+
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkImpl::CMccVideoSinkImpl( TUint32 aEndpointId ) :
+    iEndpointId( aEndpointId ),
+    iVolumeAdaptation( 0 ),
+    iPreroll( 0 ), 
+    iPrerollSet( EFalse )
+    {
+    	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::CMccVideoSinkImpl" ) 
+    	
+    iSettings.iVideoFrameRate = KMccDefaultVideoFrameRate;
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::ConstructL( const TMccVideoSinkSetting& aSettings )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL" ) 
+    
+    iSettings = aSettings;
+    
+    SetVideoFrameRate( aSettings.iVideoFrameRate );
+
+    const TInt KMccVideoSinkMaxSdpLen = 800;
+    iSdp = HBufC8::NewL( KMccVideoSinkMaxSdpLen );
+
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL, init Helix" ) 
+	iPacketSink = CXPSPacketSink::New();
+	__ASSERT_ALWAYS(iPacketSink, User::Leave( KErrNotReady ) );
+	
+	const TInt KMaxTUintAsDesLen = 12;
+	iServerName  = 
+	    HBufC::NewL( KMccHelixSource().Length() + KMaxTUintAsDesLen );
+	iServerName->Des().AppendFormat( KMccHelixSource, (TUint32)this );
+	
+	iPacketSink->Init( *iServerName, this );
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL, init Helix complete" ) 
+    
+    iSearchTermUser = CMccVideoSinkUser::NewL( 
+        NULL, KNullUid, 0, iSettings.iVideoFrameRate, *iPacketSink );
+  
+    User::LeaveIfError( iRwSession.Connect() );
+	
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL connected to ws" )
+    __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window pos:", 
+                                  iSettings.iLocation.iX, " ", iSettings.iLocation.iY ) 
+    __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window size (w,h):", 
+                                  iSettings.iSize.iWidth, " ", iSettings.iSize.iHeight ) 
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal pos:", 
+                                  iSettings.iWindowOrdinalPosition )
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal priority:", 
+                                  iSettings.iWindowOrdinalPriority )
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl rotation:", 
+                                  iSettings.iRotation )
+    
+	// Create window group
+	TInt groupId = iRwSession.GetFocusWindowGroup();
+    iRwGroup = new (ELeave) RWindowGroup( iRwSession );	
+    
+	User::LeaveIfError( iRwGroup->Construct( groupId, EFalse ) );	
+    iRwGroup->SetName( KMccWindowGroupName );
+    
+    // TBD: use also iWindowOrdinalPriority
+    iRwGroup->SetOrdinalPosition( iSettings.iWindowOrdinalPosition );
+         
+    // Create screen device
+	iDev = new (ELeave) CWsScreenDevice( iRwSession );
+	User::LeaveIfError( iDev->Construct( iSettings.iDeviceIndex ) ); 
+	
+	// Create window
+	iRw = new (ELeave) RWindow( iRwSession );
+    
+    User::LeaveIfError( iRw->Construct( *iRwGroup, (TUint32)iRw ) );
+
+    iRw->SetPosition( iSettings.iLocation );
+    iRw->SetSize( iSettings.iSize );
+    
+    iRw->SetOrdinalPosition( iSettings.iWindowOrdinalPosition );
+        
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: creating graphics context ..." )
+    User::LeaveIfError( iDev->CreateContext( iGc ) );
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: graphics context created!" )
+    
+      
+    iRw->Activate();
+    
+    iRwSession.Flush();
+    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: creating redraw handler" )
+    
+    iRedrawHandler = CMccRedrawHandler::NewL( iRwSession, *iRw, *iGc );
+    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: created redraw handler" )
+      
+    // Videoplayer needs to be created last, otherwise destruction
+    // order causes problems
+    iVideoPlayer = CVideoPlayerUtility2::NewL( 
+            *this,
+            iSettings.iPriority.iPriority,
+            iSettings.iPriority.iPref );
+
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: created CVideoPlayerUtility2" )
+    
+    // Wait for MvpuoOpenComplete before adding display window
+    
+    RegisterForVideoLoadingNotification( *this );
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkImpl* CMccVideoSinkImpl::NewL( 
+    const TMccVideoSinkSetting& aSettings,
+    TUint32 aEndpointId )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::NewL" ) 
+    CMccVideoSinkImpl* self = new ( ELeave ) CMccVideoSinkImpl( aEndpointId );
+
+    CleanupStack::PushL( self );
+
+    self->ConstructL( aSettings );
+
+    CleanupStack::Pop( self ); // self 
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkImpl::~CMccVideoSinkImpl()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::~CMccVideoSinkImpl" )
+    
+    SetCurrentUser( NULL );
+    
+    delete iSdp;
+    
+    if ( iPacketSink )
+        {
+        for ( TInt i = 0; i < iUsers.Count(); i++ )
+            {
+            iPacketSink->StreamEnd( iUsers[ i ]->iStreamId );
+            }
+        iPacketSink->Reset();
+        }
+
+    	
+	iUsers.ResetAndDestroy();
+	   
+    delete iPacketSink;
+    
+    if( iVideoPlayer )
+		{
+		Stop();
+		iVideoPlayer->Close();	
+		}
+		
+	delete iVideoPlayer;
+	
+	delete iRedrawHandler;
+	
+	delete iGc;
+	delete iDev;
+
+    delete iRw;
+    delete iRwGroup;	
+	iRwSession.Close();
+
+	delete iServerName;
+	
+	delete iSearchTermUser;
+	
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::~CMccVideoSinkImpl, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SinkThreadLogon()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::SinkThreadLogon( MAsyncEventHandler& aEventHandler )
+	{
+	// Give zero stream id at beginning, correct id is set later
+	TRAPD( err, AddUserL( aEventHandler ) );
+	return err;
+	}
+   
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SinkThreadLogoff()
+// ---------------------------------------------------------------------------
+//     
+TBool CMccVideoSinkImpl::SinkThreadLogoff()
+	{
+	if ( iCurrentUser )
+	    {
+	    TUint streamId( 0 );
+	    if ( ResolveStreamId( iCurrentUser, streamId ) == KErrNone )
+	        {
+            RemoveVideoSinkUser( iCurrentUser, streamId );
+	        }
+	    iCurrentUser = NULL;
+	    }	
+	return ( iUsers.Count() == 0 );
+	}
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetCurrentUser()
+// ---------------------------------------------------------------------------
+// 	
+void CMccVideoSinkImpl::SetCurrentUser( MAsyncEventHandler* aEventHandler )
+    {
+    iCurrentUser = aEventHandler;
+    }
+        
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::OpenL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::OpenL()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL" )
+    if ( SetVideoSinkState( EOpening ) )
+        {
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL, doing setup" )
+        
+        RemoteSetupL();
+        
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL, opening" )
+        __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+        __ASSERT_ALWAYS( iPacketSink, User::Leave( KErrArgument ) );
+
+        const TUid KUidController = { 0x101F8514 };  //RNAVCONTROLLER.DLL
+    
+        HBufC* url = 
+            HBufC::NewLC( KMccPacketSource().Length() + iServerName->Length() );
+        url->Des().AppendFormat( KMccPacketSource, &*iServerName );
+        iVideoPlayer->OpenUrlL( *url, 0, KNullDesC8, KUidController );
+        CleanupStack::PopAndDestroy( url );
+        }
+    else if ( iState == EOpened )
+        {
+        // If already opened, prepare can be called immediately
+        Prepare();
+        }
+    else
+        {
+        __V_SOURCESINK_CONTROLL( 
+            "CMccVideoSinkImpl::OpenL, waiting for opening" )
+        }
+        
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Prepare()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Prepare()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Prepare" )
+    
+    if ( SetVideoSinkState( EPrepared ) && iVideoPlayer )
+        {
+	    iVideoPlayer->Prepare();
+	    
+	    // Wait for async completion	
+	    }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RemoteSetupL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::RemoteSetupL()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RemoteSetup" )
+    
+    __ASSERT_ALWAYS( iVideoPlayer && iPacketSink, User::Leave( KErrNotReady ) );
+
+    ConstructSdpL();
+    
+    __V_SOURCESINK_CONTROLL_INT1( "Sending SDP to helix, len= ", iSdp->Length() )
+
+    TUint numStreams( iUsers.Count() );
+    __V_SOURCESINK_CONTROLL_INT1( 
+        "CMccVideoSinkImpl::RemoteSetup, num streams:", numStreams );
+                                 
+    User::LeaveIfError( iPacketSink->SetSessionDescription( *iSdp, numStreams ) );
+    
+    for ( TInt i = 0;  i < iUsers.Count(); i++ )
+        {
+        CMccVideoSinkUser& entry = *iUsers[ i ];
+        
+        __V_SOURCESINK_CONTROLL_INT1( 
+            "CMccVideoSinkImpl::RemoteSetup, stream:", entry.iStreamId );
+        __V_SOURCESINK_CONTROLL_INT1( 
+            "CMccVideoSinkImpl::RemoteSetup, queuesize defined:", 
+            entry.IsQueueSizeDefined() );
+        __V_SOURCESINK_CONTROLL_INT1( 
+            "CMccVideoSinkImpl::RemoteSetup, queuesize:", entry.QueueSize() );
+        User::LeaveIfError( 
+            iPacketSink->ConfigStream( entry.iStreamId, entry.QueueSize() ) );
+        }
+
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RemoteSetup, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::StartL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::StartL()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::StartL" )
+    
+    if ( SetVideoSinkState( EPlaying ) )
+        { 
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::StartL, playing" )
+
+        CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+        
+        UpdateSettingsL( iSettings, ETrue );
+
+        DoPlay();
+        
+        // No need to wait any async completion
+        if ( IsStartedOnce( userEntry ) )
+            {
+            SendStreamEventToClient( KMccStreamResumed, iCurrentUser );
+            }
+        else
+            {
+            iRedrawHandler->BlackDrawingL( ETrue );
+            SendStreamEventToClient( KMccStreamStarted, iCurrentUser );
+            SetStartedOnce( userEntry, ETrue );
+            }   
+        }
+  
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::StartL, exit" )
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Stop()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Stop()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Stop" )
+    
+    TBool playerOpened( IsPlayerOpened() );
+    
+    if ( SetVideoSinkState( EStopped ) && iVideoPlayer ) 
+	    {
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Stop, hiding window disabled" )
+        
+        // Stopping the player before opening has completed can cause crash
+        if ( playerOpened )
+            {
+            iVideoPlayer->Stop();
+            }
+	    
+	    // No need to wait any async completion
+	    SendStreamEventToClient( KMccStreamStopped, iCurrentUser );
+	    
+	    CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+	    SetStartedOnce( userEntry, EFalse );
+	    
+	    DoPauseForUser( userEntry );
+	    }
+	    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Stop, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Pause()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::PauseL()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::PauseL" )
+    __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+    
+    if ( SetVideoSinkState( EPaused ) )
+        {
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::PauseL, pausing" )
+
+        DoPauseL();
+        
+        DoResetL();
+        
+        // No need to wait any async completion
+        SendStreamEventToClient( KMccStreamPaused, iCurrentUser );
+        }
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::PauseL, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Close()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Close()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Close" )
+    if ( iVideoPlayer ) 
+	    {
+	    iVideoPlayer->Close();
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetDisplayWindowL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetDisplayWindowL( 
+    RWsSession& aWs, 
+    CWsScreenDevice& aScreenDevice,
+    RWindow& aWindow )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetDisplayWindowL" ) 
+    __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+    iVideoPlayer->RemoveDisplayWindow( aWindow );
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetDisplayWindowL, removed old" )
+    iVideoPlayer->AddDisplayWindowL( aWs, aScreenDevice, aWindow );
+    
+    iVideoPlayer->SetAutoScaleL( aWindow, EAutoScaleBestFit );
+    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetDisplayWindowL, added new" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Priority()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Priority( TInt& aPriority, 
+                                  TInt& aPreference )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Priority" ) 
+    
+    aPriority = iSettings.iPriority.iPriority;
+    aPreference = iSettings.iPriority.iPref;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetPriority()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetPriority( TInt aPriority, 
+                                     TInt aPreference )
+    {
+    if ( iSettings.iPriority.iPriority != aPriority ||
+         iSettings.iPriority.iPref != aPreference )
+        {
+        __V_SOURCESINK_CONTROLL_INT1( 
+            "CMccVideoSinkImpl::SetPriority, mmf priority:", aPriority )
+        __V_SOURCESINK_CONTROLL_INT1( 
+        "CMccVideoSinkImpl::SetPriority, mmf preference:", aPreference )
+    
+        iSettings.iPriority.iPriority = aPriority;
+        iSettings.iPriority.iPref = aPreference;
+            
+        if ( IsPlayerOpened() && iVideoPlayer )
+            {
+            __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetPriority, setting" )
+            
+
+            TRAPD( err, iVideoPlayer->SetPriorityL( iSettings.iPriority.iPriority, 
+                                                    iSettings.iPriority.iPref ) );
+            if ( err )
+                {
+                __V_SOURCESINK_CONTROLL_INT1( 
+                    "CMccVideoSinkImpl::SetPriority, failed with err:", err )
+                err++;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Volume()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::Volume() const 
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Volume" )
+    
+    if ( iVideoPlayer )
+	    {
+	    return iVideoPlayer->Volume();	
+	    }
+    else
+	    {
+	    return KErrArgument;	    	
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MaxVolume()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::MaxVolume() const 
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MaxVolume" )
+
+    if ( iVideoPlayer )
+	    {
+	    return iVideoPlayer->MaxVolume();
+	    }
+    else
+	    {
+	    return KErrArgument;
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetVolumeL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetVolumeL( TInt aVolume )
+    {
+    __V_SOURCESINK_CONTROLL_INT1( 
+        "CMccVideoSinkImpl::SetVolumeL, vol:", aVolume )
+    __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+    
+    iVolume = aVolume;
+    
+    if ( iVolumeAdaptation == 0 && iMccMaxVolume != 0 && IsPlayerOpened() )
+        {
+        TInt playerMaxVolume = iVideoPlayer->MaxVolume();
+        
+        __V_SOURCESINK_CONTROLL_INT1( 
+            "CMccVideoSinkImpl::SetVolumeL, player max volume:", 
+            playerMaxVolume )
+        
+        iVolumeAdaptation = TReal( playerMaxVolume ) / iMccMaxVolume;
+        
+        __V_SOURCESINK_CONTROLL_REAL( 
+            "CMccVideoSinkImpl::SetVolumeL, vol adapt:", iVolumeAdaptation )
+        }
+    
+    if ( iVolumeAdaptation != 0 )
+        {
+        aVolume = (TInt) ( iVolume * iVolumeAdaptation );
+        
+        __V_SOURCESINK_CONTROLL_INT1( 
+            "CMccVideoSinkImpl::SetVolumeL, after adaptation:", aVolume )
+    
+        iVideoPlayer->SetVolumeL( aVolume );
+        }
+
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetVolumeL, exit" )
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetMaxVolume()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetMaxVolume( TInt aMaxVolume )
+    {
+     __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::SetMaxVolume, max vol:", aMaxVolume )
+     
+    iMccMaxVolume = aMaxVolume;
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Balance()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::Balance() const
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Balance" )
+    
+    if ( iVideoPlayer ) 
+	    {
+	   	return iVideoPlayer->Balance();
+	    }
+	else
+		{
+		return KErrArgument;
+		}
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetBalanceL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetBalanceL( TInt aBalance )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetBalanceL" )
+    __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+    iVideoPlayer->SetBalanceL(aBalance);
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RegisterForVideoLoadingNotification()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::RegisterForVideoLoadingNotification(
+                                     MVideoLoadingObserver& aCallback )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RegisterForVideoLoadingNotification" )
+    
+    if ( iVideoPlayer )
+	    {
+	    iVideoPlayer->RegisterForVideoLoadingNotification( aCallback );
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Version()
+// ---------------------------------------------------------------------------
+//
+TVersion CMccVideoSinkImpl::Version() const
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Version" )
+    return TVersion(0, 1, 0);
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FormatVideoSDPInfoL
+// ---------------------------------------------------------------------------
+// 	
+void CMccVideoSinkImpl::FormatVideoSDPInfoL( const TMccCodecInfo& aVideoCodec )
+	{
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::FormatVideoSDPInfoL" )
+    
+    // Update payload type since it might not have been provided at
+    // initialization phase
+    iSettings.iVideoPayloadType = aVideoCodec.iPayloadType;
+    
+    CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+    __ASSERT_ALWAYS( userEntry, User::Leave( KErrNotFound ) );
+    userEntry->iMediaType = KUidMediaTypeVideo;
+    userEntry->SetCodecInfoL( aVideoCodec );
+	}
+	
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FormatAudioSDPInfoL
+// ---------------------------------------------------------------------------
+// 	
+void CMccVideoSinkImpl::FormatAudioSDPInfoL( const TMccCodecInfo& aAudioCodec )
+	{
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::FormatAudioSDPInfoL" )
+    
+    // Update payload type since it might not have been provided at
+    // initialization phase
+    iSettings.iAudioPayloadType = aAudioCodec.iPayloadType;
+    
+    CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+    __ASSERT_ALWAYS( userEntry, User::Leave( KErrNotFound ) );
+    userEntry->iMediaType = KUidMediaTypeAudio;
+    userEntry->SetCodecInfoL( aAudioCodec );
+	}
+
+// ---------------------------------------------------------------------------
+// void CMccVideoSinkImpl::EmptyBufferL
+// 
+// ---------------------------------------------------------------------------
+//     
+void CMccVideoSinkImpl::EmptyBufferL( CMMFBuffer* aBuffer, 
+		                          MDataSource* /*aSupplier*/,
+		                          TMediaId aMediaId,
+		                          TRtpRecvHeader& aHeaderInfo )	
+	{
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::EmptyBufferL" )
+    
+    if ( iState != EPlaying )
+        {
+        __V_SOURCESINK_CONTROLL( 
+            "CMccVideoSinkImpl::EmptyBufferL, not playing, ignore buffer!" )
+        return;
+        }
+    
+    TInt index = FindVideoSinkUserEntryByMediaType( aMediaId.iMediaType );
+    __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) );
+    
+    CMccVideoSinkUser& user = *iUsers[ index ];
+	
+	__V_SOURCESINK_CONTROLL_INT1( 
+	    "CMccVideoSinkImpl::EmptyBufferL, streamId:", user.iStreamId )
+	
+	CMMFDataBuffer* buf = static_cast<CMMFDataBuffer*>( aBuffer ); 
+	
+	TInt dataSize = buf->Data().Length();
+	__V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::EmptyBufferL, data size:", 
+    	                          dataSize )		
+
+	if ( AnalyzeTimeStampL( user, aHeaderInfo ) &&
+	     user.PacketOverflowState() != CMccVideoSinkUser::EOccured && 
+	     dataSize >= KMccMinPacketSize )
+		{
+		iRedrawHandler->BlackDrawingL( EFalse );
+		
+    	__V_SOURCESINK_CONTROLL( 
+    	    "CMccVideoSinkImpl::EmptyBufferL, sending packet to helix" )		
+      
+        CMccVideoJitterBuffer::TMccPacketBufferingStatus bufferingStatus =
+            user.EnqueueL( aHeaderInfo, buf->Data() );
+        
+        if ( bufferingStatus == CMccVideoJitterBuffer::EPlaying )
+    	    {
+    	    DoMvloLoadingComplete( ETrue );
+    	    }
+        else
+            {
+            DoMvloLoadingStarted( ETrue );
+            }
+    	    
+        iNumPacketsEnqueued++;
+		}
+	else
+		{
+		__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::EmptyBufferL, packet dropped" )		
+		}
+
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::EmptyBufferL, exit" )
+	}
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::UpdateSettingsL() 
+// ---------------------------------------------------------------------------
+//	
+void CMccVideoSinkImpl::UpdateSettingsL( 
+    const TMccVideoSinkSetting& aSettings,
+    TBool aForceUpdate )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::UpdateSettingsL" )
+    
+    __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrNotReady ) );
+    
+    if ( aForceUpdate ||
+         iSettings.iWindowOrdinalPosition != aSettings.iWindowOrdinalPosition ||
+         iSettings.iWindowOrdinalPriority != aSettings.iWindowOrdinalPriority ||
+         iSettings.iLocation != aSettings.iLocation ||
+         iSettings.iSize != aSettings.iSize ||
+         iSettings.iDeviceIndex != aSettings.iDeviceIndex ||
+         iSettings.iRotation != aSettings.iRotation )
+        {
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::UpdateSettingsL, settings changed" )
+        
+        __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window pos:", 
+                aSettings.iLocation.iX, " ", aSettings.iLocation.iY ) 
+        __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window size (w,h):", 
+                aSettings.iSize.iWidth, " ", aSettings.iSize.iHeight ) 
+        __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal pos:", 
+                aSettings.iWindowOrdinalPosition )
+        __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal priority:", 
+                aSettings.iWindowOrdinalPriority )
+        __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl rotation:", 
+                aSettings.iRotation )
+        
+        __ASSERT_ALWAYS( iRw && iRwGroup && iDev, User::Leave( KErrNotReady ) );
+        
+        // TBD: use also aSettings.iWindowOrdinalPriority
+        iRwGroup->SetOrdinalPosition( aSettings.iWindowOrdinalPosition );
+
+        iRw->SetPosition( aSettings.iLocation );
+        iRw->SetSize( aSettings.iSize );
+        iRw->SetOrdinalPosition( aSettings.iWindowOrdinalPosition );
+        
+        iRwSession.Flush();
+            
+        SetDisplayWindowL( iRwSession, *iDev, *iRw );
+        
+        SetRotationL( aSettings.iRotation, aForceUpdate );
+        
+        __V_SOURCESINK_CONTROLL( 
+            "CMccVideoSinkImpl::UpdateSettingsL, videoplyer updated" )
+        }
+    
+    // Store new settings
+    iSettings = aSettings;
+    
+    SetVideoFrameRate( aSettings.iVideoFrameRate );
+    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::UpdateSettingsL, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetCurrentSettings() 
+// ---------------------------------------------------------------------------
+//        
+void CMccVideoSinkImpl::GetCurrentSettings( TMccVideoSinkSetting& aSettings ) const
+    {
+    aSettings = iSettings;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RestorePacketSupply() 
+// ---------------------------------------------------------------------------
+//	
+void CMccVideoSinkImpl::RestorePacketSupply( TUint aStreamId )
+	{
+    __V_SOURCESINK_CONTROLL_INT1( 
+        "CMccVideoSinkImpl::RestorePacketSupply, streamId:", aStreamId )
+    iSearchTermUser->Set( 0, KNullUid, aStreamId );
+    TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+    TInt index = iUsers.Find( iSearchTermUser, comparison );
+    if ( index != KErrNotFound )
+        {
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RestorePacketSupply, found entry")
+        
+        iUsers[ index ]->SetPacketOverflow( CMccVideoSinkUser::ERecovered );
+        }
+
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RestorePacketSupply, exit" )	
+	}
+
+	
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvloLoadingStarted() 
+// ---------------------------------------------------------------------------
+//     
+void CMccVideoSinkImpl::MvloLoadingStarted() 
+	{
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MvloLoadingStarted" )
+	
+	DoMvloLoadingStarted();
+	}
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvloLoadingComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvloLoadingComplete()
+	{
+	__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MvloLoadingComplete" ) 
+
+    DoMvloLoadingComplete();
+	}
+	
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoOpenComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoOpenComplete( TInt aError )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MvpuoOpenComplete" ) 
+
+    if ( !aError && ( iState != EStopped ) )
+        {
+        iState = EOpened;
+        SetPriority( iSettings.iPriority.iPriority, iSettings.iPriority.iPref );
+        TRAP( aError, 
+            {
+            SetDisplayWindowL( iRwSession, *iDev, *iRw );
+            SetVolumeL( iVolume );
+            SetRotationL( iSettings.iRotation, ETrue );
+            } );
+            
+        if ( !aError )
+            {
+            Prepare();
+            }
+        }
+        
+    if ( aError )
+        {
+        __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoOpenComplete, error:", 
+                                      aError ) 
+                                      
+        SendStreamEventToAllClients( KMccStreamPrepared, aError );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoPrepareComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoPrepareComplete( TInt aError )
+    {
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoPrepareComplete(), \
+aError=", aError)
+	
+    SendStreamEventToAllClients( KMccStreamPrepared, aError );
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoFrameReady()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoFrameReady( CFbsBitmap& /*aFrame*/,
+#ifdef _DEBUG
+TInt aError
+#else
+TInt /*aError*/
+#endif
+ )
+    {
+#ifdef _DEBUG
+    
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoFrameReady, \
+aError=", aError )
+#endif
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoPlayComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoPlayComplete( TInt aError )
+    {
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoPlayComplete(), \
+aError=", aError)
+	
+	if ( aError )
+	    {
+        SendStreamEventToAllClients( KMccStreamStopped, aError );
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoEvent()
+// ---------------------------------------------------------------------------
+//	
+void CMccVideoSinkImpl::MvpuoEvent( const TMMFEvent& aEvent )
+    {
+    __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl::MvpuoEvent(), \
+aEvent.iEventType=", (TInt)aEvent.iEventType.iUid, "aEvent.iErrorCode", 
+    aEvent.iErrorCode)
+
+    if ( aEvent.iEventType == KMMFEventCategoryVideoPlayerGeneralError /*&&
+         aEvent.iErrorCode == KConnectionDone*/ )
+        {
+        // NOP
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetVideoSinkState
+// -----------------------------------------------------------------------------
+//    
+TBool CMccVideoSinkImpl::SetVideoSinkState( TMccVideoSinkState aState )
+    {
+    __V_SOURCESINK_CONTROLL_INT1( 
+        "CMccVideoSinkImpl::SetVideoSinkState, state:", aState )
+
+    TBool controlSink( iState != aState );
+    
+    TMccEventType eventType = KMccEventNone;
+    
+    switch ( aState )
+        {
+        case EOpening:
+            {
+            // No event to client
+            if ( AllUsersReady() )
+                {
+                iState = aState;
+                }
+            else
+                {
+                // All users not ready, don't start opening yet
+                controlSink = EFalse;
+                }
+            break;
+            }
+        case EOpened:
+            {
+            // No event to client
+            iState = aState;
+            break;
+            }
+        case EPrepared:
+            {
+            eventType = KMccStreamPrepared;
+            iState = aState;
+            break;
+            }
+        case EPlaying:
+            {
+            CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+            if ( IsStartedOnce( userEntry ) )
+                {
+                eventType = KMccStreamResumed;
+                }
+            else
+                {
+                eventType = KMccStreamStarted;
+                
+                if ( !controlSink )
+                    {
+                    SetStartedOnce( userEntry, ETrue );
+                    }
+                }
+            iState = aState;
+            break;
+            }
+        case EPaused:
+            {
+            eventType = KMccStreamPaused;
+            iState = aState;
+            break;
+            }
+        case EStopped:
+            {
+            eventType = KMccStreamStopped;
+            CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+            SetStartedOnce( userEntry, EFalse );
+            iState = aState;
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+        
+    if ( eventType != KMccEventNone && !controlSink )
+        {
+        SendStreamEventToClient( eventType, iCurrentUser );
+        }
+        
+    return controlSink;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::CreateModesetDesL()
+// -----------------------------------------------------------------------------
+// 
+HBufC8* CMccVideoSinkImpl::CreateModesetDesL( TUint aBitrateMask )
+    {
+    _LIT8( KModesetDelim, "," );
+    const TInt KModeValMaxLength = 2;
+    const TInt KModesMaxAmount = 8;
+    const TInt KModesetDelimLength = KModesetDelim().Length();
+    
+    HBufC8* modeset = 
+        HBufC8::NewL( KModesMaxAmount * 
+                    ( KModeValMaxLength + KModesetDelimLength ) );
+    
+    TPtr8 modesetPtr( modeset->Des() );
+    
+    TBool allModes( 
+        MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrateAll ) );
+                 
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate475 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode0 );
+        modesetPtr.Append( KModesetDelim );
+        }
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate515 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode1 );
+        modesetPtr.Append( KModesetDelim );
+        }
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate590 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode2 );
+        modesetPtr.Append( KModesetDelim );
+        }
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate670 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode3 );
+        modesetPtr.Append( KModesetDelim );
+        }
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate740 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode4 );
+        modesetPtr.Append( KModesetDelim );
+        }
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate795 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode5 );
+        modesetPtr.Append( KModesetDelim );
+        }
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate102 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode6 );
+        modesetPtr.Append( KModesetDelim );
+        }
+    if ( allModes || 
+         MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate122 ) )
+        {
+        modesetPtr.AppendNum( KAMRMode7 );
+        modesetPtr.Append( KModesetDelim );
+        }
+        
+    if ( modesetPtr.Length() - KModesetDelimLength >= 0 )
+        {
+        // Remove last delimiter
+        modesetPtr.Delete( modesetPtr.Length() - KModesetDelimLength, 
+                           KModesetDelimLength );
+        }
+        
+    return modeset;
+    }
+   
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::SendStreamEventToAllClients()
+// -----------------------------------------------------------------------------
+//	
+void CMccVideoSinkImpl::SendStreamEventToAllClients( 
+    TMccEventType aEventType,
+    TInt aError,
+    TBool aAllEndpoints )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SendStreamEventToAllClients" )
+    
+    for ( TInt i = 0; i < iUsers.Count(); i++ )
+        {
+        SendStreamEventToClient( aEventType, 
+                                 iUsers[ i ]->iAsyncEventHandler, 
+                                 aError, 
+                                 aAllEndpoints );
+        }
+    }
+       
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::SendStreamEventToClient()
+// -----------------------------------------------------------------------------
+//	
+void CMccVideoSinkImpl::SendStreamEventToClient( 
+    TMccEventType aEventType,
+    MAsyncEventHandler* aEventHandler,
+    TInt aError,
+    TBool aAllEndpoints )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SendStreamEventToClient" )
+    
+    if ( aEventHandler )
+	    {
+	    aEventType = aError ? KMccStreamError : aEventType;
+	    
+	    TUint32 endpointId = 
+	        aAllEndpoints ? 0 : iEndpointId;
+	        
+	    TMccEvent event( 0, 
+	                     0, 
+	                     0, 
+	                     endpointId, 
+	                     KMccEventCategoryStream, 
+	                     aEventType, 
+	                     aError, 
+	                     KNullDesC8 );
+
+		TMccInternalEvent internalEvent( KMccVideoSinkUid, 
+		                                 EMccInternalEventNone,
+		                                 event );
+		                         
+		aEventHandler->SendEventToClient( internalEvent );
+	    }
+	else
+		{
+		__V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SendStreamEventToClient, \
+		aEventHandler=NULL" )
+		}
+    }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResolveStreamId()
+// -----------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::ResolveStreamId( TMediaId aMediaId, TUint& aStreamId )
+    {
+    iSearchTermUser->Set( 0, aMediaId.iMediaType, 0 );
+    return FindStreamIdForVideoSinkUser( *iSearchTermUser, aStreamId );
+    }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResolveStreamId()
+// -----------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::ResolveStreamId( 
+    MAsyncEventHandler* aUser, 
+    TUint& aStreamId )
+    {
+    iSearchTermUser->Set( aUser, KNullUid, 0 );
+    return FindStreamIdForVideoSinkUser( *iSearchTermUser, aStreamId );
+    }   
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GenerateStreamId
+// ---------------------------------------------------------------------------
+//
+TUint CMccVideoSinkImpl::GenerateStreamId()
+    {
+    return iHelixStreamId++;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FindVideoSinkUserEntryByMediaType
+// ---------------------------------------------------------------------------
+//   
+TInt CMccVideoSinkImpl::FindVideoSinkUserEntryByMediaType( TUid aMediaType )
+    {
+    iSearchTermUser->Set( NULL, aMediaType, 0 );
+    TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+    return iUsers.Find( iSearchTermUser, comparison );
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FindStreamIdForVideoSinkUser
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::FindStreamIdForVideoSinkUser( 
+    CMccVideoSinkUser& aEntry,
+    TUint& aStreamId )
+    {
+    TInt err( KErrNotFound );
+
+    TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+    TInt index = iUsers.Find( &aEntry, comparison );
+    if ( index != KErrNotFound )
+        {
+        aStreamId = iUsers[ index ]->iStreamId;
+        err = KErrNone;
+        }
+    return err;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FindVideoSinkUserEntryForCurrent
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkUser* CMccVideoSinkImpl::FindVideoSinkUserEntryForCurrent()
+    {
+    iSearchTermUser->Set( iCurrentUser, KNullUid, 0 );
+    TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+    TInt index = iUsers.Find( iSearchTermUser, comparison );
+    if ( index != KErrNotFound )
+        {
+        return iUsers[ index ];
+        }
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RemoveVideoSinkUser
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::RemoveVideoSinkUser( 
+    MAsyncEventHandler* aUser, TUint aStreamId )
+    {
+    iSearchTermUser->Set( aUser, KNullUid, aStreamId );
+    TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+    TInt index = iUsers.Find( iSearchTermUser, comparison );
+    if ( index != KErrNotFound )
+        {
+        delete iUsers[ index ];
+        iUsers.Remove( index );
+        }
+    
+    // If there's no more users for this stream id, packet sink is notified
+    // about stream ending
+    iSearchTermUser->Set( NULL, KNullUid, aStreamId );
+    index = iUsers.Find( iSearchTermUser, comparison );
+    if ( iPacketSink && index == KErrNotFound )
+        {
+        iPacketSink->StreamEnd( aStreamId );
+        }
+    }
+        
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::VideoSinkUserMatch
+// ---------------------------------------------------------------------------
+//   
+TBool CMccVideoSinkImpl::VideoSinkUserMatch( 
+    const CMccVideoSinkUser& aUser1, 
+    const CMccVideoSinkUser& aUser2 )
+    {
+    // First argument is always the search term
+    
+    TBool match( EFalse );
+    if ( aUser1.iAsyncEventHandler )
+        {
+        match = ( aUser1.iAsyncEventHandler == aUser2.iAsyncEventHandler );
+        }
+    else if ( aUser1.iMediaType != KNullUid )
+        {
+        match = ( aUser1.iMediaType == aUser2.iMediaType );
+        }
+    else
+        {
+        match = ( aUser1.iStreamId == aUser2.iStreamId );
+        }
+    return match;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::ConstructSdpL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::ConstructSdpL()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructSdpL" )
+    
+    __ASSERT_ALWAYS( iSdp, User::Leave( KErrNotReady ) );
+
+    iSdp->Des().Copy( KMccSdpInboundStart );
+    
+    
+    // Check amount of mediatypes before constructing sdp as 
+    // sdp contents are affected on that information    
+    TBool multipleMediaTypes( MultipleMediaTypes() );
+    for ( TInt i = 0; i < iUsers.Count(); i++ )
+        {
+        iUsers[ i ]->SetMultipleMediaTypesL( multipleMediaTypes );
+        }
+        
+    HandleAudioSdpL();
+    
+    HandleVideoSdpL();
+    
+    __V_SOURCESINK_CONTROLL_STR8( "SDP:", *iSdp )
+    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructSdpL, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::HandleAudioSdpL
+// ---------------------------------------------------------------------------
+//    
+void CMccVideoSinkImpl::HandleAudioSdpL()
+    {
+    TInt audioEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeAudio );
+    if ( audioEntry == KErrNotFound )
+ 	    {
+ 	    __V_SOURCESINK_CONTROLL( 
+ 	        "CMccVideoSinkImpl::HandleAudioSdpL, no audio codec defined" )
+ 	    return;
+ 	    }	   
+ 	
+ 	// Set correct stream id   
+ 	iUsers[ audioEntry ]->iStreamId = GenerateStreamId();
+
+    // Form sdp from codec information
+    TMccCodecInfo& audioCodec = iUsers[ audioEntry ]->CodecInfo();
+    	
+    HBufC8* modeset = CreateModesetDesL( audioCodec.iBitrateMask );
+
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::HandleAudioSdpL, AudioPayloadType:", 
+                                  iSettings.iAudioPayloadType )
+	
+    iSdp->Des().AppendFormat( KMccSdpInboundAudio, 
+	                          iSettings.iAudioPayloadType,
+                    	      iSettings.iAudioPayloadType, 
+                              &audioCodec.iSdpName, 
+                              audioCodec.iPtime,
+                              audioCodec.iMaxPtime,
+    	                      iSettings.iAudioPayloadType,
+    	                      ( audioCodec.iCodecMode == KAmrCodecModeOctetAlign ),
+    	                      &*modeset );
+    
+    
+    delete modeset;
+    
+    iSdp->Des().AppendFormat( 
+        KMccSdpInboundPreroll, iUsers[ audioEntry ]->GetPreroll() );
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::HandleVideoSdpL
+// ---------------------------------------------------------------------------
+//     
+void CMccVideoSinkImpl::HandleVideoSdpL()
+    {
+    TUint streamId( 0 );
+    TBool firstUserHandled( EFalse );
+    for ( TInt i = 0; i < iUsers.Count(); i++ )
+        {
+        CMccVideoSinkUser& user = *iUsers[ i ];
+        if ( user.iMediaType == KUidMediaTypeVideo )
+            {
+            if ( !firstUserHandled )
+                {
+                streamId = GenerateStreamId();
+                
+                // Form sdp from codec information
+            	TMccCodecInfo& videoCodec = user.CodecInfo();
+         	
+                 // Helix uses width and height info for loading appropriate
+                 // video decoder
+                TInt frameWidth = KH263FrameWidth;
+                TInt frameHeight = KH263FrameHeight;
+            		
+            	__V_SOURCESINK_CONTROLL_INT1( 
+            	    "CMccVideoSinkImpl::HandleVideoSdpL, VideoPayloadType:", 
+            	    iSettings.iVideoPayloadType )
+
+                HBufC8* fmtp = GetFmtpLC( videoCodec );
+            	iSdp->Des().AppendFormat( KMccSdpInboundVideo, 
+            	                          iSettings.iVideoPayloadType,
+                                	      iSettings.iVideoPayloadType, 
+                                          &videoCodec.iSdpName, 
+                	                      iSettings.iVideoPayloadType,
+                	                      &*fmtp,
+                	                      user.GetPayloadSize(),
+                	                      frameWidth,
+                	                      frameHeight );
+                CleanupStack::PopAndDestroy( fmtp );
+                
+                
+                iPreroll = user.GetPreroll();
+                
+                if ( RealTimeMode() )
+                    {
+                    __V_SOURCESINK_CONTROLL( 
+                        "CMccVideoSinkImpl::HandleVideoSdpL, disable clock" )
+                    iSdp->Des().Append( KMccSdpInboundDisableVideoClock );
+                    
+                    // Currently, preroll needs to be set to some value
+                    // until disable video clock feature is working fully
+                    // at Helix side, once supported fully, preroll value
+                    // will not have any effect.
+                    const TInt KMccVideoSinkRealTimeTransitionPreroll = 500;
+                    iPreroll = KMccVideoSinkRealTimeTransitionPreroll;
+                    }
+                
+                 __V_SOURCESINK_CONTROLL_INT1( 
+                    "CMccVideoSinkImpl::HandleVideoSdpL, iPreroll ", iPreroll )
+                iPrerollSet = ETrue;
+                iSdp->Des().AppendFormat( KMccSdpInboundPreroll, iPreroll );
+                
+                firstUserHandled = ETrue;
+                }
+                
+            // Set correct stream id (all video users will have the same id)
+            user.iStreamId = streamId;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::AnalyzeTimeStampL
+// Checks whether rtp packet belongs to currently played stream. Check is done
+// based on timestamp monitoring. If this is new stream, helix needs to be 
+// resetted as it cannot cope with stream change. Helix is resetted
+// immediately if one of media types is detected to be from new stream.
+// Packets of other media types need to be dropped until also new stream
+// in those begins.
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::AnalyzeTimeStampL( 
+    CMccVideoSinkUser& aUser, 
+    TRtpRecvHeader& aHeaderInfo )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::AnalyzeTimeStampL" )
+        
+    aUser.CalculateAverageTimeStampDifference();
+
+    if ( aUser.IsResetNeeded( aHeaderInfo ) )
+        {
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::AnalyzeTimeStampL, reset needed" )
+            
+        if ( ResetOngoing() )
+            {
+            // XPS was resetted already earlier, allow queueing for this user
+            aUser.Reset( ETrue );
+            }
+        else
+            {
+            DoResetL( ETrue, &aUser );
+            
+            // Other media types cannot pass their data until new stream
+            // in them begin
+            for ( TInt i = 0; i < iUsers.Count(); i++ )
+                {
+                if ( iUsers[ i ] != &aUser )
+                    {
+                    iUsers[ i ]->SetAllowFrame( EFalse );
+                    }
+                }
+            }     
+        
+        }
+    
+    aUser.AddTimeStamp( (TInt64)aHeaderInfo.iTimestamp, aHeaderInfo.iSeqNum );
+        
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::AnalyzeTimeStampL, exit" )
+    
+    return aUser.AllowFrame();
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoResetL
+// ---------------------------------------------------------------------------
+//     
+void CMccVideoSinkImpl::DoResetL( TBool aFullReset, CMccVideoSinkUser* aUser )
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL" )
+    
+    // Start from scratch.
+    //
+    
+    if ( iVideoPlayer )
+        {
+        // If playing, have to pause, otherwise set position will not work
+        if ( iState == EPlaying )
+            {
+            __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL, mode 1" )
+            DoPauseL( aUser );
+            ResetPacketSink();
+            iVideoPlayer->SetPositionL( TTimeIntervalMicroSeconds( 0 ) );
+            DoPlay( aUser );
+            }
+        else
+            { 
+            __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL, mode 2" )
+            ResetPacketSink();
+            iVideoPlayer->SetPositionL( TTimeIntervalMicroSeconds( 0 ) );
+            }
+        }
+    
+    if ( aUser )
+        {
+        aUser->Reset( aFullReset );
+        }
+    else
+        {
+        for ( TInt i = 0; i < iUsers.Count(); i++ )
+            {
+            iUsers[ i ]->Reset( aFullReset );
+            }
+        }
+        
+    iNumPacketsEnqueued = 0;
+        
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::IsPlayerOpened
+// ---------------------------------------------------------------------------
+//    
+TBool CMccVideoSinkImpl::IsPlayerOpened() const
+    {
+    return ( iState > EOpening );
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResetPacketSink
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::ResetPacketSink()
+    {
+    if ( iPacketSink )
+        {
+        iPacketSink->Reset(); 
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::IsStartedOnce
+// ---------------------------------------------------------------------------
+//   
+TBool CMccVideoSinkImpl::IsStartedOnce( const CMccVideoSinkUser* aUser )
+    {
+    return ( aUser && aUser->iStartedOnce );
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetStartedOnce
+// ---------------------------------------------------------------------------
+//   
+void CMccVideoSinkImpl::SetStartedOnce( 
+    CMccVideoSinkUser* aUser, 
+    TBool aIsStartedOnce )
+    {
+    if ( aUser )
+        {
+        aUser->iStartedOnce = aIsStartedOnce;
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetRotationL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetRotationL( 
+    TMccVideoRotation aRotation, 
+    TBool aForceUpdate )
+    {
+    __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::SetRotationL, rotation:", 
+                                  aRotation )
+    __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+    
+    if ( aForceUpdate || ( aRotation != iSettings.iRotation ) )
+        {
+        __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetRotationL, setting" )
+        
+        // Enums for videoplayer rotation and mcc rotation are identical
+        iVideoPlayer->SetRotationL( *iRw, static_cast<TVideoRotation>( aRotation ) );
+        }
+    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetRotationL, exit" )
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetActualPrerollL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::GetActualPrerollL( TInt& aPreroll )
+    {
+    __V_SOURCESINK_CONTROLL_INT1( 
+        "CMccVideoSinkImpl::GetActualPrerollL, iPrerollSet:", iPrerollSet )
+    TInt videoEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeVideo );
+    if ( videoEntry == KErrNotFound )
+ 	    {
+ 	    __V_SOURCESINK_CONTROLL( 
+ 	        "CMccVideoSinkImpl::GetActualPrerollL, no video codec defined" )
+ 	    return;
+ 	    }
+ 	
+    aPreroll = iUsers[ videoEntry ]->GetActualPreroll();
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetVideoFrameRate
+// ---------------------------------------------------------------------------
+//
+TReal CMccVideoSinkImpl::GetVideoFrameRate()
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::GetVideoFrameRate" )
+    return iSettings.iVideoFrameRate;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetVideoFrameRate
+// ---------------------------------------------------------------------------
+//        
+void CMccVideoSinkImpl::SetVideoFrameRate( TReal aFrameRate )
+    {
+    __V_SOURCESINK_CONTROLL_INT1( 
+        "CMccVideoSinkImpl::SetVideoFrameRate, framerate:", (TUint32) aFrameRate )
+    
+    if ( aFrameRate > 0 )
+        {   
+        iSettings.iVideoFrameRate = aFrameRate;
+        
+        for ( TInt i = 0; i < iUsers.Count(); i++ )
+            {
+            TRAP_IGNORE( iUsers[ i ]->SetFrameRateL( iSettings.iVideoFrameRate ) )
+            }
+        }
+    else
+        {
+        iSettings.iVideoFrameRate = KMccDefaultVideoFrameRate;
+        }
+    
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetVideoFrameRate, exit" )
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResetOngoing
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::ResetOngoing() const
+    {
+    for ( TInt i = 0; i < iUsers.Count(); i++ )
+        {
+        if ( !iUsers[ i ]->AllowFrame() )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetFmtpLC
+// ---------------------------------------------------------------------------
+//
+HBufC8* CMccVideoSinkImpl::GetFmtpLC( const TMccCodecInfo& aCodecInfo )    
+    {
+    __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::GetFmtpLC" )
+    	
+    CMccCodecInformationFactory* factory = CMccCodecInformationFactory::NewL();
+    CleanupStack::PushL( factory );
+    CMccCodecInformation* codec = 
+        factory->CreateCodecInformationL( aCodecInfo.iSdpName );
+    CleanupStack::PushL( codec );
+    codec->SetValues( aCodecInfo );
+    HBufC8* fmtp = codec->GetFmtpL().AllocL();
+    CleanupStack::PopAndDestroy( codec );
+    CleanupStack::PopAndDestroy( factory );
+    CleanupStack::PushL( fmtp );
+    return fmtp;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoPauseL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoPauseL( const CMccVideoSinkUser* aUser )
+    {
+    if ( !RealTimeMode() )
+        {
+        iVideoPlayer->PauseL();
+        }
+    
+    DoPauseForUser( aUser );
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoPauseForUser
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoPauseForUser( const CMccVideoSinkUser* aUser )
+    {
+    for ( TInt i = 0; i < iUsers.Count(); i++ )
+        {
+        if ( !aUser || aUser == iUsers[ i ] )
+            {
+            iUsers[ i ]->Pause();
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoPlay
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoPlay( const CMccVideoSinkUser* aUser )
+    {
+    for ( TInt i = 0; i < iUsers.Count(); i++ )
+        {
+        if ( !aUser || aUser == iUsers[ i ] )
+            {
+            iUsers[ i ]->Play();
+            }
+        }
+        
+    iVideoPlayer->Play();
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MultipleMediaTypes
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::MultipleMediaTypes()
+    {
+    TInt audioEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeAudio );
+    TInt videoEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeVideo );
+    return ( audioEntry != KErrNotFound && videoEntry != KErrNotFound );	   
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RealTimeMode
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::RealTimeMode()
+    {
+    TBool realTimeMode( EFalse );
+    if ( !MultipleMediaTypes() )
+        {
+        for ( TInt i = 0; i < iUsers.Count() && !realTimeMode; i++ )
+            {
+            // If preroll is zero, real time mode is used
+            if ( iUsers[ i ]->GetPreroll() == 0 )
+                {
+                realTimeMode = ETrue;
+                }
+            }
+        }
+    
+    return realTimeMode;
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::AddUserL
+// ---------------------------------------------------------------------------
+//    
+void CMccVideoSinkImpl::AddUserL( MAsyncEventHandler& aEventHandler )
+    {
+    __ASSERT_ALWAYS( iPacketSink, User::Leave( KErrNotReady ) );
+    CMccVideoSinkUser* user = CMccVideoSinkUser::NewLC( 
+        &aEventHandler, KNullUid, 0, iSettings.iVideoFrameRate, *iPacketSink );
+    iUsers.AppendL( user );
+    CleanupStack::Pop( user );
+    }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoMvloLoadingComplete
+// If in realtime mode, helix gives loading completion istantly after starting
+// whichis not desired as buffering is done at MCC side. In that case
+// loading completion is not notified until MCC jitter buffer completes
+// loading (i.e. play threshold is reached).
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoMvloLoadingComplete( TBool aSimulated )
+	{
+	if ( RealTimeMode() )
+        {
+        if ( aSimulated && !iSimulatedStreamingEventSent )
+            {
+            __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoMvloLoadingComplete, simulate" ) 
+            
+            SendStreamEventToAllClients( KMccStreamPlaying, KErrNone, ETrue );
+            
+            iSimulatedBufferingEventSent = EFalse;
+            iSimulatedStreamingEventSent = ETrue;
+            }
+        }
+	else if ( !aSimulated )
+        {
+        SendStreamEventToAllClients( KMccStreamPlaying, KErrNone, ETrue );
+        }
+    else
+        {
+        // NOP
+        }
+	}
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoMvloLoadingComplete
+// If in realtime mode, helix gives loading started instantly after starting
+// it (even before passing in any packets). Loading starting is not notified
+// until first packet has been passed to MCC video jitterbuffer.
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoMvloLoadingStarted( TBool aSimulated )
+    {
+    if ( RealTimeMode() )
+        {
+        if ( aSimulated && !iSimulatedBufferingEventSent )
+            {
+            __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoMvloLoadingStarted, simulate" ) 
+            
+            SendStreamEventToAllClients( KMccStreamBuffering, KErrNone, ETrue );
+            
+            iSimulatedBufferingEventSent = ETrue;
+            iSimulatedStreamingEventSent = EFalse;
+            }
+        }
+    else if ( !aSimulated )
+        {
+        SendStreamEventToAllClients( KMccStreamBuffering, KErrNone, ETrue );
+        }
+    else
+        {
+        // NOP
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::AllUsersReady
+// Check if some user hasn't yet configured its settings
+// ---------------------------------------------------------------------------
+// 
+TBool CMccVideoSinkImpl::AllUsersReady()
+    {
+    TBool allUsersReady( ETrue );
+    for ( TInt i = 0; i <  iUsers.Count(); i++ )
+        {
+        if ( iUsers[ i ]->iMediaType == KNullUid )
+            {
+            allUsersReady = EFalse;
+            }
+        }
+    return allUsersReady;
+    }
+    
+// End of file
+