diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccrtpsourcesink/src/mccrtpdatasink.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommscontroller/mmccrtpsourcesink/src/mccrtpdatasink.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,852 @@ +/* +* Copyright (c) 2002-2004 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: RTP Datasink +* +*/ + + + + +// INCLUDE FILES +#include + +#include "rtpheader.h" +#include +#include + +#include "mccrtpdatasink.h" +#include "mmccevents.h" +#include "mccinternaldef.h" +#include "mccrtpdefs.h" +#include "mmccinterfacedef.h" +#include "mccrtpmediaclock.h" + +// MACROS + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS +#define MCC_RTPSINK_ENDPOINT_ID MCC_ENDPOINT_ID( static_cast( this ) ) + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::CMccRtpDataSink +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CMccRtpDataSink::CMccRtpDataSink() : + CMccDataSink( KMccRtpSinkUid ), + MMccRtpInterface(), iRtpStreamId( KNullId ) + { + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::NewSinkL +// Static constructor. +// ----------------------------------------------------------------------------- +// +MDataSink* CMccRtpDataSink::NewSinkL( TUid /*aImplementationUid*/, + const TDesC8& /*aInitData*/ ) + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::NewSinkL()" ) + + CMccRtpDataSink* self = new ( ELeave ) CMccRtpDataSink(); + return static_cast( self ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::ConstructSinkL +// class MDataSink inherited 2nd phase construction +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::ConstructSinkL( const TDesC8& aInitData ) + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::ConstructSinkL" ) + + SetStateL( ERtpStateConstructed ); + + TInt res = aInitData.Compare( KNullDesC8 ); + if ( 0 != res ) + { + TRACE_RTP_SOURCE_PRINT( "CMccRtpDataSink::ConstructSinkL KErrArgument" ) + + User::Leave( KErrArgument ); + } + + #ifdef FTD_ENABLED + TInt err = iStreamStatsQueue.OpenGlobal( KMccStreamStats, EOwnerProcess ); + if ( KErrNone != err ) + { + User::Leave( err ); + } + #endif + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::~CMccRtpDataSink +// Destructor +// ----------------------------------------------------------------------------- +// +CMccRtpDataSink::~CMccRtpDataSink() + { + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::~CMccRtpDataSink 0x%x", this ) + + // We don't own this + iEventHandler = NULL; + + CloseStreams(); + + iDataSource = NULL; + iBufferToBeEmptied = NULL; + + iUsers.Close(); + + delete iSender; + + #ifdef FTD_ENABLED + iStreamStatsQueue.Close(); + #endif + } + + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SetCurrentUser +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SetCurrentUser( MAsyncEventHandler* aEventHandler ) + { + iEventHandler = aEventHandler; + } + + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::Mute +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::Mute( TBool aMuteOn, TUint8 aExceptionPt ) + { + TRACE_RTP_SINK_PRINT3( "CMccRtpDataSink::Mute, ENABLED: %d, PT: %u", + aMuteOn, aExceptionPt ) + + iMuteOn = aMuteOn; + iExceptionPt = aExceptionPt; + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SinkThreadLogon +// +// Method to 'logon' the data sink to the same thread that sink will be consuming +// data in. Thread specific initialisation is done here. +// ----------------------------------------------------------------------------- +// +TInt CMccRtpDataSink::SinkThreadLogon( MAsyncEventHandler& aEventHandler ) + { + TRACE_RTP_SINK_PRINT ( "CMccRtpDataSink::SinkThreadLogon" ) + + if ( FindRtpUserEntryForCurrent( aEventHandler ) ) + { + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SinkThreadLogon, ERR: %d", KErrAlreadyExists ) + return KErrAlreadyExists; + } + + TMccRtpUser user( &aEventHandler ); + TInt err = iUsers.Append( user ); + + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SinkThreadLogon, exit with err: %d", err ) + + return err; + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SinkThreadLogoff +// +// Method to 'logoff' the data sink from the same thread that sink consumes +// data in. Thread specific releasing of resources is done here. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SinkThreadLogoff() + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkThreadLogoff" ) + + RemoveCurrentRtpUser(); + + SetCurrentUser( NULL ); + + if ( 0 == iUsers.Count() ) + { + // SinkThreadLogoff may be called while not stopped, so don't + // bother checking any states here. SinkThreadLogoff means that the + // thread is going down, so we must cleanup here... + + StopKeepalive(); + CloseStreams(); + iRtpAPI = NULL; + iRtpStreamId = KNullId; + iUsers.Close(); + + delete iSender; + iSender = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SetSinkDataTypeCode +// Sets the datatype code ( codec ) +// ----------------------------------------------------------------------------- +// +TInt CMccRtpDataSink::SetSinkDataTypeCode( TFourCC aCodec, TMediaId aMedia ) + { + if ( KUidMediaTypeAudio == aMedia.iMediaType || + KUidMediaTypeVideo == aMedia.iMediaType ) + { + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SetSinkDataTypeCode, mediatype:%d", + aMedia.iMediaType.iUid ) + iMedia = aMedia; + iCodecInfo.iFourCC = aCodec; + return KErrNone; + } + else + { + return KErrNotSupported; + } + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SinkDataTypeCode +// Returns the datatype code ( codec ) +// ----------------------------------------------------------------------------- +// +TFourCC CMccRtpDataSink::SinkDataTypeCode( TMediaId aMediaId ) + { + if ( KUidMediaTypeAudio == aMediaId.iMediaType || + KUidMediaTypeVideo == aMediaId.iMediaType ) + { + return iCodecInfo.iFourCC; + } + else + { + // Initializes to KMMFFourCCCodeNULL so the caller cannot see + // if this sink really has some media type currently registered + return TFourCC(); + } + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::EmptyBufferL +// NOT SUPPORTED. MDataSink pure virtual function must be implemented. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::EmptyBufferL( CMMFBuffer* /*aBuffer*/, + MDataSource* /*aSupplier*/, + TMediaId /*aMediaId*/ ) + { + User::Leave( KErrNotSupported ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::EmptyBufferL +// Overload to class MDataSink pure virtual function implementation. +// Take RTP packet in the buffer and send it. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::EmptyBufferL( CMMFBuffer* aBuffer, + MDataSource* aSupplier, + TMediaId /*aMediaId*/, + TRtpSendHeader& aHeaderInfo ) + { + __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); + this->CheckBufferSupportL( aBuffer ); + User::LeaveIfNull( aSupplier ); + + if ( SendingAllowed( aHeaderInfo ) ) + { + __ASSERT_ALWAYS( iSender, User::Leave( KErrNotReady ) ); + + TRACE_RTP_SINK_PRINT3( + "CMccRtpDataSink::EmptyBufferL, timestamp: %d, datalen: %d", + aHeaderInfo.iTimestamp, aBuffer->BufferSize() ) + + iBufferToBeEmptied = static_cast( aBuffer ); + + iSender->SendRtpPacketL( iRtpStreamId, + aHeaderInfo, + iBufferToBeEmptied->Data() ); + ResetKeepaliveTimer(); + } + else + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::EmptyBufferL, PACKET DROPPED" ) + } + + // Buffer is emptied, notify the caller so it can reuse the buffer. + // We risk a dead lock if we don't do this if the supplier relies on this + // callback. + aSupplier->BufferEmptiedL( aBuffer ); + + #ifdef FTD_ENABLED + TMccStreamStats stats; + stats.iPacketsSent = ++iPacketsSent; + stats.SetFieldUpdatedFlag( EPacketsSent ); + iStreamStatsQueue.Send( stats ); + #endif + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::BufferFilledL +// NOT SUPPORTED. MDataSink pure virtual function must be implemented. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::BufferFilledL( CMMFBuffer* /*aBuffer*/ ) + { + // DataSource calls synchronously CMccRtpDataSink->EmptyBuffer(), + // so DataSource->FillBuffer, CMccRtpDataSink->BufferFilledL chain is not used at the moment + User::Leave( KErrNotSupported ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::CanCreateSinkBuffer +// NOT SUPPORTED. MDataSink pure virtual function must be implemented. +// ----------------------------------------------------------------------------- +// +TBool CMccRtpDataSink::CanCreateSinkBuffer() + { + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::CreateSinkBufferL +// NOT SUPPORTED. MDataSink pure virtual function must be implemented. +// ----------------------------------------------------------------------------- +// +CMMFBuffer* CMccRtpDataSink::CreateSinkBufferL( TMediaId /*aMediaId*/, + TBool& /*aReference*/ ) + { + User::Leave( KErrNotSupported ); + return NULL; + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SinkPrimeL +// Prime the sink. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SinkPrimeL() + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPrimeL" ) + + SetStateL( ERtpStatePrimed ); + + // Start sending keep alive packets. Secure session has to wait until + // secure stream is created + if ( !iSecSession ) + { + StartKeepaliveL( *iRtpMediaClock ); + } + + SendStreamEventToClient( KMccStreamPrepared ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SinkPlayL +// Start the playout operation. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SinkPlayL() + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPlayL IN" ) + if ( iSecureKeyExpired ) + { + TRACE_RTP_SINK_PRINT( "Leave becuase the secure key expired" ) + User::Leave( KErrGeneral ); + } + TMccRtpUser* user = FindRtpUserEntryForCurrent( *iEventHandler ); + __ASSERT_ALWAYS( user, User::Leave( KErrNotReady ) ); + + SetStateL( ERtpStatePlaying ); + + if ( user->iStartedOnce ) + { + SendStreamEventToClient( KMccStreamResumed ); + } + else + { + SendStreamEventToClient( KMccStreamStarted ); + user->iStartedOnce = ETrue; + } + + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPlayL OUT" ) + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SinkPauseL +// Pauses the playout operation. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SinkPauseL() + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPauseL" ) + + SetStateL( ERtpStatePaused ); + + + iSender->Clear(); + + SendStreamEventToClient( KMccStreamPaused ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SinkStopL +// Stop the playout operation. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SinkStopL() + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkStopL" ) + + SetStateL( ERtpStateStopped ); + + StopKeepalive(); + + iSender->Clear(); + + SendStreamEventToClient( KMccStreamStopped ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SendMediaSignallingL() +// Sends media level signalling +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SendMediaSignallingL( const TMccEvent& aEvent ) + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL" ) + + __ASSERT_ALWAYS( aEvent.iEventCategory == KMccEventCategoryRtcp && + aEvent.iEventType == KMccRtcpControl && + iEnableRtcp, + User::Leave( KErrNotSupported ) ); + + __ASSERT_ALWAYS( iRtpAPI, User::Leave( KErrNotReady ) ); + + const TMccRtcpEventData& rtcpEvent = + (*reinterpret_cast( + &aEvent.iEventData ))(); + + switch ( rtcpEvent.iRtcpPacketType ) + { + case KRtcpSdesPacket: + { + TPckgBuf package; + package.Copy( rtcpEvent.iRtcpPacketData ); + iRtpAPI->SetLocalSdes( package() ); + break; + } + case KRtcpByePacket: + { + __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); + User::LeaveIfError( + iRtpAPI->SendRtcpByePacket( iRtpStreamId, + rtcpEvent.iRtcpPacketData ) ); + break; + } + case KRtcpAppPacket: + { + __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); + + TPckgBuf package; + package.Copy( rtcpEvent.iRtcpPacketData ); + + User::LeaveIfError( + iRtpAPI->SendRtcpAppPacket( iRtpStreamId, package() ) ); + + break; + } + case KRtcpSrPacket: + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL, SR" ) + + __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); + User::LeaveIfError( iRtpAPI->SendRtcpSrPacket( iRtpStreamId ) ); + break; + } + case KRtcpAnyPacket: + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL, FC" ) + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SendMediaSignallingL, sessionid:%d", + iSessionID ) + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SendMediaSignallingL, datalen: %d", + rtcpEvent.iRtcpPacketData.Length() ) + + __ASSERT_ALWAYS( iSender, User::Leave( KErrNotReady ) ); + TBool useRTPSocket( EFalse ); + iSender->SendDataL( iSessionID, + useRTPSocket, + rtcpEvent.iRtcpPacketData ); + break; + } + default: + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL, default" ) + User::Leave( KErrArgument ); + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::DoCreateStreamL +// Creates a transmit stream. +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::DoCreateStreamL() + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL IN" ) + __ASSERT_ALWAYS( KNullId == iRtpStreamId, User::Leave( KErrAlreadyExists ) ); + __ASSERT_ALWAYS( NULL != iRtpAPI, User::Leave( KErrNotReady ) ); + + if ( !iSender ) + { + // Can do marker based cleanup only with video stream + TBool doMarkerBasedCleanup( iMedia.iMediaType == KUidMediaTypeVideo ); + iSender = CMccRtpSender::NewL( + *this, *iRtpAPI, iSessionID, doMarkerBasedCleanup ); + } + + TTranStreamParams transParams; + transParams.iPayloadType = iCodecInfo.iPayloadType; + iRtpStreamId = + iRtpAPI->CreateTransmitStreamL( iSessionID, transParams, iSSRC ); + + if ( KNullId == iRtpStreamId ) + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL KErrCouldNotConnect 1" ) + + User::Leave( KErrCouldNotConnect ); + } + + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL SetSamplingRate 1" ) + + User::LeaveIfError( iRtpAPI->SetSamplingRate( + iCodecInfo.iPayloadType, KDefSampleRate ) ); + + if ( KMccPayloadTypeMax != iCodecInfo.iRedundantPayload ) + { + User::LeaveIfError( iRtpAPI->SetSamplingRate( + iCodecInfo.iRedundantPayload, KDefSampleRate ) ); + } + + DoCreateSrtpStreamL(); + + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL OUT" ) + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SendErrorOccured +// Asynchronous sending error occured +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SendErrorOccured( TInt aError ) + { + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SendErrorOccured, err: %d", aError ) + + SendInternalRtpEventToAllClients( iUsers, + KMccRtpSinkUid, + EMccInternalRtpSinkError, + KMccStreamError, + MCC_RTPSINK_ENDPOINT_ID, + aError ); + + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendErrorOccured, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::DoCreateSrtpStreamL +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::DoCreateSrtpStreamL() + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateSrtpStreamL IN" ) + if ( !iSrtpStream && iContext && iSecSession && KNullId != iRtpStreamId ) + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateSrtpStreamL, creating" ) + iSrtpStream = CSRTPStreamOut::NewL( + *iSecSession, static_cast( iSSRC ), iContext, *this ); + + // Now it's possible to send keepalive + StartKeepaliveL( *iRtpMediaClock ); + } + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateSrtpStreamL OUT" ) + } + +// --------------------------------------------------------------------------- +// CMccRtpDataSink::SinkCustomCommand() +// +// --------------------------------------------------------------------------- +// +void CMccRtpDataSink::SinkCustomCommand( TMMFMessage& aMessage ) + { + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SinkCustomCommand - FUNCTION: %d", + aMessage.Function() ) + + TInt result( KErrNone ); + aMessage.Complete( result ); + } + +// --------------------------------------------------------------------------- +// CMccRtpDataSink::SendRTCPData() +// Sends Non-RTCP data +// --------------------------------------------------------------------------- +// +void CMccRtpDataSink::SendRTCPDataL( const TDesC8& aData ) + { + if ( iRtpAPI && iSender ) + { + TBool useRTPSocket( EFalse ); + iSender->SendDataL( iSessionID, useRTPSocket, aData ); + } + else + { + User::Leave( KErrNotReady ); + } + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::HandleBySsrc +// ----------------------------------------------------------------------------- +// +TBool CMccRtpDataSink::HandleBySsrc( const TRtpSSRC& aSsrc ) + { + return ( iSSRC == aSsrc ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::RtpStreamId +// ----------------------------------------------------------------------------- +// +TRtpId CMccRtpDataSink::RtpStreamId() + { + return iRtpStreamId; + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::IsSink +// ----------------------------------------------------------------------------- +// +TBool CMccRtpDataSink::IsSink() const + { + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::IsSending +// ----------------------------------------------------------------------------- +// +TBool CMccRtpDataSink::IsSending() const + { + return ( ERtpStatePlaying == State() ); + } + +// ----------------------------------------------------------------------------- +// CMccRtpDataSink::SendStreamEventToClient() +// ----------------------------------------------------------------------------- +// +void CMccRtpDataSink::SendStreamEventToClient( + TMccEventType aEventType, + TInt aError ) + { + TRACE_RTP_SOURCE_PRINT( "CMccRtpDataSink::SendStreamEventToClient" ) + + if ( iEventHandler ) + { + TMccEvent event( 0, + 0, + 0, + MCC_ENDPOINT_ID( static_cast( this ) ), + KMccEventCategoryStream, + aEventType, + aError, + KNullDesC8 ); + + TMccInternalEvent internalEvent( KMccRtpSinkUid, + EMccInternalEventNone, + event ); + + iEventHandler->SendEventToClient( internalEvent ); + } + else + { + TRACE_RTP_SOURCE_PRINT( "CMccRtpDataSink::SendStreamEventToClient, \ + iEventHandler=NULL" ) + } + } + +// --------------------------------------------------------------------------- +// CMccRtpDataSink::FindRtpUserEntryForCurrent +// --------------------------------------------------------------------------- +// +TMccRtpUser* CMccRtpDataSink::FindRtpUserEntryForCurrent( + MAsyncEventHandler& aEventHandler ) + { + TMccRtpUser entry( &aEventHandler ); + TIdentityRelation comparison( RtpUserMatch ); + TInt index = iUsers.Find( entry, comparison ); + if ( index != KErrNotFound ) + { + return &iUsers[ index ]; + } + return NULL; + } + +// --------------------------------------------------------------------------- +// CMccRtpDataSink::RemoveCurrentRtpUser +// --------------------------------------------------------------------------- +// +void CMccRtpDataSink::RemoveCurrentRtpUser() + { + TMccRtpUser entry( iEventHandler ); + TIdentityRelation comparison( RtpUserMatch ); + TInt index = iUsers.Find( entry, comparison ); + if ( index != KErrNotFound ) + { + iUsers.Remove( index ); + } + } + +// --------------------------------------------------------------------------- +// CMccRtpDataSink::RtpUserMatch +// --------------------------------------------------------------------------- +// +TBool CMccRtpDataSink::RtpUserMatch( + const TMccRtpUser& aUser1, + const TMccRtpUser& aUser2 ) + { + // First argument is always the search term + + TBool match( EFalse ); + if ( aUser1.iEventHandler ) + { + match = ( aUser1.iEventHandler == aUser2.iEventHandler ); + } + return match; + } + +// --------------------------------------------------------------------------- +// CMccRtpDataSink::SendingAllowed +// --------------------------------------------------------------------------- +// +TBool CMccRtpDataSink::SendingAllowed( + const TRtpSendHeader& aHeaderInfo ) const + { + // If secure session, srtp stream has to exist + TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::Sending allowed iSecureKeyExpired = ", + iSecureKeyExpired ) + + TBool isPayloadMuted + = iMuteOn ? aHeaderInfo.iPayloadType != iExceptionPt : EFalse; + + return ( ERtpStatePlaying == State() && + ( !iSecSession || iSrtpStream ) && + !iSecureKeyExpired && + !isPayloadMuted ); + } + +// --------------------------------------------------------------------------- +// CMccRtpDataSink::SetMediaClock +// --------------------------------------------------------------------------- +// +void CMccRtpDataSink::SetMediaClock( CMccRtpMediaClock& aRtpMediaClock ) + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SetMediaClock" ) + + if ( !iRtpMediaClock ) + { + iRtpMediaClock = &aRtpMediaClock; + } + else + { + TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SetMediaClock - Allready set!" ) + } + } + +// --------------------------------------------------------------------------- +// FROM SRTP API +// This function is called by SRTP Stream initiated with +// MSRTPReKeyingObserver when a master key is stale and needs +// to be refreshed. +// --------------------------------------------------------------------------- +// +void CMccRtpDataSink::SRTPMasterKeyStaleEvent( const CSRTPStream& aStream ) + { + TRACE_RTP_INTERFACE_PRINT( "CMccRtpDataSink::SRTPMasterKeyStaleEvent" ) + + if ( iSrtpStream == &aStream ) + { + iSecureKeyExpired = ETrue; + SendSecureRtpEventToClient( iEventHandler, + KMccRtpSinkUid, + EMccInternalEventNone, + KMccMasterKeyStaled, + MCC_RTPSINK_ENDPOINT_ID ); + } + else + { + TRACE_RTP_INTERFACE_PRINT( "CMccRtpDataSink::SRTPMasterKeyStaleEvent - Wrong stream" ) + } + } + +// --------------------------------------------------------------------------- +// FROM SRTP API +// This function is called by SRTP Stream initiated with +// CSRTPSession when a master key is stale and +// needs to be refreshed. +// --------------------------------------------------------------------------- +void CMccRtpDataSink::SRTPMasterKeyStaleEvent(const CSRTPSession& aSession ) + { + TRACE_RTP_INTERFACE_PRINT( "CMccRtpStream::SRTPMasterKeyStaleEvent" ) + + if ( iSecSession == &aSession ) + { + iSecureKeyExpired = ETrue; + SendSecureRtpEventToClient( iEventHandler, + KMccRtpSinkUid, + EMccInternalEventNone, + KMccMasterKeyStaled, + MCC_RTPSINK_ENDPOINT_ID ); + } + else + { + TRACE_RTP_INTERFACE_PRINT( "MccRtpStream::SRTPMasterKeyStaleEvent - Wrong session" ) + } + } + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + +// End of File +