multimediacommsengine/mmcesrv/mmcemediamanager/src/mcesrvstream.cpp
changeset 0 1bce908db942
child 11 2a28ef775f15
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmcemediamanager/src/mcesrvstream.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1224 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:    
+*
+*/
+
+
+
+
+#include "mcesrvstream.h"
+#include "mcesrvsource.h"
+#include "mcesrvsink.h"
+#include "mceevents.h"
+
+#include <sdpcodecstringconstants.h>
+
+#include "mcecomsession.h"
+#include "mcecomaudiostream.h"
+#include "mcecomaudiocodec.h"
+#include "mcecommediasource.h"
+#include "mcecommediasink.h"
+#include "mcecomvideostream.h"
+#include "mcecomvideocodec.h"
+#include "mcecomdisplaysink.h"
+#include "mcecomcamerasource.h"
+#include "mcedisplaysink.h"
+#include "mcecamerasource.h"
+
+#include "mceaudiostream.h"
+#include "mcevideostream.h"
+#include "mcesrvstreamiterator.h"
+#include "mcemediamanager.h"
+#include "mcedtmfcodec.h"
+#include "mcemmlogs.h"
+#include "mcedtmfhandler.h"
+
+#define MCE_MCC_STREAM_STATE_CHANGE_EVENT( event )\
+( aEvent.iEvent == KMccStreamPrepared || \
+  aEvent.iEvent == KMccStreamStarted || \
+  aEvent.iEvent == KMccStreamPaused || \
+  aEvent.iEvent == KMccStreamResumed || \
+  aEvent.iEvent == KMccStreamStopped )
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::DecodeL
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::DecodeL( RPointerArray<CMceSrvStream>& aStreams,
+                             CMceComMediaStream& aStream,
+                             CMceMediaManager& aManager )
+    {
+    MCEMM_DEBUG("CMceSrvStream::DecodeL(), Entry ");
+        
+    switch( aStream.iType )
+        {
+        case KMceAudio:
+            {
+            CMceComAudioStream& audio = 
+                static_cast<CMceComAudioStream&>( aStream );
+            DecodeAudioL( aStreams, audio, aManager );
+            break;
+            }
+        case KMceVideo:
+            {
+            CMceComVideoStream& video = 
+                static_cast<CMceComVideoStream&>( aStream );
+            DecodeVideoL( aStreams, video, aManager );
+            break;
+            }
+        default:
+            {
+            User::Leave( KErrNotSupported );
+            break;
+            }
+        }
+    MCEMM_DEBUG("CMceSrvStream::DecodeL(), Exit ");
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::DecodeAudioL
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::DecodeAudioL( RPointerArray<CMceSrvStream>& aStreams,
+                                  CMceComAudioStream& aAudio,
+                                  CMceMediaManager& aManager )
+    {
+    MCEMM_DEBUG("CMceSrvStream::DecodeAudioL(), Entry ");
+    
+    // First clear all enabled states, those are affected inside codec
+    // specific decoding
+    for(  TInt i = 0; i < aAudio.CodecCount(); ++i )
+        {
+        aAudio.CodecL( i )->SetEnabled( EFalse );
+        }
+    
+    for ( TInt j = 0; j < aAudio.CodecCount(); ++j )
+        {
+        aAudio.CodecL( j )->DoDecodeAudioL( j, 
+                                              aStreams, 
+                                              aAudio, 
+                                              aManager );
+        }
+        
+    if ( aAudio.BoundStream() && aAudio.Binder() )
+        {
+        DecodeL( aStreams, aAudio.BoundStreamL(), aManager );
+        }
+    MCEMM_DEBUG("CMceSrvStream::DecodeAudioL(), Exit ");
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::DecodeVideoL
+// -----------------------------------------------------------------------------
+//
+
+void CMceSrvStream::DecodeVideoL( RPointerArray<CMceSrvStream>& aStreams,
+                                  CMceComVideoStream& aVideo,
+                                  CMceMediaManager& aManager )
+    {
+    MCEMM_DEBUG("CMceSrvStream::DecodeVideoL(), Entry ");
+    
+    for( TInt codecNdx = 0;codecNdx < aVideo.CodecCount();codecNdx++ )
+        {
+        aVideo.CodecL( codecNdx )->SetEnabled( 
+            codecNdx == 0 || IS_RECEIVESTREAM( &aVideo ) );
+            
+        for( TInt sinkNdx = 0 ; sinkNdx < aVideo.Sinks().Count() ; sinkNdx++ )
+            {
+            CMceSrvStream* srvStream = NewL( aManager, aVideo, 
+                                             *aVideo.Source(),
+                                             *aVideo.Sinks()[ sinkNdx ],
+                                             *aVideo.CodecL( codecNdx ) );
+                CleanupStack::PushL( srvStream );
+                MCEMM_DEBUG_STREAM( "CMceSrvStream::DecodeVideoL(): decoded video", *srvStream );
+                aStreams.AppendL( srvStream );
+                CleanupStack::Pop( srvStream );
+            }
+        }
+    if ( aVideo.BoundStream() && aVideo.Binder() )
+        {
+        DecodeL( aStreams, aVideo.BoundStreamL(), aManager );
+        }
+    MCEMM_DEBUG("CMceSrvStream::DecodeVideoL(), Exit ");
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::NewL
+// -----------------------------------------------------------------------------
+//
+CMceSrvStream* CMceSrvStream::NewL( CMceMediaManager& aManager,
+                          CMceComMediaStream& aData,
+                          CMceComMediaSource& aSource,
+                          CMceComMediaSink& aSink,
+                          CMceComCodec& aCodec )
+    {
+    CMceSrvStream* self = new (ELeave) CMceSrvStream( &aManager, &aData, &aCodec );
+    CleanupStack::PushL( self );
+    self->ConstructL( aSource, aSink );
+    CleanupStack::Pop( self );
+    
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::CMceSrvStream
+// -----------------------------------------------------------------------------
+//
+CMceSrvStream::CMceSrvStream()
+    {
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::CMceSrvStream
+// -----------------------------------------------------------------------------
+//
+CMceSrvStream::CMceSrvStream( CMceMediaManager* aManager,
+                              CMceComMediaStream* aData,
+                              CMceComCodec* aCodec )
+    : iManager( aManager ),
+      iData( aData ),
+      iCodec( aCodec ),
+      iMerged( EFalse ),
+      iID( KMceNotAssigned )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::CreateLinkL
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::CreateLinkL()
+    {
+    __ASSERT_ALWAYS( State() == ECreated, User::Leave( KErrArgument ) );
+    TBool sequence = KMceSrvStreamDefaultSequence;
+    
+    if ( !UseDefaultStartupSequence() )
+        {
+        sequence = KMceSrvStreamAlternativeSequence;
+        }
+        
+    return sequence;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::PrepareL
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::PrepareL()
+    {
+    __ASSERT_ALWAYS( State() == ELinkCreated, User::Leave( KErrArgument ) );
+    TBool sequence = KMceSrvStreamDefaultSequence;
+    
+    if ( !UseDefaultStartupSequence() )
+        {
+        MCEMM_DEBUG("CMceSrvStream::PrepareL(): alternative prepare");
+        
+        sequence = KMceSrvStreamAlternativeSequence;
+        TMceMccComEvent prepare( KMccStreamPrepared );
+                
+        iSource->EventReceived( prepare );
+        iSink->EventReceived( prepare );
+        
+        MCEMM_DEBUG_STREAM( "CMceSrvStream::PrepareL(): after prepare", *this );
+        }
+    else if ( IsMccPrepared() )
+        {
+        iSource->Data().PrepareL();
+        iSink->Data().PrepareL();
+        }        
+    else
+        {
+        // NOP
+        }
+
+    return sequence;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::StartL
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::StartL()
+    {
+        
+    if ( IsMccPrepared() )
+        {
+        return KMceSrvStreamDefaultSequence;
+        }
+
+    MCEMM_DEBUG("CMceSrvStream::StartL(): alternative start");
+        
+    TMceMccComEvent started( KMccStreamStarted );
+    TMceMccComEvent paused( KMccStreamPaused );
+    
+    if ( iSource->Data().IsEnabled() )
+        {
+        iSource->EventReceived( started );
+        iSource->EnableL( *this, KMceSrvStreamSync );
+        }
+    else
+        {
+        iSource->EventReceived( paused );
+        }
+        
+    if ( iSink->Data().IsEnabled() )
+        {
+        iSink->EventReceived( started );
+        iSink->EnableL( *this, KMceSrvStreamSync );
+        }
+    else
+        {
+        iSink->EventReceived( paused );
+        }
+        
+    MCEMM_DEBUG_STREAM( "CMceSrvStream::StartL(): after start", *this );
+    
+    return KMceSrvStreamAlternativeSequence;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::SynchronizeL
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::SynchronizeL()
+    {    
+        
+    if ( IsMccPrepared() )
+        {
+        return KMceSrvStreamDefaultSequence;
+        }
+
+    MCEMM_DEBUG("CMceSrvStream::SynchronizeL(): alternative synchronize");
+    
+    if ( iSource->Data().IsEnabled() )
+        {
+        iSource->EnableL( *this, KMceSrvStreamSync );
+        }
+    else
+        {
+        iSource->DisableL( *this, KMceSrvStreamSync );
+        }
+        
+    if ( iSink->Data().IsEnabled() )
+        {
+        iSink->EnableL( *this, KMceSrvStreamSync );
+        }
+    else
+        {
+        iSink->DisableL( *this, KMceSrvStreamSync );
+        }
+
+    MCEMM_DEBUG_STREAM( "CMceSrvStream::SynchronizeL(): after synchronize", *this );
+        
+    return KMceSrvStreamAlternativeSequence;
+    
+    }
+
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Stop
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::Stop()
+    {
+        
+    if ( IsMccPrepared() )
+        {
+        return KMceSrvStreamDefaultSequence;
+        }
+        
+    MCEMM_DEBUG("CMceSrvStream::Stop(): alternative stop, stopping source");
+
+    DoEndpointDisable( *iSource );
+  
+    MCEMM_DEBUG("CMceSrvStream::Stop(): alternative stop, stopping sink");
+    
+    DoEndpointDisable( *iSink );
+    
+    // Generating stopped event must be done after disabling
+    TMceMccComEvent stopped( KMccStreamStopped );
+    iSink->EventReceived( stopped );
+    iSource->EventReceived( stopped );
+        
+    MCEMM_DEBUG_STREAM( "CMceSrvStream::Stop(): after stop", *this );
+    return KMceSrvStreamAlternativeSequence;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Validate
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::Validate()
+    {
+    return StreamType() == CMceComMediaStream::ELocalStream;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::UseDefaultStartupSequence
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::UseDefaultStartupSequence()
+    {
+    TBool defaultSequence = ETrue;
+    
+    //special case: local stream, which has camera source and
+    //              diaplay sink
+    if ( StreamType() == CMceComMediaStream::ELocalStream &&
+         iSource->Data().iType == KMceCameraSource &&
+         iSink->Data().iType == KMceDisplaySink )
+        {
+        //try to find stream, which is send stream and it has the
+        //same camera source
+        TMceSrvStreamIterator streams( 
+                Data().Session()->MccStreams(), iSource->Data() );
+                
+        CMceSrvStream* pairedStream = NULL;
+        CMceSrvStream* stream = NULL;
+        while( !pairedStream && streams.Next( stream ) )
+            {
+            pairedStream = 
+                ( stream->StreamType() == CMceComMediaStream::ESendStream ||
+                  stream->StreamType() == CMceComMediaStream::ESendOnlyStream ) ?
+                  stream : NULL;
+            }
+        defaultSequence = MCE_IS_NULL_PTR( pairedStream );
+        if ( !defaultSequence )
+            {
+            static_cast<CMceComDisplaySink&>( iSink->Data() ).SetViewFinder( ETrue );
+            }
+        
+        }
+    
+    return defaultSequence;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::ConstructL( CMceComMediaSource& aSource,
+                               CMceComMediaSink& aSink )
+    {
+    iSource = new (ELeave) CMceSrvSource( *iManager, aSource );
+    iSink = new (ELeave) CMceSrvSink( *iManager, aSink );
+    }
+                   
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::IsMerged
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::IsMerged() const
+    {
+    return iMerged;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::IsMccPrepared
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::IsMccPrepared() const
+    {
+    return iID != KMceNotAssigned;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Merge
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::Merge( CMceSrvStream& aMergeWith, TBool aDeepMerge )
+    {
+    aMergeWith.iMerged = ETrue;
+    
+    iMerged = aMergeWith.iMerged;
+    iID = aMergeWith.iID;
+    iSource->Merge( aMergeWith.Source() );
+    iSink->Merge( aMergeWith.Sink() );
+    Data().SetLinkId( aMergeWith.LinkId() );
+    
+    if ( aDeepMerge )
+        {
+        Data().Merge( aMergeWith.Data() );
+        iCodec->Merge( aMergeWith.Codec() );
+        iSource->Data().Merge( aMergeWith.Source().Data() );
+        iSink->Data().Merge( aMergeWith.Sink().Data() );
+        }
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::IsAdopted
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::IsAdopted() const
+    {
+    return EFalse;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::UnMerge
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::UnMerge()
+    {
+    iMerged = EFalse;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::UnMergeL
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::UnMergeL( CMceSrvStream& aUnMergeFrom )
+    {
+    UnMerge();
+    
+    if ( !IsAdopted() && !aUnMergeFrom.IsAdopted() )
+        {
+        iSource->Merge( aUnMergeFrom.Source() );
+        iSink->Merge( aUnMergeFrom.Sink() );
+        iManager->SynchronizeMccStreamL( *this );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Cleanup
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::Cleanup()
+    {
+    MCEMM_DEBUG("CMceSrvStream::Cleanup(), Entry ");
+
+    if ( iManager->CanReleaseEndpoint( *this, Source().Id() ) )
+        {
+        iManager->ReleaseSource( *this, Source().Id() );
+        }
+        
+    if ( iManager->CanReleaseEndpoint( *this, Sink().Id() ) )
+        {
+        iManager->ReleaseSink( *this, Sink().Id() );
+        }
+
+    MCEMM_DEBUG("CMceSrvStream::Cleanup(), Exit ");        
+    }
+
+
+
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::IsEqual
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::IsEqual( const CMceSrvStream& aStream ) const
+    {
+    TBool equal = EFalse;
+    if ( &aStream )
+        {
+        equal = Codec().Id() == aStream.Codec().Id() &&
+               Source().Data().Id() == aStream.Source().Data().Id() &&
+               Sink().Data().Id() == aStream.Sink().Data().Id();
+        }
+    
+    return equal;
+            
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Consumes
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::Consumes( const TMceMccComEvent& aEvent ) const
+    {
+    TBool match = EFalse;
+    
+    if ( State() != EAdopted )
+        {
+        if ( aEvent.iStreamId )
+            {
+            match = iID == aEvent.iStreamId;
+            }
+        else if ( aEvent.iEndpointId )
+            {
+            match = LinkId() == aEvent.iLinkId &&
+                    ( Sink().Id() == aEvent.iEndpointId ||
+                      Source().Id() == aEvent.iEndpointId );
+            }
+        else 
+            {
+            match = LinkId() == aEvent.iLinkId;
+            }
+        }
+    
+    return match;
+    }
+ 
+ // -----------------------------------------------------------------------------
+// CMceSrvStream::DtmfHandlerL
+// -----------------------------------------------------------------------------
+//   
+CMceDtmfHandler& CMceSrvStream::DtmfHandlerL( CMccInterface& aMccInterface )
+    {
+    __ASSERT_ALWAYS( MccStreamType() == KMccDtmfStream, 
+                     User::Leave( KErrNotFound ) );
+    
+    if ( !iDtmfHandler )
+        {
+        iDtmfHandler = CMceDtmfHandler::NewL( *this, aMccInterface );
+        }
+        
+    return *iDtmfHandler;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::UpdateEndpointStates
+// -----------------------------------------------------------------------------
+//    
+void CMceSrvStream::UpdateEndpointStates( 
+    TBool aSinkAffected, 
+    TBool aSourceAffected, 
+    TBool aIsEnabled )
+    {
+    MCEMM_DEBUG_DVALUES( "CMceSrvStream::UpdateEndpointStates, sink affected:", 
+                         aSinkAffected,
+                         " source affected:",
+                         aSourceAffected )
+    MCEMM_DEBUG_DVALUE( "CMceSrvStream::UpdateEndpointStates, enabled:", 
+                        aIsEnabled )
+    
+    if ( aSinkAffected )
+        {
+        Sink().Data().Enabled( aIsEnabled );
+        }
+    if ( aSourceAffected )
+        {
+        Source().Data().Enabled( aIsEnabled );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::EndpointMatch
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::EndpointMatch( 
+    const CMceComEndpoint& aEndpoint, 
+    TBool aUseProxyMatch )
+    {
+    CMceSrvEndpoint* srvEndpoint = NULL;
+    if ( aEndpoint.Category() == KMceCategorySource )
+        {
+        srvEndpoint = &Source();
+        }
+    else
+        {
+        srvEndpoint = &Sink();
+        }
+    return srvEndpoint->EndpointMatch( aEndpoint, aUseProxyMatch );
+    }
+       
+// -----------------------------------------------------------------------------
+// CMceSrvStream::~CMceSrvStream
+// -----------------------------------------------------------------------------
+//
+CMceSrvStream::~CMceSrvStream()
+    {
+    delete iDtmfHandler;
+    delete iSource;
+    delete iSink;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::SessionId
+// -----------------------------------------------------------------------------
+//
+TUint32 CMceSrvStream::SessionId() const
+    {
+    return Data().Session()->iMccID;
+    }
+
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::LinkId
+// -----------------------------------------------------------------------------
+//
+TUint32 CMceSrvStream::LinkId() const
+    {
+    TUint32 linkId = Data().iLinkId;
+    return linkId == 0 ? KMceNotAssigned : linkId;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::SetLinkId
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::SetLinkId( TUint32 aLinkId )
+    {
+    Data()().SetLinkId( aLinkId );
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::IapId
+// -----------------------------------------------------------------------------
+//
+TUint32 CMceSrvStream::IapId() const
+    {
+    return Data().Session()->iIapId;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::LocalMediaPort
+// -----------------------------------------------------------------------------
+//
+TUint CMceSrvStream::LocalMediaPort() const
+    {
+    return Data().LocalMediaPort();
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::SetLocalMediaPort
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::SetLocalMediaPort( TUint aPort )
+    {
+    return Data().SetLocalMediaPort( aPort );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::RemoteIpAddress
+// -----------------------------------------------------------------------------
+//
+TInetAddr CMceSrvStream::RemoteIpAddress() const
+    {
+    TInetAddr remoteAddress = Data().Session()->iRemoteIpAddress;
+    remoteAddress.SetPort( Data().RemoteMediaPort() );
+    return remoteAddress;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Id
+// -----------------------------------------------------------------------------
+//
+TUint32& CMceSrvStream::Id()
+    {
+    return iID;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Data
+// -----------------------------------------------------------------------------
+//
+CMceComMediaStream& CMceSrvStream::Data() const
+    {
+    return *iData;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Source
+// -----------------------------------------------------------------------------
+//
+CMceSrvSource& CMceSrvStream::Source() const
+    {
+    return *iSource;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Sink
+// -----------------------------------------------------------------------------
+//
+CMceSrvSink& CMceSrvStream::Sink() const
+    {
+    return *iSink;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Codec
+// -----------------------------------------------------------------------------
+//
+CMceComCodec& CMceSrvStream::Codec() const
+    {
+    return *iCodec;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Invalidate
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::Invalidate()
+    {
+    MCEMM_DEBUG("CMceSrvStream::Invalidate(), Entry ");
+
+    TMceMccComEvent invalidate( KMccStreamStopped, 
+                                Data().iLinkId, iID, 0 );
+                                
+    EventReceived( invalidate, KMceSrvStreamNoCallback );
+    MCEMM_DEBUG("CMceSrvStream::Invalidate(), Exit ");
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::EventReceived
+// -----------------------------------------------------------------------------
+//
+TInt CMceSrvStream::EventReceived( TMceMccComEvent& aEvent, TBool aCallback )
+    {
+
+    MCEMM_DEBUG("CMceSrvStream::EventReceived(), Entry ");
+    MCEMM_DEBUG_DVALUE("event", aEvent.iEvent );
+    MCEMM_DEBUG_DVALUE("callback", aCallback );
+    
+    TInt status = KMceEventConsumed;
+        
+    if ( aEvent.iEvent == KMccLinkCreated )
+        {
+        if ( State() == ECreatingLink ) //might be inactive
+            {
+            iSource->EventReceived( aEvent );
+            iSink->EventReceived( aEvent );
+            TPckgBuf<TMccNetSettings> netSettingsBuf;
+            netSettingsBuf.Copy( *aEvent.iItcDataDesC );
+            TMccNetSettings netSettings = netSettingsBuf();
+            SetLocalMediaPort( netSettings.iLocalAddress.Port() );
+            Data().Session()->iServiceType = netSettings.iMediaQosValue;
+            TMceSrvStreamIterator streams( Data().Session()->MccStreams(), 
+                                           Data() );
+            CMceSrvStream* stream = NULL;
+            if ( !streams.Next( stream, ECreatingLink ) )
+                {
+                // If all created, update client side
+                Data().EventReceived( aEvent );
+                }
+            }
+        }
+    else if ( IsMccPrepared() ||
+              aEvent.iLinkId == Data().iLinkId )
+        {
+        aEvent.iCodec = iCodec;
+        aEvent.iSource = aEvent.iEndpointId > 0 && iSource->Id() == aEvent.iEndpointId ? 
+                         &iSource->Data() : NULL;
+        aEvent.iSink = aEvent.iEndpointId > 0 && iSink->Id() == aEvent.iEndpointId ? 
+                       &iSink->Data() : NULL;
+
+        if ( aEvent.iSource )
+            {
+            iSource->EventReceived( aEvent );
+            }
+        else if ( aEvent.iSink )
+            {
+            iSink->EventReceived( aEvent );
+            }
+        else
+            {
+            iSource->EventReceived( aEvent );
+            iSink->EventReceived( aEvent );
+            }
+        
+        TBool allowEvent( ETrue );
+        if ( MCE_MCC_STREAM_STATE_CHANGE_EVENT( aEvent ) )
+            {
+            allowEvent = StreamStateChangeEventReceived( aEvent );
+            }
+        
+        if ( Data().iState == CMceMediaStream::EDisabled &&
+             aEvent.iEvent == KMccStreamError &&
+             aEvent.iError == KErrHostUnreach )
+            {
+            allowEvent = EFalse;
+            }
+        
+        if ( allowEvent )
+            {
+            Data().SetState( aEvent );
+            if ( aCallback )
+                {
+                Data().EventReceived( aEvent );
+                }
+            }
+        }
+    else //if 'local' stream
+        {
+        iSource->EventReceived( aEvent );
+        iSink->EventReceived( aEvent );
+        }
+
+    MCEMM_DEBUG_STREAM( "CMceSrvStream::EventReceived(): after received", *this );
+    MCEMM_DEBUG("CMceSrvStream::EventReceived(), Exit ");
+
+    return status;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::RequireSignalling
+// -----------------------------------------------------------------------------
+//
+TInt CMceSrvStream::RequireSignalling( CMceSrvStream& aCurrent,
+                                        CMccCodecInformation& aMccCurentCodec, 
+                                        CMccCodecInformation& aMccUpdateCodec ) const
+    {
+    MCEMM_DEBUG("CMceSrvStream::RequireSignalling(), Entry ");
+    
+    TInt action = KMceNoSignalling;
+    
+    if ( Codec().MccRequireSignalling( *this, aMccCurentCodec, aMccUpdateCodec ) )
+        {
+        MCEMM_DEBUG("CMceSrvStream::RequireSignalling(): codec requires signalling");
+        action = KMceRequiresSignalling;
+        }
+    else if ( LocalMediaPort() != aCurrent.LocalMediaPort() ||
+              Data().RemoteMediaPortChanged( aCurrent.Data().RemoteMediaPort() ) )
+    //local port has changed => needs new media session & signaling
+        {
+        MCEMM_DEBUG("CMceSrvStream::RequireSignalling(): local port changed. requires signalling");
+        action = KMceRequiresSignalling;
+        }
+        
+    else if ( Data().RemoteRTCPAddressChanged(aCurrent.Data().iRemoteRtcpPort, 
+    		 	aCurrent.Data().iRemoteRtcpAddress))
+    		  
+    	{
+    	MCEMM_DEBUG("CMceSrvStream::RequireSignalling(): Remote Rtcp Port changed, requires signalling");
+        action = KMceRequiresSignalling;
+    	}
+        
+    else if ( Data().iIsEnabled != aCurrent.Data().iIsEnabled )
+    //hold or resume => just SIP signaling
+        {
+        MCEMM_DEBUG("CMceSrvStream::RequireSignalling(): hold/resume detected. requires signalling");
+        action = KMceRequiresSipSignallingOnly;
+        }
+    else
+        {
+        MCEMM_DEBUG("CMceSrvStream::RequireSignalling(): requires no signalling");
+        //NOP
+        }
+        
+    MCEMM_DEBUG("CMceSrvStream::RequireSignalling(), Exit ");
+    return action;
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::RequireSignalling
+// -----------------------------------------------------------------------------
+//
+TInt CMceSrvStream::RequireSignalling( 
+    RPointerArray<CMceSrvStream>& /*aUpdateStreams*/ ) const
+    {
+    TInt action = KMceRequiresSignalling;
+    
+    //local stream added or removed => no signalling
+    if ( StreamType() == CMceComMediaStream::ELocalStream )
+        {
+        action = KMceNoSignalling;
+        }
+    //enabled stream
+    else if ( !IsMccPrepared() )
+        {
+        action = KMceRequiresSipSignallingOnly;
+        }
+    return action;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::State
+// -----------------------------------------------------------------------------
+//
+CMceSrvStream::TState CMceSrvStream::State() const
+    {
+    
+    CMceSrvStream::TState state = EInactive;
+        
+    if ( iSource->State() == ECreated &&
+         iSink->State() == ECreated &&
+         Data().IsEnabled() )
+        {
+        state = ECreated;
+        }
+    else if ( iSource->State() == EStopped &&
+              iSink->State() == EStopped  )
+        {
+        state = EStopped;
+        }
+    else if ( iSource->State() == EPending && 
+              iSink->State() == EPending )
+        {
+        state = EPending;
+        }
+    else if ( iSource->State() == ECreatingLink || 
+              iSink->State() == ECreatingLink )
+        {
+        state = ECreatingLink;
+        }
+    else if ( iSource->State() == EPreparing || 
+              iSink->State() == EPreparing )
+        {
+        state = EPreparing;
+        }
+    else if ( iSource->State() == EStarting || 
+              iSink->State() == EStarting )
+        {
+        state = EStarting;
+        }
+    else if ( iSource->State() == ELinkCreated ||
+              iSink->State() == ELinkCreated  )
+        {
+        state = ELinkCreated;
+        }
+    else if ( iSource->State() == EPrepared ||
+              iSink->State() == EPrepared  )
+        {
+        state = EPrepared;
+        }
+    else if ( iSource->State() >= EStarted ||
+              iSink->State() >= EStarted  )
+        {
+        state = EStarted;
+        }
+    else
+        {
+        state = EInactive;
+        }
+        
+    return state;
+            
+    }
+
+
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::MccPrepareCalledL
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::MccPrepareCalledL()
+    {
+    iSource->MccPrepareCalledL( *this );
+    iSink->MccPrepareCalledL( *this );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::MccStreamType
+// -----------------------------------------------------------------------------
+//
+TInt CMceSrvStream::MccStreamType() const
+    {
+    if ( iCodec->iSdpName.CompareF( KMceSDPNameDtmf ) == 0 )
+        {
+        return KMccDtmfStream;
+        }
+    return iData->MccStreamType();
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::StreamType
+// -----------------------------------------------------------------------------
+//
+CMceComMediaStream::TStreamType CMceSrvStream::StreamType() const
+    {
+    return iData->iStreamType;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::Direction
+// -----------------------------------------------------------------------------
+//
+CMceComMediaStream::TStreamType CMceSrvStream::Direction() const
+    {
+    CMceComMediaStream::TStreamType type = StreamType();
+    TInt direction = iData->Direction();
+    if ( direction == SdpCodecStringConstants::EAttributeRecvonly )
+        {
+        type = type == CMceComMediaStream::EReceiveStream ? 
+                       CMceComMediaStream::EReceiveOnlyStream : type;
+        }
+    else if ( direction == SdpCodecStringConstants::EAttributeSendonly )
+        {
+        type = type == CMceComMediaStream::ESendStream ? 
+                       CMceComMediaStream::ESendOnlyStream : type;
+        }
+    else
+        {
+        }
+        
+    return type;
+    }
+        
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::LinkType
+// -----------------------------------------------------------------------------
+//
+TInt CMceSrvStream::LinkType() const
+    {
+    return iData->MccLinkType();
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::EventReceived
+// -----------------------------------------------------------------------------
+//
+CMceSrvStream* CMceSrvStream::EventReceived( RPointerArray<CMceSrvStream>& aStreams,
+                                             TMceMccComEvent& aEvent,
+                                             TBool aConsumeOnlyOnce )
+    {
+    TMceSrvStreamIterator iterator( aStreams );
+    CMceSrvStream* stream = NULL;
+    CMceSrvStream* firstMatch = NULL;
+    
+    TBool propagate( ETrue );
+    while( iterator.Next( stream, aEvent ) && propagate )
+        {
+        propagate = ( stream->EventReceived( aEvent ) == KMceEventConsumed ) ? 
+            ( !aConsumeOnlyOnce ) : ETrue;
+        firstMatch = !firstMatch ? stream : firstMatch;
+        }
+    
+    return firstMatch;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::StreamStateChangeEventReceived
+// -----------------------------------------------------------------------------
+//
+TBool CMceSrvStream::StreamStateChangeEventReceived( TMceMccComEvent& aEvent )
+    {
+    TBool allowEvent( ETrue );
+
+    switch ( aEvent.iEvent )
+        {
+        case KMccStreamStarted:
+        case KMccStreamPaused:
+        case KMccStreamResumed:
+            {
+            // Client side is not affected until all mcc streams are on same
+            // level
+            if ( aEvent.iSource )
+                {
+                allowEvent = iSource->StreamStateChangeEventReceived( aEvent );
+                }
+            else if ( aEvent.iSink )
+                {
+                allowEvent = iSink->StreamStateChangeEventReceived( aEvent );
+                }
+            else
+                {
+                // It might be that only another endpoint can be informed,
+                // in that case modify the event
+                TBool allowSourceEvent = iSource->StreamStateChangeEventReceived( aEvent );
+                aEvent.iSource = allowSourceEvent ? aEvent.iSource : 0;
+                TBool allowSinkEvent = iSink->StreamStateChangeEventReceived( aEvent );
+                aEvent.iSink = allowSinkEvent ? aEvent.iSink : 0;
+                allowEvent = ( allowSourceEvent || allowSinkEvent );
+                }
+            break;
+            }
+        case KMccStreamStopped:
+            {
+            // Special handling for stopped events, all streams associated with
+            // the source and sink has to be stopped before state can be updated
+            // 
+            TMceSrvStreamIterator streams( Data().Session()->MccStreams(), 
+                                           iSource->Data() );
+            CMceSrvStream* stream = NULL;
+            if ( streams.Next( 
+                        stream,
+                        CMceSrvStream::EStopped, 
+                        TMceSrvStreamIterator::ExactReverseMatch ) )
+                {
+                allowEvent = EFalse;
+                }
+                
+            TMceSrvStreamIterator streams2( Data().Session()->MccStreams(), 
+                                            iSink->Data() );
+            stream = NULL;
+            if ( allowEvent && streams2.Next( 
+                        stream,
+                        CMceSrvStream::EStopped, 
+                        TMceSrvStreamIterator::ExactReverseMatch ) )
+                {
+                allowEvent = EFalse;
+                }
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+        
+    return allowEvent;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSrvStream::DoEndpointDisable
+// -----------------------------------------------------------------------------
+//
+void CMceSrvStream::DoEndpointDisable( CMceSrvEndpoint& aEndpoint )
+    {
+    // Disable only if all corresponding endpoints are stopped 
+    //
+    TMceSrvStreamIterator streams( Data().Session()->MccStreams(), 
+                                   aEndpoint.Data(),
+                                   KMceComNoProxyMatch,
+                                   TMceSrvStreamIterator::ELocal );
+    
+    CMceSrvStream* stream = NULL;
+    TBool allowDisable( ETrue );
+    while ( streams.Next( stream ) && allowDisable )
+        {
+        if ( stream != this && 
+             aEndpoint.Endpoint( *stream ).State() != CMceSrvStream::EStopped )
+            {
+            MCEMM_DEBUG("CMceSrvStream::DoEndpointDisable(): stopping not yet allowed");
+            allowDisable = EFalse;
+            }   
+        }    
+       
+    if ( allowDisable )
+        {
+        TRAP_IGNORE( 
+            aEndpoint.DisableL( *this, KMceSrvStreamNoSync, KMceSrvStreamForce ) );
+        }
+    }
+    
+// End of file