multimediacommscontroller/mmccsubcontroller/src/mccsymsubthreadclient.cpp
changeset 0 1bce908db942
child 32 f2ed1fc4c163
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccsubcontroller/src/mccsymsubthreadclient.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,993 @@
+/*
+* Copyright (c) 2004-2008 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:    Symmetric subthread client
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <mmf/server/mmfdatasource.h>
+#include <mmf/server/mmfdatasink.h>
+
+#include "mccsymsubthreadclient.h"
+#include "mccsymulstream.h"
+#include "mccsymdlstream.h"
+#include "mccsymsimpledlstream.h"
+#include "mccdtmfdlstream.h"
+#include "mccdtmfulstream.h"
+#include "mccrtpmanager.h"
+#include "amrpayloadformatutil.h"
+#include "mccinternalevents.h"
+#include "mccsubcontrollerlogs.h"
+#include "mmccsecureinterface.h"
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::CMccSymSubthreadClient
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+CMccSymSubthreadClient::CMccSymSubthreadClient(
+    MMccEventHandler* aObserver,
+    MMccResources* aMccResources,
+    TInt aLinkType,
+    TUint32 aMccSessionId ):
+    CMccSubThreadClientBase( aObserver, aMccResources, aLinkType, aMccSessionId )        
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::ConstructL()
+    {
+	__SUBCONTROLLER( "CMccSymSubthreadClient::ConstructL" )
+	User::LeaveIfNull( iObserver );
+	User::LeaveIfNull( iMccResources );
+    iRtpmanager = CMccRtpManager::NewL( *this, *iMccResources, MccSessionId() );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::ConstructL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::NewL
+// Static constructor.
+// -----------------------------------------------------------------------------
+CMccSymSubthreadClient* CMccSymSubthreadClient::NewL( 
+    MMccEventHandler* aObserver, 
+    MMccResources* aMccResources,
+    TInt aLinkType,
+    TUint32 aMccSessionId )
+    {        
+    CMccSymSubthreadClient* self = 
+            new ( ELeave ) CMccSymSubthreadClient( aObserver, aMccResources, aLinkType, aMccSessionId );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::~CMccSymSubthreadClient
+// Destructor
+// -----------------------------------------------------------------------------
+CMccSymSubthreadClient::~CMccSymSubthreadClient()
+    {
+	__SUBCONTROLLER( "CMccSymSubthreadClient::~CMccSymSubthreadClient" )
+		        
+    iStreams.ResetAndDestroy();
+    iStreams.Close();
+    
+    iUnusedStreams.Reset();
+    iUnusedStreams.Close();
+    
+    if( iRtpmanager )
+        {
+        iRtpmanager->CloseSession();
+        delete iRtpmanager;
+        }    
+	__SUBCONTROLLER( "CMccSymSubthreadClient::~CMccSymSubthreadClient, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SetVolumeL
+// Creates a new RTP session in a subthread
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::SetVolumeL( TInt aVolume )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SetVolumeL", aVolume )
+    TInt strmCount = iStreams.Count();
+    if( strmCount )
+        {
+        for( TInt k = 0; k < strmCount; k++ )
+            {
+            iStreams[k]->SetVolumeL( aVolume );
+            }
+        }
+    else
+        {        
+	    __SUBCONTROLLER( "CMccSymSubthreadClient::SetVolumeL, no streams" )
+        }
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetVolumeL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SetGainL
+// Creates a new RTP session in a subthread
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::SetGainL( TInt aGain )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SetGainL", aGain )
+    TInt strmCount = iStreams.Count();
+    if( strmCount )
+        {
+        for( TInt k = 0; k < strmCount; k++ )
+            {
+            iStreams[k]->SetGainL( aGain );
+            }
+        }
+    else
+        {
+	    __SUBCONTROLLER( "CMccSymSubthreadClient::SetGainL, no streams" )
+        }
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetGainL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::VolumeL
+// Creates a new RTP session in a subthread
+// -----------------------------------------------------------------------------
+TInt CMccSymSubthreadClient::GetVolumeL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetVolumeL for streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt volume = 0;
+    TInt index = FindStreamL( aStreamId );
+    volume = iStreams[index]->VolumeL();
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetVolumeL exit with", volume )
+    return volume;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::GainL
+// Creates a new RTP session in a subthread
+// -----------------------------------------------------------------------------
+TInt CMccSymSubthreadClient::GetGainL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetGainL for streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt gain = 0;
+    TInt index = FindStreamL( aStreamId );
+    gain = iStreams[index]->GainL();
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetGainL exit with", gain )
+    return gain;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::MaxVolumeL
+// Creates a new RTP session in a subthread
+// -----------------------------------------------------------------------------
+TInt CMccSymSubthreadClient::MaxVolumeL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::MaxVolumeL for streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt maxvolume = 0;
+    TInt index = FindStreamL( aStreamId );
+    maxvolume = iStreams[index]->MaxVolumeL();
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::MaxVolumeL exit with", maxvolume )
+    return maxvolume;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::MaxGainL
+// Creates a new RTP session in a subthread
+// -----------------------------------------------------------------------------
+TInt CMccSymSubthreadClient::MaxGainL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::MaxGainL for streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt maxgain = 0;
+    TInt index = FindStreamL( aStreamId );
+    maxgain = iStreams[index]->MaxGainL();
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::MaxGainL exit with", maxgain )
+    return maxgain;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SetBalanceL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::SetBalanceL( const TUint32 aStreamId, TInt aLeftBalance, 
+        TInt aRightBalance )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SetBalanceL for streamId", aStreamId )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SetBalanceL for LeftBalance", aLeftBalance )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SetBalanceL for RightBalance", aRightBalance )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->SetBalanceL( aLeftBalance, aRightBalance );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetBalanceL exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::GetBalanceL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::GetBalanceL( const TUint32 aStreamId, TInt& aLeftBalance, 
+        TInt& aRightBalance )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetBalanceL for streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->GetBalanceL( aLeftBalance, aRightBalance );
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetBalanceL for LeftBalance", aLeftBalance )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetBalanceL for RightBalance", aRightBalance )
+	__SUBCONTROLLER( "CMccSymSubthreadClient::GetBalanceL exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::OpenL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::OpenL( TInt aStreamType,
+                                    TFourCC aFourCC,
+                                    MDataSource* aDatasource, 
+                                    MDataSink* aDatasink,
+                                    const TUint32 aStreamId,
+                                    TMMFPrioritySettings aSettings )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::OpenL for streamId", aStreamId )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient stream type", aStreamType )
+    __ASSERT_ALWAYS( iSessionCreated, User::Leave( KErrNotReady ) );
+    __ASSERT_ALWAYS( aDatasource, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( aDatasink, User::Leave( KErrArgument ) );
+        
+    TUid sourceType = aDatasource->DataSourceType();
+    TUid sinkType = aDatasink->DataSinkType();
+
+	iPrioritySettingsData = aSettings;
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient audio priority", iPrioritySettingsData.iPriority )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient audio preference", iPrioritySettingsData.iPref )
+
+    CMccSymStreamBase* stream( NULL );
+    
+    TBool localAVToDisplayStream = ( aStreamType == KMccVideoLocalStream ||
+                                     aStreamType == KMccAudioLocalStream ) &&
+                                     sourceType == KMccFileSourceUid &&
+                                     sinkType == KMccVideoSinkUid;
+    
+    if ( KMccDtmfStream == aStreamType && KMccRtpSourceUid == sourceType )
+        {
+        __SUBCONTROLLER( "CMccSymSubthreadClient::OpenL, new CMccDtmfDlStream" )
+        
+        stream = CMccDtmfDlStream::NewLC( aStreamId, this, iMccResources,
+            iRtpmanager, aFourCC, aStreamType, *iRtpMediaClock );
+        }
+    else if ( KMccDtmfStream == aStreamType && KMccRtpSinkUid == sinkType )
+        {
+        __SUBCONTROLLER( "CMccSymSubthreadClient::OpenL, new CMccDtmfUlStream" )
+        
+        stream = CMccDtmfUlStream::NewLC( aStreamId, this, iMccResources,
+            iRtpmanager, aFourCC, aStreamType, *iRtpMediaClock );
+        }
+    // Special handling for local video if it should be displayed (treat as uplink)
+    else if( sinkType == KMccRtpSinkUid ||
+        localAVToDisplayStream )
+        {
+	    __SUBCONTROLLER( "CMccSymSubthreadClient::OpenL, new CMccSymUlStream" )
+        stream = CMccSymUlStream::NewLC( aStreamId, 
+                                         this, 
+                                         iMccResources, 
+                                         iRtpmanager, 
+                                         aFourCC, 
+                                         aStreamType,
+                                         *iRtpMediaClock );
+        }
+    else if( sourceType == KMccRtpSourceUid && sinkType != KMccVideoSinkUid )
+        {
+	    __SUBCONTROLLER( "CMccSymSubthreadClient::OpenL, new CMccSymDlStream" )
+        stream = CMccSymDlStream::NewLC( aStreamId, 
+                                         this, 
+                                         iMccResources,
+                                         iRtpmanager, 
+                                         aStreamType );
+        }
+    else if( ( sourceType == KMccRtpSourceUid && sinkType == KMccVideoSinkUid ) ||
+             ( aStreamType == KMccAudioLocalStream || aStreamType == KMccVideoLocalStream ) )
+        {  
+        __SUBCONTROLLER( "CMccSymSubthreadClient::OpenL, new CMccSymSimpleDlStream" )      
+        stream = CMccSymSimpleDlStream::NewLC( aStreamId, 
+                                               this, 
+                                               iMccResources,
+                                               iRtpmanager, 
+                                               aFourCC, 
+                                               aStreamType );
+                
+        }
+    else
+        {
+	    __SUBCONTROLLER( "CMccSymSubthreadClient::OpenL, KErrArgument" )
+        User::Leave( KErrArgument );
+        }
+    
+    stream->AddSinkAndSourceL( aDatasink, aDatasource );
+    iStreams.AppendL( stream );
+    CleanupStack::Pop( stream );
+        
+    TInt index = FindStreamL( aStreamId );     
+    iStreams[ index ]->SetMMFPriority( aSettings );
+   
+	__SUBCONTROLLER( "CMccSymSubthreadClient::OpenL, exit" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::PrepareL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::PrepareL( const TUint32 aStreamId, 
+									   const TUint32 aEndpointId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::PrepareL, streamId", aStreamId )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::PrepareL, aEndpointId", aEndpointId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->PrimeL( aEndpointId );	
+	__SUBCONTROLLER( "CMccSymSubthreadClient::PrepareL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::PlayL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::PlayL( const TUint32 aStreamId,
+                                    const TUint32 aEndpointId,
+                                    TBool aStreamPaused,
+                                    TBool aEnableRTCP )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::PlayL, streamId", aStreamId )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::PlayL, aEndpointId", aEndpointId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->PlayL( aEndpointId, aStreamPaused, aEnableRTCP ); 
+	__SUBCONTROLLER( "CMccSymSubthreadClient::PlayL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::StopL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::StopL( const TUint32 aStreamId,
+									const TUint32 aEndpointId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::StopL, streamId", aStreamId )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::StopL, aEndpointId", aEndpointId )
+    TInt index = FindStream( aStreamId );
+    if ( index != KErrNotFound )
+        {
+        iStreams[index]->StopL( aEndpointId );
+        }
+    else
+        {
+        // No need to stop if unused
+        index = iUnusedStreams.Find( aStreamId );
+        __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) );
+        }
+	__SUBCONTROLLER( "CMccSymSubthreadClient::StopL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::PauseL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::PauseL( const TUint32 aStreamId,
+									 const TUint32 aEndpointId,
+                                     TBool aEnableRTCP )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::PauseL, streamId", aStreamId )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::PauseL, aEndpointId", aEndpointId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->PauseL( aEndpointId, aEnableRTCP );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::PauseL, exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::ResumeL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::ResumeL( const TUint32 aStreamId,
+									  const TUint32 aEndpointId,
+                                      TBool aEnableRTCP )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::ResumeL, streamId", aStreamId )
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::ResumeL, aEndpointId", aEndpointId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->ResumeL( aEndpointId, aEnableRTCP );
+    __SUBCONTROLLER( "CMccSymSubthreadClient::ResumeL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::CloseL
+// From CMccSubThreadClientBase
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::CloseL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::CloseL, streamId", aStreamId )
+    
+    TInt index = FindStream( aStreamId );
+    if ( index != KErrNotFound )
+        {
+        CMccSymStreamBase* tmp = iStreams[index];
+        iStreams.Remove( index );
+        delete tmp;
+        }
+    else 
+        {
+        index = iUnusedStreams.Find( aStreamId );
+        __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) );
+
+        // Stream was already deleted
+        iUnusedStreams.Remove( index );
+        }
+    
+    // No need to fail stream deletion if manager update fails
+    TRAP_IGNORE( iRtpmanager->UpdateL() )
+        
+	__SUBCONTROLLER( "CMccSymSubthreadClient::CloseL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::CloseL 
+// Closes all links
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::CloseL()
+    {
+	__SUBCONTROLLER( "CMccSymSubthreadClient::CloseL" )
+	
+    for ( TInt i = iStreams.Count() - 1; i >= 0; i-- )
+    	{
+        CMccSymStreamBase* tmp = iStreams[i];
+        tmp->RemoveContext( 0 );
+        iStreams.Remove( i );
+        delete tmp;        	    	
+    	}
+	__SUBCONTROLLER( "CMccSymSubthreadClient::CloseL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::StreamsExistsL 
+// -----------------------------------------------------------------------------
+TBool CMccSymSubthreadClient::StreamsExistsL()
+    {
+    if (iStreams.Count())
+        {
+        return ETrue;
+        }
+    else
+        {
+        return  EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SendMediaSignalL
+// Send media signalling to uplink
+// -----------------------------------------------------------------------------
+//  
+void CMccSymSubthreadClient::SendMediaSignalL( const TMccEvent& aEvent )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SendMediaSignalL, streamId", aEvent.iStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aEvent.iStreamId );
+    iStreams[index]->SendMediaSignalL( aEvent );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SendMediaSignalL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccUlSubThreadClient::SendRTCPReceiverReportL
+// Sends a RTCP receiver report
+// -----------------------------------------------------------------------------
+//  
+void CMccSymSubthreadClient::SendRTCPReceiverReportL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SendRTCPReceiverReportL, streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->SendRTCPReceiverReportL();
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SendRTCPReceiverReportL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccUlSubThreadClient::SendRTCPSenderReportL
+// Sends a RTCP sender report
+// -----------------------------------------------------------------------------
+// 
+void CMccSymSubthreadClient::SendRTCPSenderReportL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SendRTCPSenderReportL, streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->SendRTCPSenderReportL();
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SendRTCPSenderReportL, exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SendRTCPDataL
+// Sends Non-RTCP data
+// -----------------------------------------------------------------------------
+// 
+void CMccSymSubthreadClient::SendRTCPDataL( const TUint32 aStreamId,
+                                            const TDesC8& aData )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::SendRTCPDataL, streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->SendRTCPDataL( aData );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SendRTCPDataL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccUlSubThreadClient::GetSupportedBitratesL
+// Gets the supported bitrates from the codec of the specified stream
+// -----------------------------------------------------------------------------    
+void CMccSymSubthreadClient::GetSupportedBitratesL( const TUint32 /*aStreamId*/,
+                                                   RArray<TUint>& /*aBitrates*/ )
+    {
+    //TBI: What with the stream ID?
+    //TODO //User::LeaveIfError( iSubthread.GetSupportedBitrates( aBitrates ) );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccUlSubThreadClient::GetSSRCL
+// Gets the syncronization source for the specified stream
+// -----------------------------------------------------------------------------    
+void CMccSymSubthreadClient::GetSSRCL( const TUint32 aStreamId, TUint32& aSSRCValue )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetSSRCL, streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->GetSSRCL( aSSRCValue );
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::GetSSRCL, SSRC", aSSRCValue )
+	__SUBCONTROLLER( "CMccSymSubthreadClient::GetSSRCL, exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccDlSubThreadClient::StartInactivityTimerL
+// Starts inactivity timer for a stream 
+// -----------------------------------------------------------------------------    
+void CMccSymSubthreadClient::StartInactivityTimerL( const TUint32 aStreamId,
+                                                   TUint32 aTimeoutTime )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::StartInactivityTimerL, streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->StartInactivityTimerL( aTimeoutTime );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::StartInactivityTimerL, exit" )
+    }
+       
+// -----------------------------------------------------------------------------
+// CMccDlSubThreadClient::StopInactivityTimerL
+// Stops inactivity timer for a stream 
+// -----------------------------------------------------------------------------    
+void CMccSymSubthreadClient::StopInactivityTimerL( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::StopInactivityTimerL, streamId", aStreamId )
+	__ASSERT_ALWAYS( iStreams.Count(), User::Leave( KErrNotFound ) );
+    TInt index = FindStreamL( aStreamId );
+    iStreams[index]->StopInactivityTimerL();
+	__SUBCONTROLLER( "CMccSymSubthreadClient::StopInactivityTimerL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::GetFmtpAttrL
+// Fetches the FMTP attribute of the current codec
+// -----------------------------------------------------------------------------
+// 
+void CMccSymSubthreadClient::GetFmtpAttrL( const TUint32 /*aStreamId*/,
+                                           TDes8& /*aFmtp*/ )
+    {
+    
+    } 
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SetRemoteAddressL
+// Sets the remote address of uplink stream
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::SetRemoteAddressL( TInetAddr aRemAddr )
+    {    
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetRemoteAddressL" )
+    __ASSERT_ALWAYS( iRtpmanager, User::Leave( KErrArgument ) );
+
+    User::LeaveIfError( iRtpmanager->SetRemoteAddress( aRemAddr ) );
+    
+    TInt strmCount = iStreams.Count();
+    for( TInt k = 0; k < strmCount; k++ )
+        {
+        iStreams[k]->ResetCountersL();
+        }
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetRemoteAddressL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SetRemoteAddressL
+// Sets the remote address of uplink stream
+// -----------------------------------------------------------------------------
+void CMccSymSubthreadClient::SetRemoteRtcpAddrL( TInetAddr aRemAddr )
+    {    
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetRemoteRtcpAddrL" )
+    __ASSERT_ALWAYS( iRtpmanager, User::Leave( KErrArgument ) );
+
+    User::LeaveIfError( iRtpmanager->SetRemoteRtcpAddr( aRemAddr ) );
+    
+    TInt strmCount = iStreams.Count();
+    for( TInt k = 0; k < strmCount; k++ )
+        {
+        iStreams[k]->ResetCountersL();
+        }
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetRemoteRtcpAddrL, exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::InitializeLinkL
+// Initializes the RTP session in the subthread
+// -----------------------------------------------------------------------------
+//
+void CMccSymSubthreadClient::InitializeLinkL( TRequestStatus& aStatus,
+                                              TInt aIapId )
+    {    
+	__SUBCONTROLLER( "CMccSymSubthreadClient::InitializeLinkL" )
+    __ASSERT_ALWAYS( !iSessionCreated, User::Leave( KErrAlreadyExists ) );
+    iRtpmanager->InitializeL( aStatus, aIapId );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::InitializeLinkL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::CreateRtpSessionL
+// Creates the RTP session in the subthread
+// -----------------------------------------------------------------------------
+//
+void CMccSymSubthreadClient::CreateRtpSessionL( TUint aPort, 
+                                                TBool aEnableRTCP,
+                                                TInt aIpTos, 
+                                                CMccRtpMediaClock& aClock )
+    {
+	__SUBCONTROLLER( "CMccSymSubthreadClient::CreateRtpSessionL" )
+    iRtpMediaClock = &aClock;
+    
+    TBool secure( EFalse );
+    if ( KMccLinkSecure == iLinkType || KMccLinkSecureVideo == iLinkType )
+        {
+        secure = ETrue;
+        }
+    
+    TBool increaseDefaultSocketSize( EFalse );
+    if ( KMccLinkGeneralVideo == iLinkType || KMccLinkSecureVideo == iLinkType )
+        {
+        increaseDefaultSocketSize = ETrue;
+        }
+        
+    iRtpmanager->CreateSessionL( aPort, aEnableRTCP, secure, increaseDefaultSocketSize );
+    iRtpmanager->SetIpTOS( aIpTos );
+	iSessionCreated = ETrue;
+	
+	__SUBCONTROLLER( "CMccSymSubthreadClient::CreateRtpSessionL, exit" )
+	}
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SetAudioRouteL
+// -----------------------------------------------------------------------------
+//    
+void CMccSymSubthreadClient::SetAudioRouteL( 
+    TUint32 aStreamId,
+    TUint32 aRoutingDestination )
+    {
+    __SUBCONTROLLER( "CMccSymSubthreadClient::SetAudioRouteL" )
+    TInt index = FindStreamL( aStreamId );
+    iStreams[ index ]->SetAudioRouteL( aRoutingDestination );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SetAudioRouteL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::GetAudioRouteL
+// -----------------------------------------------------------------------------
+//
+void CMccSymSubthreadClient::GetAudioRouteL( 
+    TUint32 aStreamId,
+    TUint32& aRoutingDestination )
+    {
+    __SUBCONTROLLER( "CMccSymSubthreadClient::GetAudioRouteL" )
+    TInt index = FindStreamL( aStreamId );
+    iStreams[ index ]->GetAudioRouteL( aRoutingDestination );
+	__SUBCONTROLLER( "CMccSymSubthreadClient::GetAudioRouteL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::UnuseL
+// -----------------------------------------------------------------------------
+//    
+void CMccSymSubthreadClient::UnuseL( TUint32 aStreamId )
+    {
+    __SUBCONTROLLER_INT1( "CMccSymSubthreadClient::UsuseL, streamId", aStreamId )
+    
+    TInt index = FindStream( aStreamId );
+    if ( index != KErrNotFound )
+        {
+        CMccSymStreamBase* tmp = iStreams[index];
+        iStreams.Remove( index );
+        delete tmp;
+        
+        // Store stream id for later use (when stream is explicitly deleted)
+        iUnusedStreams.AppendL( aStreamId );
+        }
+    else 
+        {
+        index = iUnusedStreams.Find( aStreamId );
+        __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) );
+        }
+    
+	__SUBCONTROLLER( "CMccSymSubthreadClient::UsuseL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::GetLocalIpAddressesL
+// -----------------------------------------------------------------------------
+//
+void CMccSymSubthreadClient::GetLocalIpAddressesL( TMccCreateLink& aClientData )
+	{
+	__SUBCONTROLLER( "CMccSymSubthreadClient::GetLocalIpAddressesL" )
+	
+	iRtpmanager->GetLocalIpAddressesL( aClientData );
+	                                      
+	__SUBCONTROLLER( "CMccSymSubthreadClient::GetLocalIpAddressesL, exit" )
+	}
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SetParameterL
+// -----------------------------------------------------------------------------
+//     
+void CMccSymSubthreadClient::SetParameterL( 
+    TUint32 aParam,
+    TUint32 /*aStreamId*/,
+    TUint32 /*aEndpointId*/,
+    const TDesC8& aVal )
+    {
+    __SUBCONTROLLER( "CMccSymSubthreadClient::SetParameterL" )
+    
+    switch ( aParam )
+        {
+        case KMccRtpCName:
+            {
+            iRtpmanager->SetCNameL( aVal );
+            break;
+            }
+        default:
+            {
+            User::Leave( KErrNotSupported );
+            break;
+            }
+        }
+        
+    __SUBCONTROLLER( "CMccSymSubthreadClient::SetParameterL, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::GetParameterL
+// -----------------------------------------------------------------------------
+//          
+void CMccSymSubthreadClient::GetParameterL( 
+    TUint32 /*aParam*/,
+    TUint32 /*aStreamId*/,
+    TUint32 /*aEndpointId*/,
+    TDesC8& /*aVal*/ )
+    {
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::SendEventToClient
+// -----------------------------------------------------------------------------
+//    
+TInt CMccSymSubthreadClient::SendEventToClient( const TMMFEvent& aEvent )
+	{
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SendEventToClient" )
+	
+	// Do in a bit ackward way in order to save stack memory
+	TMccEvent* mccEventPtr = 0;
+	if ( IS_MCC_EVENT( aEvent ) )
+	    {
+	    mccEventPtr = 
+	        reinterpret_cast<const TMccInternalEvent&>( aEvent ).iMccEvent;                                     
+	    }
+	
+	if ( mccEventPtr )
+	    {
+	    mccEventPtr->iLinkId = iLinkId;
+
+    	__SUBCONTROLLER_EVENT( (*mccEventPtr) )	    
+
+        TUid eventUid = aEvent.iEventType;
+        TUid amrUid = TUid::Uid( KDllUidAmrPayloadFormat );
+	    
+	    // If RTCP BYE received remove crypto context
+	    if ( KMccRtcpReceived == mccEventPtr->iEventType )
+	        {
+	        const TMccRtcpEventData& eventdata = 
+    		    (*reinterpret_cast<const TMccRtcpEventDataPackage*>( 
+                &mccEventPtr->iEventData ))();
+                
+            if ( KRtcpByePacket == eventdata.iRtcpPacketType )
+                {
+                // Remove crypto context                               
+                const TInt count = iStreams.Count();
+                for( TInt k = 0; k < count; k++ )
+                    {
+                    // Ignore the return value as we're doing this blindly                        
+                    iStreams[k]->RemoveContext( 0 );
+                    }   
+                }
+	        }
+	    
+        if( amrUid == eventUid )
+            {
+            // Amr events not forwarded
+            TInt err = HandleAmrEvent( aEvent, *mccEventPtr );
+            __SUBCONTROLLER( "CMccSymSubthreadClient::SendEventToClient, exit" )
+            return err;
+            }
+            
+	    iObserver->SendMccEventToClient( *mccEventPtr );
+	    }
+	else
+	    {
+	    TMccEvent mccEvent;
+	    DoMccEvent( mccEvent, aEvent );
+
+    	__SUBCONTROLLER_EVENT( mccEvent )
+
+	    iObserver->SendMccEventToClient( mccEvent );
+	    }
+    
+	__SUBCONTROLLER( "CMccSymSubthreadClient::SendEventToClient, exit" )
+    return KErrNone;
+	}
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::DoMccEvent
+// -----------------------------------------------------------------------------
+//
+void CMccSymSubthreadClient::DoMccEvent( 
+    TMccEvent& aEvent, 
+    const TMMFEvent& aMMFEvent )
+    {
+    aEvent.iEventCategory = KMccEventCategoryStream;
+	aEvent.iEventType = KMccStreamMMFEvent;
+    aEvent.iErrorCode = aMMFEvent.iErrorCode;
+    aEvent.iLinkId = iLinkId;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::DataSink
+// -----------------------------------------------------------------------------
+//
+MDataSink* CMccSymSubthreadClient::DataSink( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::DataSink, streamId", aStreamId )
+    TInt strmCount = iStreams.Count();
+    if( strmCount )
+        {
+        TInt index = this->FindStream( aStreamId );
+        if ( index != KErrNotFound )
+	        {
+	        return iStreams[index]->DataSink();        	
+	        }
+        }
+    return NULL;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::DataSource
+// -----------------------------------------------------------------------------
+//
+MDataSource* CMccSymSubthreadClient::DataSource( const TUint32 aStreamId )
+    {
+	__SUBCONTROLLER_INT1( "CMccSymSubthreadClient::DataSource, streamId", aStreamId )
+    TInt strmCount = iStreams.Count();
+    if( strmCount )
+        {
+        TInt index = this->FindStream( aStreamId );
+        if ( index != KErrNotFound )
+	        {
+	        return iStreams[index]->DataSource();        	
+	        }
+        }
+    return NULL; 
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::BindContextIntoStreamL
+// -----------------------------------------------------------------------------
+//
+void CMccSymSubthreadClient::BindContextIntoStreamL( TUint32 aStreamId,
+                                                     TUint32 aEndpointId,
+                                                     const TMccCryptoContext& aContextParams )
+    {
+	__SUBCONTROLLER( "CMccSymSubthreadClient::BindContextIntoStreamL IN" )
+	
+	TInt index = this->FindStreamL( aStreamId );
+	
+	iStreams[ index ]->BindContextIntoStreamL( aEndpointId, aContextParams );
+
+	__SUBCONTROLLER( "CMccSymSubthreadClient::BindContextIntoStreamL END" )
+    }   
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::RemoveContextL
+// -----------------------------------------------------------------------------
+//
+void CMccSymSubthreadClient::RemoveContextL( TUint32 aStreamId,
+                                             TUint32 aEndpointId )
+    {
+	__SUBCONTROLLER( "CMccSymSubthreadClient::RemoveContextL IN" )
+	
+	TInt index = this->FindStreamL( aStreamId );
+	
+	iStreams[ index ]->RemoveContext( aEndpointId );
+
+	__SUBCONTROLLER( "CMccSymSubthreadClient::RemoveContextL END" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccSymSubthreadClient::HandleAmrEvent
+// -----------------------------------------------------------------------------
+//
+TInt CMccSymSubthreadClient::HandleAmrEvent( 
+    const TMMFEvent& aEvent,
+    const TMccEvent& aMccEvent )
+    {
+    const TInt internalEvent = 
+        reinterpret_cast<const TMccInternalEvent&>( aEvent ).iInternalEventType; 
+    
+    const TMccAmrEventData& eventdata = 
+	    (*reinterpret_cast<const TMccAmrEventDataPackage*>( 
+        &aMccEvent.iEventData ))();
+    
+    __SUBCONTROLLER_INT1( "CMccSymStreamBase::HandleAmrEvent AMR EVENT:", 
+                          internalEvent );
+    __SUBCONTROLLER_INT1( "CMccSymStreamBase::HandleAmrEvent AMR MODE_REQ BITRATE:", 
+                          eventdata.iModeRequestBitrate );
+    
+    if ( EMccInternalAmrEventCmr == internalEvent )
+        {
+        if ( eventdata.iModeRequestBitrate > 0 )
+            {
+            // Mode change request, forward it to other streams
+            const TInt count = iStreams.Count();
+            for( TInt k = 0; k < count; k++ )
+                {
+                // Ignore the return value as we're doing this blindly
+                iStreams[k]->ChangeBitrate( eventdata.iModeRequestBitrate );
+                }
+            }
+        }
+    return KErrNone;
+    }
+    
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+//  End of File