--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rtp/rtpstack/src/rtpsession.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,4143 @@
+/*
+* Copyright (c) 2002-2003 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "rtpsession.h"
+
+
+// CONSTANTS
+const TInt TStream::iOffset = _FOFF( TStream, iMagicKey );
+
+// Used to calculate the average size of an RTCP packet, this represents
+// the fraction by which the most recent RTCP packet influences the average.
+const TReal KRtcpSizeGain = ( 1.0 / 16.0 );
+const TReal KRtcpSizeGainRemainder = 1 - KRtcpSizeGain;
+const TInt KRtpLimitNumberOfRecvStream=100;
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CRtpSession::CRtpSession( const TRtpId aSessionId,
+ const TUint32* aProfileRTPTimeRates,
+ const TBool aStandardRtp,
+ MRtpErrNotify& aErrNotify,
+ const CRtpSDES* aSdesInfo ,
+ MRtpAsignUniqueID& aAssignUniqueID)
+ :
+ iStandardRtp( aStandardRtp ),
+ iSessionId( aSessionId ),
+ iLocalSdes( aSdesInfo ),
+ iNewSdes( NULL ),
+ // Send one SDES packet after every KDES_SEND_PACKET SR or RR
+ iSendSdesCounter( KSDES_SEND_PACKET ),
+ iRtpRecvBuf( NULL, 0 ),
+ iRtcpRecvBuf( NULL, 0 ),
+ iRtcpEnabled( EFalse ),
+ iFirstRTCPSent( EFalse ),
+ iFPortsInit( EFalse ),
+ iNumOfTxStreams( 0 ),
+ iNumOfRxStreams( 0 ),
+ iProfileRTPTimeRates( aProfileRTPTimeRates ),
+ iAverageRtcpSize( static_cast<TReal>( KAverageRtcpPacketLength ) ),
+ iRtcpTimeInterval( KMinRtcpTimeInterval ),
+ // default: the session has one participant
+ iTotalParticipantsSession( 1 ),
+ iRtpObserver( NULL ),
+ iRtcpObserver( NULL ),
+ iNonRTPDataObserver( NULL ),
+ iErrNotify( aErrNotify ),
+ iAssignUniqueID( aAssignUniqueID),
+ iSessionStarted( EFalse ),
+ iSSRCJumps( 0 ),
+ iRtcpErrors( 0 ),
+ iRtcpSendingSuspended( EFalse ),
+ iSeed( 0 )
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::ConstructL( const TCreateSessionParams& aParams,
+ TUint& aPort,
+ TBool aEnableRtcp,
+ const TRtcpParams* aRtcpParams,
+ RSocketServ& aSocketServ,
+ RConnection& aRConn,
+ const RLibrary& aLibrary,
+ MRtpErrNotify& aErrNotify )
+ {
+ RTP_DEBUG_DETAIL_DVALUE( "CRtpSession::ConstructL, socket size:",
+ aParams.iSocketBufSize );
+
+ // Create at least packets of size KMaxRtpPacketSize. If client
+ // wants to use bigger socket than that, also packets need to
+ // have the same size.
+ TInt packetSize = ( aParams.iSocketBufSize > KMaxRtpPacketSize ) ?
+ aParams.iSocketBufSize : KMaxRtpPacketSize;
+
+ if ( iStandardRtp )
+ {
+ // allocate 1 packet to RTP sending
+ iPktSnd = CRtpPacket::NewL( packetSize, iProfileRTPTimeRates );
+ iPktSnd->SetType( ERTP );
+
+ // allocate 1 packet to RTP receiving
+ iPktRcv = CRtpPacket::NewL( packetSize, iProfileRTPTimeRates );
+ iPktRcv->SetType( ERTP );
+ TPtr8 aux1( iPktRcv->GetHBuf()->Des() );
+ iRtpRecvBuf.Set( aux1 );
+ }
+ else
+ {
+ // Function at ordinal 1 creates new CRtpPacketExt
+ TLibraryFunction entry = aLibrary.Lookup( 1 );
+
+ iPktExtRcv = ( MRtpPacketExt * ) entry(); //NewL()
+ iPktExtRcv->ConstructL( packetSize, iSessionId );
+ TPtr8 aux1( iPktExtRcv->GetHBuf()->Des() );
+ iRtpRecvBuf.Set( aux1 );
+
+ iPktExtSnd = ( MRtpPacketExt * ) entry(); //NewL()
+ iPktExtSnd->ConstructL( packetSize, iSessionId );
+ }
+
+ if ( aEnableRtcp )
+ {
+ iRtcpEnabled = ETrue;
+
+ // allocate 1 packet for RTCP sending
+ iPktRtcpSnd = CRtpPacket::NewL( KMaxRtcpPacketSize,
+ iProfileRTPTimeRates );
+
+ // allocate 1 packet for RTCP receiving
+ iPktRtcpRcv = CRtpPacket::NewL( KMaxRtcpPacketSize,
+ iProfileRTPTimeRates );
+ TPtr8 aux2( iPktRtcpRcv->GetHBuf()->Des() );
+ iRtcpRecvBuf.Set( aux2 );
+
+ iSndRtcpTimer = CRtpTimer::NewL( CActive::EPriorityStandard, *this );
+
+ InitialiseRtcp( aRtcpParams );
+ }
+
+ iCommNet = CRtpComm::NewL( aPort, aSocketServ, aRConn, aParams, aErrNotify,
+ aEnableRtcp );
+
+ iCommNet->RegisterReceivedNotify( this );
+
+ // instantiate RTP stream arrays
+ iStreamTxArray = new ( ELeave ) CArrayFixFlat<TStream>( 2 );
+ iStreamRxArray = new ( ELeave ) CArrayFixFlat<TStream>( 2 );
+ iSdesArray = new ( ELeave ) CArrayPtrFlat<CRtpSDES>( 2 );
+
+ // Assigned default SSRC
+ iDefaultSSRC = GenerateSSRC();
+ iIsSrtp=EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CRtpSession* CRtpSession::NewL( const TCreateSessionParams& aParams,
+ TUint& aPort,
+ TBool aEnableRtcp,
+ const TRtcpParams* aRtcpParams,
+ RSocketServ& aSocketServ,
+ RConnection& aRConn,
+ const TRtpId aSessionId,
+ const CRtpSDES* aSdes, // application's SDES
+ const TUint32* aProfileRTPTimeRates,
+ const TBool aStandardRtp,
+ const RLibrary& aLibrary,
+ MRtpErrNotify& aErrNotify,
+ MRtpAsignUniqueID& aAssignUniqueID )
+ {
+ CRtpSession* self = new ( ELeave ) CRtpSession( aSessionId,
+ aProfileRTPTimeRates,
+ aStandardRtp, aErrNotify,
+ aSdes,aAssignUniqueID);
+ CleanupStack::PushL( self );
+ self->ConstructL( aParams, aPort, aEnableRtcp, aRtcpParams, aSocketServ,
+ aRConn, aLibrary, aErrNotify );
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CRtpSession::~CRtpSession()
+ {
+ RemoveAllStreams();
+ delete iStreamTxArray;
+ delete iStreamRxArray;
+ if (iSdesArray)
+ {
+ iSdesArray->ResetAndDestroy();
+ }
+ delete iSdesArray;
+ delete iCommNet;
+ if ( iRtcpEnabled )
+ {
+ delete iSndRtcpTimer;
+ }
+ if ( iNewSdes )
+ {
+ delete iNewSdes;
+ }
+ if ( iStandardRtp )
+ {
+ delete iPktSnd;
+ delete iPktRcv;
+ if ( iRtcpEnabled )
+ {
+ delete iPktRtcpSnd;
+ delete iPktRtcpRcv;
+ }
+ }
+ else
+ {
+ if (iPktExtSnd)
+ {
+ iPktExtSnd->Close(); // delete iPktExtSnd;
+ }
+ if (iPktExtRcv)
+ {
+ iPktExtRcv->Close(); // delete iPktExtRcv;
+ }
+ }
+ iRxSSRCArray.Close();
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SetRemoteAddress()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SetRemoteAddress( TInetAddr& aRemoteAddr )
+ {
+ if ( !iCommNet )
+ {
+ return KErrGeneral;
+ }
+
+ TInt error( KErrNone );
+
+ if ( iSessionStarted )
+ {
+ ResetTxStreamStats();
+ ResetRxStreamStats();
+ }
+
+ iRemoteAddr[ERTPPort].SetAddress( aRemoteAddr.Address() );
+ iRemoteAddr[ERTPPort].SetPort( aRemoteAddr.Port() );
+
+ error = iCommNet->SetToAddress( ERTPPort, aRemoteAddr );
+ if (aRemoteAddr.Family() == KAfInet6 )
+ {
+ iRemoteAddr[ERTPPort].SetAddress( aRemoteAddr.Ip6Address() );
+ }
+
+ if ( error == KErrNone && iRtcpEnabled )
+ {
+ TInetAddr remoteAddr( aRemoteAddr );
+
+ // Set RTCP port
+ remoteAddr.SetPort( remoteAddr.Port() + 1 );
+
+ iRemoteAddr[ERTCPPort].SetAddress( remoteAddr.Address() );
+ iRemoteAddr[ERTCPPort].SetPort( remoteAddr.Port() );
+ if (aRemoteAddr.Family() == KAfInet6 )
+ {
+ iRemoteAddr[ERTCPPort].SetAddress( aRemoteAddr.Ip6Address() );
+ }
+ error = iCommNet->SetToAddress( ERTCPPort, remoteAddr );
+ }
+
+ if ( error == KErrNone && !iSessionStarted )
+ {
+ iCommNet->RegisterReceivedNotify( this );
+ }
+
+ iRemoteAddrSet = ETrue;
+ return error;
+ }
+
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SetRemoteRtcpAddress()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SetRemoteRtcpAddress( TInetAddr& aRemoteAddr )
+ {
+ TInt error( KErrNone );
+
+ if ( !iRtcpEnabled )
+ {
+ return KErrNotSupported;
+ }
+ else
+ {
+
+ iRemoteAddr[ERTCPPort].SetAddress( aRemoteAddr.Address() );
+ iRemoteAddr[ERTCPPort].SetPort( aRemoteAddr.Port() );
+ if (aRemoteAddr.Family() == KAfInet6 )
+ {
+ iRemoteAddr[ERTCPPort].SetAddress( aRemoteAddr.Ip6Address() );
+ }
+ error = iCommNet->SetToAddress( ERTCPPort, aRemoteAddr );
+ }
+
+ return error;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::CreateReceiveStreamL()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::CreateReceiveStreamL( TRtpId aRcvStreamId,
+ const TRtpPayloadType aPayloadType )
+ {
+ if ( iNumOfRxStreams == 0 )
+ {
+ // This is the first Rx stream
+ iCommNet->ConstructReceiverL(iNonRTPDataObserver!=NULL);
+ if (iRemoteAddrSet)
+ {
+ iCommNet->SetAcceptedFromAddress(iRemoteAddr[ERTPPort]);
+ }
+ }
+
+ CRtpRecvStream* newReceiveStream =
+ CRtpRecvStream::NewL( aPayloadType, iSessionId, aRcvStreamId,
+ &iRtpObserver, iRtcpObserver,
+ iProfileRTPTimeRates, this );
+
+
+ // store new receive stream address in stream array
+ TStream arrayData( aRcvStreamId, ( TUint ) newReceiveStream );
+
+ TInt err( AddStream( arrayData, ERxStream ) );
+
+ if ( err == KErrNone )
+ {
+ iNumOfRxStreams++;
+ }
+ else
+ {
+ delete newReceiveStream;
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::GetUniqueSSRC()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpSSRC CRtpSession::GetUniqueSSRC()
+ {
+ TRtpSSRC ssrc( 0 );
+ if ( iNumOfTxStreams != 0 )
+ {
+ ssrc = GenerateSSRC();
+
+ // find if SSRC is already in use
+ while ( FindStreamForSSRC( ssrc ) )
+ {
+ // if SSRC is already in use, create a new one
+ ssrc = GenerateSSRC();
+ }
+ }
+ else // first TX stream, set transmit stream SSRC equal default SSRC
+ {
+ ssrc = iDefaultSSRC;
+ }
+ return ssrc;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::CreateTransmitStreamL()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::CreateTransmitStreamL( TRtpId aTranStreamId,
+ const TRtpPayloadType aPayloadType,
+ TRtpSSRC& aSSRC )
+ {
+ if ( iNumOfTxStreams == 0 )
+ {
+ // This is the first Tx stream
+ iCommNet->ConstructSenderL(iRemoteAddr[ERTPPort], iRemoteAddr[ERTCPPort]);
+ }
+
+ aSSRC = GetUniqueSSRC();
+
+ CRtpTranStream* newTranStream =
+ CRtpTranStream::NewL( aPayloadType, iSessionId, aTranStreamId, aSSRC,
+ iRtcpObserver, iProfileRTPTimeRates );
+
+ // store new transmit stream address in stream array
+ TStream arrayData( aTranStreamId, ( TUint ) newTranStream );
+
+ TInt ret( AddStream( arrayData, ETxStream ) );
+
+ if ( ret == KErrNone )
+ {
+ iNumOfTxStreams++;
+ RedistributeBandwidth();
+ }
+ else
+ {
+ delete newTranStream;
+ }
+
+ RTP_DEBUG_DETAIL_DVALUE( "Created TX Stream with Session ID = ", iSessionId );
+ RTP_DEBUG_DETAIL_DVALUE( "Created TX Stream ID = ", aTranStreamId );
+ RTP_DEBUG_DETAIL_DVALUE( "Created TX Stream SSRC = ", aSSRC );
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::CreateTransmitStreamExtL()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::CreateTransmitStreamExtL( TRtpId aTranStreamId,
+ const TRtpPayloadType aPayloadType,
+ const TRtpSSRC aSSRC )
+ {
+ if ( iNumOfTxStreams == 0 )
+ {
+ // This is the first Tx stream
+ iCommNet->ConstructSenderL(iRemoteAddr[ERTPPort], iRemoteAddr[ERTCPPort]);
+ }
+
+ iDefaultSSRC = aSSRC; // asigned this value to the default just in case
+
+ CRtpTranStream* newTranStream =
+ CRtpTranStream::NewL( aPayloadType, iSessionId, aTranStreamId, aSSRC,
+ iRtcpObserver, iProfileRTPTimeRates );
+
+ // store new receive stream address in stream array
+ TStream arrayData( aTranStreamId, ( TUint ) newTranStream );
+
+ TInt ret( AddStream( arrayData, ETxStream ) );
+
+ if ( ret == KErrNone )
+ {
+ iNumOfTxStreams++;
+ RedistributeBandwidth();
+ }
+ else
+ {
+ delete newTranStream;
+ }
+
+ RTP_DEBUG_DETAIL_DVALUE( "Created TX Stream with Session ID = ", iSessionId );
+ RTP_DEBUG_DETAIL_DVALUE( "Created TX Stream ID = ", aTranStreamId );
+ RTP_DEBUG_DETAIL_DVALUE( "Created TX Stream SSRC = ", aSSRC );
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::CloseStream()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::CloseStream( TRtpId aRcvStreamID )
+ {
+ TStreamType streamType;
+
+ // remove stream
+ TInt error( RemoveStream( aRcvStreamID, streamType ) );
+
+ if ( error == KErrNone )
+ {
+ if ( streamType == ERxStream )
+ {
+ iNumOfRxStreams--;
+ }
+ else //ETxStream
+ {
+ iNumOfTxStreams--;
+ RedistributeBandwidth();
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CRtpSession::RedistributeBandwidths()
+//
+// Calculate a new bandwidth for the TX streams.
+//
+// iFraction is the procent reserved for RTCP.
+//
+// Note, the bandwith is just the theoretical bandwidth which is used
+// for RTCP and has nothing to do with the real bandwith.
+// So if RTCP is not enabled, it will return (no calculation needed).
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::RedistributeBandwidth()
+ {
+ if ( iRtcpEnabled && ( iStreamTxArray != NULL ) )
+ {
+
+ CRtpTranStream* tempTxStream;
+
+ TInt count = iStreamTxArray->Count();
+ if ( count == 0 )
+ {
+ return;
+ }
+ TUint32 bandwidth = static_cast<TUint32>(
+ ( iBandWidth * ( 1 - iFraction ) ) / count );
+
+ for( int index = 0; index < count; index++ )
+ {
+ tempTxStream = reinterpret_cast<CRtpTranStream*>(
+ ( iStreamTxArray->At( index ).GetStreamAddress() )
+ );
+ tempTxStream->SetBandwidth( bandwidth );
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::ResetRxStreamStats()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::ResetRxStreamStats()
+ {
+ CRtpRecvStream* tempStream;
+
+ TInt count = iStreamRxArray->Count();
+
+ for(int index = 0; index < count; index++ )
+ {
+ tempStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+ tempStream->ResetStreamStat();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::ResetTxStreamStats()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::ResetTxStreamStats()
+ {
+ CRtpTranStream* tempStream;
+
+ TInt count = iStreamTxArray->Count();
+
+ for ( TInt index( 0 ); index < count; index++ )
+ {
+ tempStream = ( CRtpTranStream* )
+ ( iStreamTxArray->At( index ).GetStreamAddress() );
+ tempStream->ResetStreamStat();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtpPacket()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtpPacket( TRtpId aTranStreamId,
+ const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData )
+ {
+ if ( static_cast<TUint> (aPayloadData.Size()) > iCommNet->MaxSocketSize() )
+ {
+ return KErrOverflow;
+ }
+
+ // find stream
+ TUint streamAddress = 0;
+ TInt ret( FindStream( aTranStreamId, streamAddress ) );
+
+ if ( ret == KErrNone )
+ {
+ CRtpTranStream* tempStream = ( CRtpTranStream* ) streamAddress;
+ tempStream->BuildRtpPacket( aHeaderInfo, aPayloadData, 0, EFalse,
+ iPktSnd );
+ ret = iCommNet->Send( ERTPPort, iPktSnd->Des() );
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtpPacket()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtpPacket( TRtpId aTranStreamId,
+ const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData,
+ TRequestStatus& aStatus )
+ {
+ if ( static_cast<TUint>( aPayloadData.Size() ) > iCommNet->MaxSocketSize() )
+ {
+ return KErrOverflow;
+ }
+
+ // find stream
+ TUint streamAddress = 0;
+ TInt ret( FindStream( aTranStreamId, streamAddress ) );
+
+ if ( ret == KErrNone )
+ {
+ CRtpTranStream* tempStream =
+ reinterpret_cast<CRtpTranStream*>( streamAddress );
+ tempStream->BuildRtpPacket( aHeaderInfo, aPayloadData, 0, EFalse,
+ iPktSnd );
+ iCommNet->Send( ERTPPort, iPktSnd->Des(), aStatus );
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtpPacket()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtpPacket( const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData )
+ {
+ if ( static_cast<TUint>( aPayloadData.Size() ) > iCommNet->MaxSocketSize() )
+ {
+ return KErrOverflow;
+ }
+
+ TInt ret( iPktExtSnd->RtpPacketBuild( aHeaderInfo, aPayloadData ) );
+
+ if( ret == KErrNone )
+ {
+ ret = iCommNet->Send( ERTPPort, iPktExtSnd->Des() );
+ }
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtpPacket()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtpPacket( const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData,
+ TRequestStatus& aStatus )
+ {
+ if ( static_cast<TUint>( aPayloadData.Size() ) > iCommNet->MaxSocketSize() )
+ {
+ return KErrOverflow;
+ }
+
+ TInt ret( iPktExtSnd->RtpPacketBuild( aHeaderInfo, aPayloadData ) );
+
+ if( ret == KErrNone )
+ {
+ iCommNet->Send( ERTPPort, iPktExtSnd->Des(), aStatus );
+ }
+
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// void CRtpSession::SendData()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::SendData( TBool aUseRTPSocket,
+ const TDesC8& aData,
+ TRequestStatus& aStatus )
+ {
+ if (aUseRTPSocket)
+ {
+ iCommNet->Send( ERTPPort, aData, aStatus );
+ }
+ else
+ {
+ iCommNet->Send( ERTCPPort, aData, aStatus );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtpPacket()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtpPacket( TRtpId aTranStreamId,
+ TRtpSequence aSequenceNum,
+ const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData,
+ TRequestStatus& aStatus )
+ {
+ if ( static_cast<TUint>( aPayloadData.Size() ) > iCommNet->MaxSocketSize() )
+ {
+ return KErrOverflow;
+ }
+
+ // find stream
+ TUint streamAddress = 0;
+ TInt ret( FindStream( aTranStreamId, streamAddress ) );
+
+ if ( ret == KErrNone )
+ {
+ CRtpTranStream* tempStream =
+ reinterpret_cast<CRtpTranStream*>( streamAddress );
+ tempStream->BuildRtpPacket( aHeaderInfo, aPayloadData, aSequenceNum,
+ ETrue, iPktSnd );
+ iCommNet->Send( ERTPPort, iPktSnd->Des(), aStatus );
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::CancelSend()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::CancelSend()
+ {
+ iCommNet->CancelSend( ERTPPort );
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtcpByePacket()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtcpByePacketL( TRtpId aTranStreamId,
+ const TDesC8& aReason )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrNotSupported;
+ }
+ if ( !iSessionStarted )
+ {
+ RTP_DEBUG_DETAIL("CRtpSession::SendRtcpByePacket, Session not started" );
+
+ return KErrNotReady;
+ }
+ if ( aReason.Size() >= KMaxRtcpReason )
+ {
+ return KErrTooBig;
+ }
+
+ // find stream
+ TUint streamAddress( 0 );
+ TInt ret( FindStream( aTranStreamId, streamAddress ) );
+
+ if ( ret == KErrNone )
+ {
+ CRtpTranStream* tempStream =
+ reinterpret_cast<CRtpTranStream*>( streamAddress );
+ ret = BuildRTCPReport( tempStream, NULL );
+ if ( ret == KErrNone )
+ {
+ ret = tempStream->BuildRtcpBYEPacket( aReason, iPktRtcpSnd );
+ }
+ if ( ret == KErrNone )
+ {
+ if(IsSrtp())
+ {
+ SendSRTCPReportL(tempStream->GetLocalSSRC());
+ }
+ else
+ {
+ SendRTCPReport();
+ }
+ }
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtcpAppPacketL()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtcpAppPacketL( TRtpId aTranStreamId,
+ const TRtcpApp& aApp )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrNotSupported;
+ }
+ if ( !iSessionStarted )
+ {
+ RTP_DEBUG_DETAIL("CRtpSession::SendRtcpAppPacket, Session not started" );
+
+ return KErrNotReady;
+ }
+ if ( aApp.iAppDataLen >= KMaxRtcpAppData )
+ {
+ return KErrTooBig;
+ }
+
+ // find stream
+ TUint streamAddress = 0;
+ TInt ret( FindStream( aTranStreamId, streamAddress ) );
+
+ if ( ret == KErrNone )
+ {
+ CRtpTranStream* tempStream =
+ reinterpret_cast<CRtpTranStream*>( streamAddress );
+ ret = BuildRTCPReport( tempStream, NULL );
+ if ( ret == KErrNone )
+ {
+ ret = tempStream->BuildRtcpAPPPacket( aApp, iPktRtcpSnd );
+ }
+ if ( ret == KErrNone )
+ {
+ if(IsSrtp())
+ {
+ SendSRTCPReportL(tempStream->GetLocalSSRC());
+ }
+ else
+ {
+ SendRTCPReport();
+ }
+ }
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtcpSrPacketL()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtcpSrPacketL( TRtpId aTranStreamId )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrNotSupported;
+ }
+ if ( !iSessionStarted )
+ {
+ RTP_DEBUG_DETAIL( "CRtpSession::SendRtcpSrPacket, Session not started" );
+ return KErrNotReady;
+ }
+
+ TInt ret( KErrNone );
+
+ // find stream
+ TUint streamAddress = 0;
+ ret = FindStream( aTranStreamId, streamAddress );
+
+ if ( ret == KErrNone )
+ {
+ CRtpTranStream* tempStream =
+ reinterpret_cast<CRtpTranStream*>( streamAddress );
+ ret = BuildRTCPReport( tempStream, NULL );
+ if ( ret == KErrNone )
+ {
+ if(IsSrtp())
+ {
+ SendSRTCPReportL(tempStream->GetLocalSSRC());
+ }
+ else
+ {
+ SendRTCPReport();
+ }
+ }
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SendRtcpRrPacketL()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SendRtcpRrPacketL( TRtpId aRecvStreamId )
+ {
+ RTP_DEBUG_DETAIL( "CRtpSession::SendRtcpRrPacket entry" );
+
+ if ( !iRtcpEnabled )
+ {
+ return KErrNotSupported;
+ }
+ if ( !iSessionStarted )
+ {
+ RTP_DEBUG_DETAIL( "Error: Session not started");
+
+ return KErrNotReady;
+ }
+
+ TInt ret( KErrNone );
+ CRtpRecvStream* tempStream( NULL );
+ // find stream
+ TUint streamAddress = 0;
+ ret = FindStream( aRecvStreamId, streamAddress );
+
+ if ( ret == KErrNone )
+ {
+ // Make sure the stream has received packets
+ tempStream =
+ reinterpret_cast<CRtpRecvStream*>( streamAddress );
+ if ( tempStream->FirstPkg() )
+ {
+ RTP_DEBUG_DETAIL( "Error: Must send RTP packets before RTCP" );
+
+ ret = KErrNotReady;
+ }
+ }
+
+ if ( ret == KErrNone )
+ {
+ // Build the RR version of the RTCP header
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam initParam;
+
+ initParam.TRTCP_HEADER.pt = ERTCP_RR;
+ initParam.TRTCP_HEADER.sourceCount = 1;
+
+ // The length of one RR block in 32-bit units is 6
+ // Added to this the source SSRC makes the total length 7
+ initParam.TRTCP_HEADER.length = 7;
+
+ streamParam.TRTCP_HEADER.SSRC = iDefaultSSRC;
+
+ iPktRtcpSnd->SetType( ERTCP_HEADER );
+ ret = iPktRtcpSnd->RtpPacketBuild( &streamParam, &initParam );
+ }
+
+ if ( ret == KErrNone )
+ {
+ // Build the RR and SDES sections, then send the packet
+ tempStream->RtpStreamCreateRtcpReportSection( iPktRtcpSnd );
+ BuildSdesSection( NULL );
+ if(IsSrtp())
+ {
+ SendSRTCPReportL(tempStream->GetLocalSSRC());
+ }
+ else
+ {
+ SendRTCPReport();
+ }
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// RSocket* CRtpSession::GetRtpSocket()
+//
+// ---------------------------------------------------------------------------
+//
+RSocket* CRtpSession::GetRtpSocket()
+ {
+ if ( iCommNet )
+ return iCommNet->GetSocket( ERTPPort );
+ else
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// RSocket* CRtpSession::GetRtcpSocket()
+//
+// ---------------------------------------------------------------------------
+//
+RSocket* CRtpSession::GetRtcpSocket()
+ {
+ if ( iCommNet && iRtcpEnabled )
+ return iCommNet->GetSocket( ERTCPPort );
+ else
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::GetStreamStatistics()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::GetStreamStatistics( TRtpId aStreamId, TRtpPeerStat& aStat )
+ {
+ TInt ret;
+
+ // find stream
+ TUint streamAddress = 0;
+ TStreamType aStreamType;
+
+ ret = FindStream( aStreamId, streamAddress, aStreamType );
+
+ if ( ret != KErrNone )
+ {
+ return ret;
+ }
+
+ if ( aStreamType == ERxStream )
+ {
+ CRtpRecvStream* tempStream = ( CRtpRecvStream* ) streamAddress;
+ ret = tempStream->GetStreamStat( aStat );
+ }
+ else //ETxStream
+ {
+ CRtpTranStream* tempStream = ( CRtpTranStream* ) streamAddress;
+ ret = tempStream->GetStreamStat( aStat );
+ }
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::InitialiseRtcp()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::InitialiseRtcp( const TRtcpParams* aParams )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrGeneral;
+ }
+
+ if ( aParams == NULL )
+ {
+ TRtcpParams params;
+ params.iSessionBWidth = KRtpDefaultBandWidth;
+ params.iRtcpFraction = KRtpDefaultRtcpFrac;
+ SetRtcpParameters( params );
+ }
+ else
+ {
+ SetRtcpParameters( *aParams );
+ }
+
+ // 1000 - milliseconds per second
+ // 8 - bits in one byte
+ iRtcpTimeInterval = ( TUint ) ( 1000 * KAverageRtcpPacketLength * 8 /
+ ( iBandWidth * iFraction ) );
+
+ // The first RTCP interval should be half the usual amount. Hence, we
+ // divide by two here.
+ if ( iRtcpTimeInterval < KMinRtcpTimeInterval / 2 )
+ {
+ iRtcpTimeInterval = KMinRtcpTimeInterval / 2;
+ }
+
+ // Randomise
+ TReal rtcpTimeInterval64 = iRtcpTimeInterval * ( Random64() + 0.5 );
+ iRtcpTimeInterval = static_cast<TUint>( rtcpTimeInterval64 );
+
+ RTCP_DEBUG_DETAIL_DVALUE( "CRtpSession::InitialiseRtcp - RTCP Interval(ms) = ", iRtcpTimeInterval );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SetRtcpParameters()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SetRtcpParameters( const TRtcpParams& aRtcpParams )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrGeneral;
+ }
+
+ if ( aRtcpParams.iSessionBWidth < KRtpMinimumBandWidth )
+ {
+ iBandWidth = KRtpDefaultBandWidth;
+ }
+ else
+ {
+ iBandWidth = aRtcpParams.iSessionBWidth;
+ }
+ if ( aRtcpParams.iRtcpFraction == 0 || aRtcpParams.iRtcpFraction > 1 )
+ {
+ iFraction = KRtpDefaultRtcpFrac;
+ }
+ else
+ {
+ iFraction = aRtcpParams.iRtcpFraction;
+ }
+
+ RedistributeBandwidth();
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::RegisterRtpObserver()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::RegisterRtpObserver( MRtpObserver& aObserver )
+ {
+ if ( iPktExtRcv )
+ iPktExtRcv->RegisterRtpObserver( aObserver );
+
+ iRtpObserver = &aObserver;
+
+ // now update observers in receiver streams
+ CRtpRecvStream* tempStream;
+ TInt count = iStreamRxArray->Count();
+ for(int index = 0; index < count; index++ )
+ {
+ tempStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+ tempStream->RegisterRtpObserver(&aObserver);
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::UnregisterRtpObserver()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::UnregisterRtpObserver()
+ {
+ if ( iPktExtRcv )
+ iPktExtRcv->UnregisterRtpObserver();
+
+ iRtpObserver = NULL;
+
+ // now unregister receiver stream RTP observer
+ CRtpRecvStream* tempStream;
+ TInt count = iStreamRxArray->Count();
+
+ for(int index = 0; index < count; index++ )
+ {
+ tempStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+ tempStream->UnRegisterRtpObserver();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::RegisterRtcpObserver()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::RegisterRtcpObserver( MRtcpObserver& aObserver )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrGeneral;
+ }
+
+ iRtcpObserver = &aObserver;
+
+ // now register receiver stream RTCP observers
+ CRtpRecvStream* tempRecvStream;
+ TInt count = iStreamRxArray->Count();
+ for(int index = 0; index < count; index++ )
+ {
+ tempRecvStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+ tempRecvStream->RegisterRtcpObserver(aObserver);
+ }
+
+ // now register transmit stream RTCP observers
+ CRtpTranStream* tempTxStream;
+ count = iStreamTxArray->Count();
+ for(int index = 0; index < count; index++ )
+ {
+ tempTxStream = ( CRtpTranStream* )
+ ( iStreamTxArray->At( index ).GetStreamAddress() );
+ tempTxStream->RegisterRtcpObserver(aObserver);
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::UnregisterRtcpObserver()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::UnregisterRtcpObserver()
+ {
+ iRtcpObserver = NULL;
+
+ // now unregister receiver stream RTCP observers
+ CRtpRecvStream* tempRecvStream;
+ TInt count = iStreamRxArray->Count();
+
+ for(int index = 0; index < count; index++ )
+ {
+ tempRecvStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+ tempRecvStream->UnRegisterRtcpObserver();
+ }
+
+ // now unregister transmit stream RTCP observers
+ CRtpTranStream* tempTxStream;
+ count = iStreamTxArray->Count();
+
+ for(int index = 0; index < count; index++ )
+ {
+ tempTxStream = ( CRtpTranStream* )
+ ( iStreamTxArray->At( index ).GetStreamAddress() );
+ tempTxStream->UnRegisterRtcpObserver();
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SetNonRTPDataObserver()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::SetNonRTPDataObserver( MNonRTPDataObserver* aNonRTPDataObserver )
+ {
+ iNonRTPDataObserver = aNonRTPDataObserver;
+ if (iNonRTPDataObserver)
+ {
+ iCommNet->SetNonRtpObserverFlag(ETrue);
+ }
+ else
+ {
+ iCommNet->SetNonRtpObserverFlag(EFalse);
+ }
+ return KErrNone;
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// CRtpSession::StartSession()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::StartSession()
+ {
+ TInt result( KErrNone );
+ if ( iNumOfRxStreams == 0 && iNumOfTxStreams == 0 )
+ {
+ return KErrNotReady;
+ }
+ if ( iNumOfRxStreams != 0 )
+ {
+ // Start receiving RTP streams
+ result = IssueRtpRecv();
+ // IssueRtpRecv() returns KErrNone the first time, KErrInUse if it
+ // has been called before and KErrNotReady if the receive resources
+ // are not constructed.
+ if ( iRtcpEnabled && ( result == KErrNone ) )
+ {
+ result = IssueRtcpRecv();
+ }
+ // If the sockets are already active listening for packets, this is OK
+ if ( result == KErrInUse )
+ {
+ result = KErrNone;
+ }
+ }
+ if ( iRtcpEnabled && iNumOfTxStreams != 0 && !iSndRtcpTimer->IsActive() )
+ {
+ // Start sending RTCP packets
+ iSndRtcpTimer->After( iRtcpTimeInterval * KMicrosecondPerMillSecond );
+ }
+ if ( result == KErrNone )
+ {
+ iSessionStarted = ETrue;
+ }
+ return result;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::IssueRtpRecv()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::IssueRtpRecv()
+ {
+ return iCommNet->Receive( ERTPPort, iRtpRecvBuf );
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::IssueRtcpRecv()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::IssueRtcpRecv()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrGeneral;
+ }
+ return iCommNet->Receive( ERTCPPort, iRtcpRecvBuf );
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::DoBuildSendRTCPReportIfNotSentL()
+//
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::DoBuildSendRTCPReportIfNotSentL()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return EFalse;
+ }
+ TInt index( 0 );
+ TBool reportSent( EFalse );
+ TInt totalTxStream( iStreamTxArray->Count() );
+
+ for ( index = 0; index < totalTxStream; index++ )
+ {
+ CRtpTranStream* tempStream = reinterpret_cast<CRtpTranStream*>
+ ( iStreamTxArray->At( index ).GetStreamAddress() );
+ if ( !tempStream->SentRtcpReport() && !reportSent )
+ {
+ // if no report has been sent, send it now
+ // totalTxStream - index - 1 makes sure method knows when this is
+ // the last RTCP report to be sent
+ if ( BuildRTCPReport( tempStream, totalTxStream - index - 1 )
+ == KErrNone )
+ {
+ RTP_DEBUG_DETAIL_DVALUE( "BuildSendRTCPReport: Sending SR RTCP REPORT TX stream ID = ",
+ iStreamTxArray->At( index ).GetMagicKey() );
+
+ if(IsSrtp())
+ {
+ SendSRTCPReportL(tempStream->GetLocalSSRC());
+ }
+ else
+ {
+ SendRTCPReport();
+ }
+ }
+ else
+ {
+ RTP_DEBUG_DETAIL_DVALUE( "BuildSendRTCPReport: No report sent for TX stream ID = ",
+ iStreamTxArray->At( index ).GetMagicKey() );
+ }
+
+ tempStream->SetRtcpReportFlag();
+ reportSent = ETrue;
+
+ }
+ }
+ return reportSent;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::DoBuildSendRTCPReportL()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::DoBuildSendRTCPReportL()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TInt index( 0 );
+ TInt totalTxStream( iStreamTxArray->Count() );
+
+ for ( index = 0; index < totalTxStream; index++ )
+ {
+ CRtpTranStream* tempStream = reinterpret_cast<CRtpTranStream*>(
+ ( iStreamTxArray->At( index ).GetStreamAddress() ) );
+ tempStream->ResetRtcpReportFlag();
+
+ // totalTxStream - index - 1 makes sure method knows when this is
+ // the last RTCP report to be send
+ if ( BuildRTCPReport( tempStream, totalTxStream - index - 1 )
+ == KErrNone )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "BuildSendRTCPReport: Sending (AFTER) SR RTCP REPORT TX stream ID = ",
+ iStreamTxArray->At( index ).GetMagicKey() );
+
+ if(IsSrtp())
+ {
+ SendSRTCPReportL(tempStream->GetLocalSSRC());
+ }
+ else
+ {
+ SendRTCPReport();
+ }
+ }
+ else
+ {
+ RTP_DEBUG_DETAIL_DVALUE( "BuildSendRTCPReport: No report sent for TX stream ID = ",
+ iStreamTxArray->At( index ).GetMagicKey() );
+ }
+ tempStream->SetRtcpReportFlag();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::BuildSendRTCPReportL()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::BuildSendRTCPReportL()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TInt totalRxStream( iStreamRxArray->Count() );
+ TInt totalTxStream( iStreamTxArray->Count() );
+ TBool reportSent( ETrue );
+
+ if ( totalTxStream > 0 )
+ {
+ reportSent = DoBuildSendRTCPReportIfNotSentL();
+ // if no reports were sent for any of the TX streams, reset flags and
+ // send an RTCP report this assures that if 2 or more Tx streams will
+ // not send at the same time
+ if ( !reportSent )
+ {
+ DoBuildSendRTCPReportL();
+ }
+ }
+ else if ( totalRxStream > 0 )
+ {
+
+ RTCP_DEBUG_DETAIL_DVALUE( "BuildSendRTCPReport::Sending RR RTCP REPORT sender SSRC = ",
+ iDefaultSSRC );
+
+ if ( BuildRTCPReport( NULL, NULL ) == KErrNone )
+ {
+ if(IsSrtp())
+ {
+ SendSRTCPReportL(iDefaultSSRC);
+ }
+ else
+ {
+ SendRTCPReport();
+ }
+ }
+ }
+ else
+ {
+ // Do Nothing
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::ShouldBuildEmptyRR()
+//
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::ShouldBuildEmptyRR( CRtpTranStream* aTempTranStream )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return EFalse;
+ }
+
+ TBool fEmptyRR( ETrue );
+ if ( aTempTranStream )
+ {
+ // check if no data has been sent lately
+ if ( aTempTranStream->SentRTPPackets() )
+ {
+ fEmptyRR = EFalse;
+ }
+ }
+
+ // find if any receive stream has received an RTP packet
+ if ( AnyRcvStreamReceivedRtpPacket() )
+ {
+ fEmptyRR = EFalse;
+ }
+ return fEmptyRR;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::DetermineSourceCountAndLength()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::DetermineSourceCountAndLength(
+ TInt& aSourceCount,
+ TInt& aLength,
+ TBool aRxActive[KMaxNumActiveRcvStreams] )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TInt k( 0 );
+ TInt numRcvStreams( iStreamRxArray->Count() );
+ for ( k = 0; k < numRcvStreams; k++ )
+ {
+ if ( aRxActive[k] )
+ {
+ if ( RcvStreamReceivedRtpPacket( k ) )
+ {
+ aSourceCount++;
+ aLength += 6; // Length of one RR block in 32-bit units
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "SEND: RX RR ID = ",
+ iStreamRxArray->At( k ).GetMagicKey() );
+ RTCP_DEBUG_DETAIL_DVALUE( "SEND: RX RR SSRC = ",
+ ( ( CRtpRecvStream* )iStreamRxArray->At( k ).
+ GetStreamAddress() )->GetLocalSSRC() );
+
+ }
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::SetParamsForFullRTCPReport()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::SetParamsForFullRTCPReport(
+ CRtpTranStream* aTranStream,
+ TRtpPacketStreamParam* aStreamParam,
+ TRtpPacketIOParam* aInitParam,
+ TBool aRxActive[KMaxNumActiveRcvStreams] )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TInt sourceCount = 0;
+ TInt length = 1;
+
+ if ( aTranStream != NULL )
+ {
+ if ( aTranStream->SentRTPPackets() )
+ {
+
+ RTCP_DEBUG_DETAIL_DVALUE( "SEND: TX SR ID = ",
+ aTranStream->GetStreamID() );
+ RTCP_DEBUG_DETAIL_DVALUE( "SEND: TX SR SSRC = ",
+ aTranStream->GetLocalSSRC() );
+
+
+ length += 5;
+ aInitParam->TRTCP_HEADER.pt = ERTCP_SR;
+ }
+ else
+ {
+ aInitParam->TRTCP_HEADER.pt = ERTCP_RR;
+ }
+ aStreamParam->TRTCP_HEADER.SSRC = aTranStream->GetLocalSSRC();
+ }
+ else
+ {
+ aInitParam->TRTCP_HEADER.pt = ERTCP_RR;
+ aStreamParam->TRTCP_HEADER.SSRC = iDefaultSSRC;
+ }
+
+ DetermineSourceCountAndLength( sourceCount, length, aRxActive );
+
+ aInitParam->TRTCP_HEADER.sourceCount = sourceCount;
+ aInitParam->TRTCP_HEADER.length = length;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::BuildRTCPReport()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::BuildRTCPReport( CRtpTranStream* aTempTranStream,
+ TInt aLastReport )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrGeneral;
+ }
+
+ RTCP_DEBUG_DETAIL( "CRtpSession::BuildRTCPReport" );
+
+
+ TBool activeStreams( EFalse );
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam initParam;
+ TBool rxActive[KMaxNumActiveRcvStreams];
+ TInt numRcvStreams( iStreamRxArray->Count() );
+ TInt k( 0 );
+ TBool streamExists( EFalse );
+
+ iPktRtcpSnd->RtpPacketReset();
+
+ // send an SDES packet if no Tx or Rx streams are available
+ if ( aTempTranStream != NULL || numRcvStreams != NULL )
+ {
+ streamExists = ETrue;
+ }
+ else
+ {
+
+ RTCP_DEBUG_DETAIL( "Error: no suitable stream exists" );
+
+ return KErrGeneral;
+ }
+
+ Mem::FillZ( rxActive, KMaxNumActiveRcvStreams );
+
+ // check which streams are active
+ for ( k = 0; k < numRcvStreams; k++ )
+ {
+ if ( RcvStreamActive( k ) )
+ {
+ rxActive[k] = ETrue;
+ activeStreams = ETrue;
+ }
+ else
+ {
+ rxActive[k] = EFalse;
+ }
+ }
+
+ if ( aTempTranStream )
+ {
+ if ( aTempTranStream->FirstPkg() )
+ {
+ RTCP_DEBUG_DETAIL( "Error: must send RTP packets before RTCP" );
+
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ if ( !activeStreams )
+ {
+ RTCP_DEBUG_DETAIL( "Error: no active receive streams found" );
+
+ return KErrGeneral;
+ }
+ }
+
+ if ( streamExists )
+ {
+ TBool fEmptyRR( ShouldBuildEmptyRR( aTempTranStream ) );
+
+ if ( fEmptyRR == EFalse )
+ {
+ // find which stream are active and send report accordingly
+ SetParamsForFullRTCPReport( aTempTranStream, &streamParam,
+ &initParam, rxActive );
+ // first build the standard RTCP header
+ iPktRtcpSnd->SetType( ERTCP_HEADER );
+ iPktRtcpSnd->RtpPacketBuild( &streamParam, &initParam );
+
+ // always send report about itself (stream) and all the other
+ // active receiving streams
+ BuildSrSection( aTempTranStream );
+ BuildRrSection( numRcvStreams, rxActive, aLastReport );
+ }
+ else
+ {
+ // build empty RR packet if we have inactive Tx and/or Rx streams
+ BuildEmptyRr( aTempTranStream );
+ }
+ }
+
+ BuildSdesSection( aTempTranStream );
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::BuildSrSection()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::BuildSrSection( CRtpTranStream* aTempTranStream )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ if ( aTempTranStream )
+ {
+ if ( aTempTranStream->SentRTPPackets() )
+ {
+ RTCP_DEBUG_DETAIL( "SEND: Sent SR packet" );
+
+ aTempTranStream->RtpStreamCreateRtcpReportSection( iPktRtcpSnd );
+ aTempTranStream->SetSentRTPPackets( EFalse );
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::BuildRrSection()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::BuildRrSection( TInt aNumRcvStreams,
+ TBool aRxActive[KMaxNumActiveRcvStreams],
+ TInt aLastReport )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ for ( TInt k = 0; k < aNumRcvStreams; k++ )
+ {
+ if ( aRxActive[k] && RcvStreamReceivedRtpPacket( k ) )
+ {
+ // get stream with the indicated index value
+ CRtpRecvStream* tempRcvStream = GetRcvStreamByIndex( k );
+
+ RTCP_DEBUG_DETAIL( "SEND: Sent RR packet" );
+
+
+ tempRcvStream->RtpStreamCreateRtcpReportSection( iPktRtcpSnd );
+ // do not set the receive stream until this is the last RTCP
+ // report to be sent
+ if ( !aLastReport )
+ {
+ tempRcvStream->SetReceivedRTPPackets( EFalse );
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::BuildEmptyRr()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::BuildEmptyRr( CRtpTranStream* aTempTranStream )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam initParam;
+
+ initParam.TRTCP_HEADER.pt = ERTCP_RR;
+ initParam.TRTCP_HEADER.sourceCount = 0;
+ initParam.TRTCP_HEADER.length = 1;
+
+ if ( aTempTranStream == NULL ) //No Tx stream
+ {
+ streamParam.TRTCP_HEADER.SSRC = iDefaultSSRC;
+ }
+ else
+ {
+ streamParam.TRTCP_HEADER.SSRC = aTempTranStream->GetLocalSSRC();
+ }
+
+ iPktRtcpSnd->SetType( ERTCP_HEADER );
+ iPktRtcpSnd->RtpPacketBuild( &streamParam, &initParam );
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "SEND: Sent EMPTY RR report sender SSRC = ",
+ streamParam.TRTCP_HEADER.SSRC );
+
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::BuildSdesSection()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::BuildSdesSection( CRtpTranStream* aTempTranStream )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TBool fCNameOnly( EFalse );
+
+ // start counter, when it equals 5, send full SDES information,
+ // other wise send CNAME only
+ iSendSdesCounter++;
+
+ // create SDES packet
+ if ( iSendSdesCounter >= KSDES_SEND_PACKET )
+ {
+ fCNameOnly = EFalse;
+
+
+ RTCP_DEBUG_DETAIL( "SEND: Sent FULL SDES packet" );
+
+
+ iSendSdesCounter = 0;
+
+ if ( !aTempTranStream ) //No Tx stream
+ {
+ CreateSDES( fCNameOnly, iDefaultSSRC );
+ }
+ else
+ {
+ CreateSDES( fCNameOnly, aTempTranStream->GetLocalSSRC() );
+ }
+ }
+ else
+ {
+ fCNameOnly = ETrue;
+
+
+ RTCP_DEBUG_DETAIL( "SEND: Sent only CNAME SDES packet" );
+
+
+ if ( !aTempTranStream ) //No Tx stream
+ {
+ CreateSDES( fCNameOnly, iDefaultSSRC );
+ }
+ else
+ {
+ CreateSDES( fCNameOnly, aTempTranStream->GetLocalSSRC() );
+ }
+ }
+
+
+ if ( !aTempTranStream ) //No Tx stream
+ {
+ RTCP_DEBUG_DETAIL( "SEND: SENDING NEW RTCP REPORT ONLY RR" );
+
+ }
+ else
+ {
+ RTCP_DEBUG_DETAIL_DVALUE( "SEND: SENDING NEW RTCP REPORT SR and RR(?) for TX Stream ID = ",
+ aTempTranStream->GetStreamID() );
+
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::SendRTCPReport()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::SendRTCPReport()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+ if ( iCommNet->Send( ERTCPPort, iPktRtcpSnd->Des() ) == KErrDisconnected )
+ {
+ RTCP_DEBUG_DETAIL( "Fail to send RTCP packet due to network disconnected" );
+
+ ( void ) StopRtcpSending();
+ }
+
+ // update RTCP average packet size
+ AverageRtcpSize( iPktRtcpSnd->Size() );
+ iPktRtcpSnd->RtpPacketReset();
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::CreateSDES()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::CreateSDES( TInt aFCNameOnly, TRtpSSRC aSSRC )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TInt paddingSize = 0;
+
+ // build RTCP SDES packet header
+
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam initParam;
+
+ TInt theIndex = 0;
+ TInt sourceCount = 1;
+ TInt length = 0;
+ TInt sdesCount = 0;
+
+ initParam.TRTCP_HEADER.pt = ERTCP_SDES;
+
+ // get number of chunks in this SDES report
+ if ( aFCNameOnly )
+ {
+ // send only the CNAME information
+ for ( theIndex = 0; theIndex <= ERTCP_SDES_CNAME; theIndex++ )
+ {
+ if ( iLocalSdes->iSDESItemsSize[theIndex] != 0 )
+ {
+ sdesCount++;
+ }
+ // calculate size of all SDES items in bytes
+ length += iLocalSdes->iSDESItemsSize[theIndex];
+ }
+ }
+ else
+ {
+ // send FULL SDES information
+ for ( theIndex = 0; theIndex < ERTCP_NUM_OF_SDES_ITEMS; theIndex++ )
+ {
+ if ( iLocalSdes->iSDESItemsSize[theIndex] != 0 )
+ {
+ sdesCount++;
+ }
+ // calculate size of all SDES items in bytes
+ length += iLocalSdes->iSDESItemsSize[theIndex];
+ }
+ }
+
+ // sdesCount*2 is the bytes for 8-bit type field and octet count
+ if ( ( sdesCount * 2 + length + 1 ) % 4 == 0 )
+ {
+ // multiples of 4 bytes, no padding is needed
+ // Calcultate total number of 32 bit words in SDES packet,
+ // including end of list null octet
+ length = ( sdesCount * 2 + length + 1 ) / 4 + sourceCount;
+ }
+ else
+ {
+ // not multiples of 4 bytes, padding is needed
+ paddingSize = 4 - ( sdesCount * 2 + length + 1 ) % 4;
+ length = ( sdesCount * 2 + length + 1 ) / 4 + 1 + sourceCount;
+ }
+
+ initParam.TRTCP_HEADER.sourceCount = sourceCount;
+ initParam.TRTCP_HEADER.length = length;
+
+ iPktRtcpSnd->SetType( ERTCP_HEADER );
+ iPktRtcpSnd->RtpPacketBuild( &streamParam, &initParam );
+
+ streamParam.TRTCP_SDES.SSRC = aSSRC;
+
+ if ( aFCNameOnly )
+ {
+ for ( theIndex = 0; theIndex <= ERTCP_SDES_CNAME; theIndex++ )
+ {
+ initParam.TRTCP_SDES.sdesItems[theIndex] =
+ iLocalSdes->iSDESItems[theIndex];
+ initParam.TRTCP_SDES.sdesItemsSize[theIndex] =
+ iLocalSdes->iSDESItemsSize[theIndex];
+ }
+
+ // set other sdes item sizes to zero
+ for ( theIndex = ERTCP_SDES_CNAME + 1;
+ theIndex < ERTCP_NUM_OF_SDES_ITEMS; theIndex++ )
+ {
+ initParam.TRTCP_SDES.sdesItemsSize[theIndex] = 0;
+ }
+ }
+ else
+ {
+ for ( theIndex = 0; theIndex < ERTCP_NUM_OF_SDES_ITEMS; theIndex++ )
+ {
+ initParam.TRTCP_SDES.sdesItems[theIndex] =
+ iLocalSdes->iSDESItems[theIndex];
+ initParam.TRTCP_SDES.sdesItemsSize[theIndex] =
+ iLocalSdes->iSDESItemsSize[theIndex];
+ }
+ }
+
+ initParam.TRTCP_SDES.paddingSize = paddingSize;
+ iPktRtcpSnd->SetType( ERTCP_SDES );
+ iPktRtcpSnd->RtpPacketBuild( &streamParam, &initParam );
+
+ RTCP_DEBUG_DETAIL( "SEND: Sending SDES message as" );
+ for ( TInt k = 0; k <= ERTCP_SDES_CNAME; k++ )
+ {
+ RTCP_DEBUG_DETAIL( initParam.TRTCP_SDES.sdesItems[k] );
+ }
+
+
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessRTCPReportSection()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessOneRTCPReportSectionL(
+ const TRtpPacketIOParam& aExtractParam,
+ TRtpSSRC aSourceSSRC )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ TRtpRtcpEnum parseResult( ERTCP_NO_ERROR );
+ iPktRtcpRcv->SetType( aExtractParam.TRTCP_HEADER.pt );
+
+ // handle compound packets
+ switch( iPktRtcpRcv->Type() )
+ {
+ case ERTCP_SDES:
+ parseResult = ProcessSDESSectionL( aSourceSSRC );
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Parsed SDES Info source SSRC ", aSourceSSRC );
+
+
+ break;
+
+ case ERTCP_BYE:
+ parseResult = ProcessBYESectionL();
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Parsed BYE Info source SSRC ", aSourceSSRC );
+
+
+ if ( parseResult == ERTCP_FOUND_RXSTREAM )
+ {
+ return ERTCP_FOUND_RXSTREAM;
+ }
+ break;
+
+ case ERTCP_APP:
+ parseResult = ProcessAPPSectionL( aExtractParam.TRTCP_HEADER.length,
+ aExtractParam.TRTCP_HEADER.sourceCount );
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Parsed APP Info source SSRC ", aSourceSSRC );
+
+
+ if ( parseResult == ERTCP_FOUND_RXSTREAM )
+ {
+ return ERTCP_FOUND_RXSTREAM;
+ }
+ break;
+
+ case ERTCP_SR:
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Received RTCP_SR, sender SSRC ", aSourceSSRC );
+
+
+ parseResult = ProcessSRSectionL(
+ aExtractParam.TRTCP_HEADER.sourceCount );
+ break;
+
+ case ERTCP_RR:
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Received RTCP_RR, sender SSRC ", aSourceSSRC );
+
+
+ // update average RTCP report size
+ AverageRtcpSize( iPktRtcpRcv->Size() );
+
+ if ( aExtractParam.TRTCP_HEADER.sourceCount == 0 )
+ {
+ // this is for the special case where we have an empty RR
+ // section (RC=0)
+
+ RTCP_DEBUG_DETAIL( "RECEIVE: Empty RR Report" );
+
+ if ( iRtcpObserver )
+ {
+ iRtcpObserver->RrReceived( iSessionId, iDefaultSSRC );
+ }
+ // expect an SDES after the empty RR
+ parseResult = ERTCP_PACKET_MORE;
+ }
+ else
+ {
+ // parse all RR reports
+ parseResult = ProcessRRSectionL(
+ aExtractParam.TRTCP_HEADER.sourceCount );
+ }
+ break;
+
+ default:
+ parseResult = ERTCP_PACKET_ERROR;
+ break;
+ } // switch
+ return parseResult;
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessRTCPReportL()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessRTCPReportL()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam extractParam;
+ TRtpRtcpEnum parseResult( ERTCP_NO_ERROR );
+ TRtpSSRC sourceSSRC( NULL );
+ TInt iPacketLength( 0 );
+ TBool bHeader( ETrue );
+ TBool bContinue = ETrue;
+
+ // set packet pointer to the beginning
+ iPktRtcpRcv->RtpPacketResetPtr();
+
+ /* All RTCP reports are compound packets, consisting of at least:
+ * - an SR section (potentially containing RR sections) or an RR section
+ * - an SDES
+ * In addition, the packet may contain one APP or BYE section.
+ * This loop processes one section at a time.
+ */
+ while ( bContinue )
+ {
+ // parse RTCP packet header
+ iPktRtcpRcv->SetType( ERTCP_HEADER );
+ // Get SSRC of packet sender for this report
+ // (This operation does not move the packet pointer)
+ sourceSSRC = iPktRtcpRcv->RtpPacketGetSSRC();
+ parseResult = iPktRtcpRcv->RtpPacketProcessL(
+ &streamParam, &extractParam );
+
+ if ( parseResult == ERTCP_PACKET_ERROR ||
+ parseResult == ERTCP_NO_ERROR )
+ {
+ return parseResult;
+ }
+
+ /**
+ * The payload type field of the first RTCP packet in a compound packet
+ * must be equal to SR or RR
+ **/
+ if( bHeader && ( extractParam.TRTCP_HEADER.pt != ERTCP_SR &&
+ extractParam.TRTCP_HEADER.pt != ERTCP_RR ) )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ if( bHeader )
+ {
+ /**
+ * The padding bit should be zero for for the first packet of a
+ * compound RTCP packet because padding should only be applied,
+ * if it is needed, to the last packet [RFC3550]
+ **/
+ if( extractParam.TRTP.padding != 0 )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+ else
+ {
+ bHeader = EFalse;
+ }
+ }
+
+ parseResult = ProcessOneRTCPReportSectionL( extractParam, sourceSSRC );
+
+ if ( parseResult == ERTCP_FOUND_RXSTREAM )
+ {
+ return ERTCP_FOUND_RXSTREAM;
+ }
+
+ /**
+ * The length fields of the individual RTCP packets must add
+ * up to the overall length of the compound RTCP packet as
+ * received. [RFC3550]
+ **/
+ if ( parseResult != ERTCP_PACKET_MORE )
+ {
+ TInt iTruePacketLength = iPktRtcpRcv->Size();
+
+ iPacketLength += ( ( extractParam.TRTCP_HEADER.length + 1 ) * 4 );
+
+ if ( iPacketLength != iTruePacketLength )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+ }
+ else //if( parseResult != ERTCP_NO_ERROR)
+ {
+ //Get the packet length and convert the 8 bit value to 32 bit
+ iPacketLength += ( ( extractParam.TRTCP_HEADER.length + 1 ) * 4 );
+ }
+
+
+ if ( parseResult == ERTCP_PACKET_ERROR ||
+ parseResult == ERTCP_NO_ERROR )
+ {
+ return parseResult;
+ }
+ } // for loop
+
+ // We should never get here
+ return ERTCP_NO_ERROR;
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessSRSection()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessSRSectionL( TInt aSourceCount )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ TRtpRtcpEnum parseResult( ERTCP_NO_ERROR );
+ CRtpStream* stream;
+ TRtpSSRC tempSSRC( NULL );
+ TUint streamAddress( 0 );
+ TStreamType streamType;
+ TInt ret( 0 );
+
+ // update average RTCP report size
+ AverageRtcpSize( iPktRtcpRcv->Size() );
+
+ // Get SSRC of SR packet, or SSRC_1 in RR Packet
+ tempSSRC = iPktRtcpRcv->RtpPacketGetSSRC();
+ ret = MatchSSRCToStream( streamAddress, tempSSRC, streamType );
+
+ if ( ret != KErrNone )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+ if ( streamType == ERxStream )
+ {
+ stream = ( CRtpRecvStream* ) streamAddress;
+ }
+ else //ETxStream
+ {
+ stream = ( CRtpTranStream* ) streamAddress;
+ }
+ if ( stream == NULL )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+ parseResult = stream->RtpStreamProcessRtcpReportSectionL( iPktRtcpRcv );
+ if ( parseResult == ERTCP_PACKET_ERROR ||
+ parseResult == ERTCP_NO_ERROR )
+ {
+ return parseResult;
+ }
+
+
+ RTCP_DEBUG_DETAIL( "RECEIVE: Parsing SR Report source SSRC secion" );
+
+
+ if ( aSourceCount > 0 )
+ {
+ iPktRtcpRcv->SetType( ERTCP_RR );
+ parseResult = ProcessRRSectionL( aSourceCount );
+ }
+ return parseResult;
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessRRSection()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessRRSectionL( TInt aSourceCount )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ TRtpRtcpEnum parseResult( ERTCP_NO_ERROR );
+ CRtpStream* stream;
+ TRtpSSRC tempSSRC( NULL );
+ TUint streamAddress( 0 );
+ TStreamType streamType;
+ TBool bExit( EFalse );
+ TInt ret( 0 );
+
+ while ( aSourceCount && !bExit )
+ {
+ // extract SSRC_X of RR packet in SR Report packet
+ tempSSRC = iPktRtcpRcv->RtpPacketGetSSRC();
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Parsing RR Report source SSRC ", tempSSRC );
+
+
+ ret = MatchSSRCToStream( streamAddress, tempSSRC, streamType );
+ if ( ret != KErrNone )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ if ( streamType == ERxStream )
+ {
+ stream = reinterpret_cast<CRtpRecvStream*>( streamAddress );
+ }
+ else //ETxStream
+ {
+ stream = reinterpret_cast<CRtpTranStream*>( streamAddress );
+ }
+ // If this is an RR, the sender participant is identified by
+ // streamParam.TRTCP_HEADER.SSRC
+ // DETAIL: Processing RTCP_RR Packet
+ parseResult = stream->RtpStreamProcessRtcpReportSectionL( iPktRtcpRcv );
+ if ( parseResult == ERTCP_PACKET_ERROR ||
+ parseResult == ERTCP_NO_ERROR )
+ // parseResult should not be ERTCP_NO_ERROR, as the packet must
+ // include an SDES section
+ {
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Error/unexpected end of RTCP packet, sender SSRC ",
+ tempSSRC );
+
+
+ return parseResult;
+ }
+
+ aSourceCount--;
+
+ if ( aSourceCount == 0 )
+ {
+ RTCP_DEBUG_DETAIL( "RECEIVE: Parsed Last RR Report" );
+
+
+ bExit = ETrue;
+ }
+ }
+ return parseResult;
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessSDESSection()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::DeallocateMemoryForSdes( TRtpPacketIOParam* aParam )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TInt index( 0 );
+ if ( aParam == NULL )
+ {
+ return;
+ }
+ // deallocate memory for SDES report packet
+ for ( index = 0; index < ERTCP_NUM_OF_SDES_ITEMS; index++ )
+ {
+ if ( aParam->TRTCP_SDES.sdesItems[index] != NULL )
+ {
+ User::Free( aParam->TRTCP_SDES.sdesItems[index] );
+ aParam->TRTCP_SDES.sdesItems[index] = NULL;
+ }
+ aParam->TRTCP_SDES.sdesItemsSize[index] = 0;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::GetSDESFromSDESData()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::GetSDESFromSDESData( TRtpSdesParams* aTargetSdes,
+ const CRtpRecvStream* aRecvStream,
+ CRtpSDES* aSourceSdes )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrGeneral;
+ }
+
+ if ( aRecvStream )
+ {
+ aRecvStream->iRemoteSDES->GetSDES( *aTargetSdes );
+ }
+ else
+ {
+ if ( !aSourceSdes )
+ {
+ return KErrGeneral;
+ }
+ aSourceSdes->GetSDES( *aTargetSdes );
+ }
+ return KErrNone;
+ }
+
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::LogSDESData()
+//
+// ---------------------------------------------------------------------------
+//
+#ifdef _DEBUG
+void CRtpSession::LogSDESData( const TRtpPacketStreamParam& aStreamParam,
+ const CRtpRecvStream* aRecvStream,
+ const CRtpSDES* aSdes,
+ const TBool aSdesSession )
+ {
+
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: NEW SDES item for SSRC = ",
+ aStreamParam.TRTCP_SDES.SSRC );
+
+ if ( !aSdesSession )
+ {
+ RTCP_DEBUG_DETAIL( "RECEIVE: Receiving NEW SDES items as" );
+ for ( TInt k = 0; k < ERTCP_NUM_OF_SDES_ITEMS; k++ )
+ {
+ RTCP_DEBUG_DETAIL( aRecvStream->iRemoteSDES->iSDESItems[k] );
+ }
+ }
+ else
+ {
+ RTCP_DEBUG_DETAIL( "RECEIVE: Receiving NEW SDES items as" );
+ for ( TInt k = 0; k < ERTCP_NUM_OF_SDES_ITEMS; k++ )
+ {
+ RTCP_DEBUG_DETAIL( aSdes->iSDESItems[k] );
+ }
+ }
+
+ }
+
+#endif
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessSDESData()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessSDESDataL( TRtpPacketStreamParam& aStreamParam,
+ TRtpPacketIOParam& aExtractParam,
+ TRtpSSRC aSourceSSRC )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ CRtpSDES* tempSdes = NULL;
+ // Flag to indicate whether SDES is to be assigned to the session
+ TBool fSdesSession( EFalse );
+ TInt newSDESSenderItemFlag( EFalse );
+ TInt err;
+
+ // For finding the receiving stream that belongs to remote participant SSRC
+ TStreamType streamType;
+ TUint streamAddress( NULL );
+ TInt matchResult( KErrNone );
+ CRtpRecvStream* tempStream = NULL;
+ matchResult = MatchSSRCToStream( streamAddress,
+ aStreamParam.TRTCP_SDES.SSRC,
+ streamType );
+
+ // If there are no RX streams, only TX streams, then assign the remote
+ // SDES to the session
+ if ( matchResult != KErrNone && iNumOfTxStreams && !iNumOfRxStreams )
+ {
+ TUint tempSdesAdress = NULL;
+ TBool result( EFalse );
+ TRAP( err, result = AddSdesToArrayL( tempSdesAdress,
+ &aExtractParam ) );
+ if ( result )
+ {
+ tempSdes = ( CRtpSDES * ) tempSdesAdress;
+ TRAP( err, tempSdes->AddSsrcToSdesL( aSourceSSRC ) );
+
+ if ( err )
+ return ERTCP_PACKET_ERROR;
+
+ fSdesSession = ETrue;
+ // increase number of members in session
+ if ( iTotalParticipantsSession <= KRtcpMaximumParticipants )
+ {
+ iTotalParticipantsSession++;
+ }
+ }
+ }
+ else if ( matchResult != KErrNone )
+ {
+ // did not find a matching stream
+ return ERTCP_PACKET_ERROR;
+ }
+ else // check stream type
+ {
+ if ( streamType == ERxStream ) //Rx stream
+ {
+ tempStream = reinterpret_cast<CRtpRecvStream*>( streamAddress );
+ }
+ else // ETxStream
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+ // update/add SDES in session SDES array
+ TUint tempSdesAdress = NULL;
+ TBool result( EFalse );
+ TRAP( err, result = AddSdesToArrayL( tempSdesAdress,
+ &aExtractParam ) );
+ if ( result )
+ {
+ tempSdes = reinterpret_cast<CRtpSDES*>( tempSdesAdress );
+ TRAP( err, tempSdes->AddSsrcToSdesL( aSourceSSRC ) );
+
+ if ( err )
+ return ERTCP_PACKET_ERROR;
+
+ // increase number of members in session
+ if ( iTotalParticipantsSession <= KRtcpMaximumParticipants )
+ {
+ iTotalParticipantsSession++;
+ }
+ }
+ }
+
+ if ( matchResult == KErrNone && !fSdesSession )
+ {
+ newSDESSenderItemFlag = CompareAndUpdateSdes( tempStream->iRemoteSDES,
+ &aExtractParam,
+ ETrue /* Update all */ );
+ }
+
+ if ( iNewSdes )
+ {
+ delete iNewSdes;
+ iNewSdes = NULL;
+ }
+ iNewSdes = new ( ELeave ) TRtpSdesParams() ;
+ if ( !iNewSdes )
+ {
+ delete iNewSdes;
+ iNewSdes = NULL;
+ return ERTCP_PACKET_ERROR;
+ }
+
+ if ( newSDESSenderItemFlag || fSdesSession )
+ {
+ if ( fSdesSession )
+ {
+ GetSDESFromSDESData( iNewSdes, NULL, tempSdes );
+ }
+ else
+ {
+ GetSDESFromSDESData( iNewSdes, tempStream, NULL );
+ }
+ #ifdef _DEBUG
+ LogSDESData( aStreamParam, tempStream, tempSdes, fSdesSession );
+ #endif
+ }
+ else
+ {
+ // No changes in SDES
+
+ RTCP_DEBUG_DETAIL_DVALUE( "NO CHANGES in SDES item for SSRC = ",
+ aStreamParam.TRTCP_SDES.SSRC );
+
+ }
+
+ // Finally, let the observer know what we received
+ if ( iRtcpObserver )
+ {
+ iRtcpObserver->SdesReceived( aStreamParam.TRTCP_SDES.SSRC, *iNewSdes );
+ }
+
+ return ERTCP_NO_ERROR;
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessSDESSectionL()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessSDESSectionL( TRtpSSRC aSourceSSRC )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam extractParam;
+ TRtpRtcpEnum parseResult( ERTCP_NO_ERROR );
+ TRtpRtcpEnum processDataResult( ERTCP_NO_ERROR );
+ TRtpRtcpEnum returnValue( ERTCP_NO_ERROR );
+
+ parseResult = iPktRtcpRcv->RtpPacketProcessL( &streamParam, &extractParam );
+
+ if ( parseResult < ERTCP_NO_ERROR )
+ {
+ returnValue = parseResult;
+ }
+ else
+ {
+ processDataResult = ProcessSDESDataL( streamParam, extractParam,
+ aSourceSSRC );
+ if ( processDataResult != ERTCP_NO_ERROR )
+ {
+ returnValue = processDataResult;
+ }
+ else
+ {
+ // parseResult may be ERTCP_NO_ERROR or ERTCP_PACKET_MORE (BYE/APP)
+ returnValue = parseResult;
+ }
+ }
+
+ DeallocateMemoryForSdes( &extractParam );
+ return returnValue;
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessBYESection()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessBYESectionL()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam extractParam;
+
+ TRtpRtcpEnum parseResult = ERTCP_NO_ERROR;
+
+ parseResult = iPktRtcpRcv->RtpPacketProcessL( &streamParam, &extractParam );
+
+ if ( parseResult < ERTCP_NO_ERROR )
+ {
+ if ( extractParam.TRTCP_BYE.reason != NULL )
+ {
+ User::Free( extractParam.TRTCP_BYE.reason );
+ }
+ return ERTCP_PACKET_ERROR;
+ }
+
+ // find the receiving stream that belongs to remote participant SSRC
+ TStreamType streamType;
+ TUint rcvStreamAddress = NULL;
+ TRtpId rcvStreamId = 0;
+ TInt ret = KErrNone;
+ CRtpRecvStream* rcvStream;
+ ret = MatchSSRCToStream( rcvStreamAddress, streamParam.TRTCP_BYE.SSRC,
+ streamType );
+ if ( streamType == ERxStream )
+ {
+ rcvStream = reinterpret_cast<CRtpRecvStream*>( rcvStreamAddress );
+ }
+ else
+ {
+ if ( extractParam.TRTCP_BYE.reason != NULL )
+ {
+ User::Free( extractParam.TRTCP_BYE.reason );
+ }
+ return ERTCP_PACKET_ERROR;
+ }
+ if ( ret == KErrNone )
+ {
+ rcvStreamId = rcvStream->GetStreamID();
+ TPtrC8 reason( const_cast<const TUint8*>( extractParam.TRTCP_BYE.reason ),
+ extractParam.TRTCP_BYE.reasonSize );
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Receiving BYE message RX stream ID ", rcvStreamId );
+ RTCP_DEBUG_DETAIL( extractParam.TRTCP_BYE.reason );
+
+
+ if ( iRtcpObserver )
+ {
+ iRtcpObserver->ByeReceived( rcvStreamId,
+ streamParam.TRTCP_BYE.SSRC, reason );
+ }
+
+ // Delete the SDES information in the array for this SSRC and decrease
+ // number participants in session
+ ret = RemoveSdesFromArray( streamParam.TRTCP_BYE.SSRC );
+ if ( ret == KErrNone )
+ {
+ if ( iTotalParticipantsSession > 1 )
+ {
+ iTotalParticipantsSession--;
+ }
+ }
+
+ if ( extractParam.TRTCP_BYE.reason != NULL )
+ {
+ User::Free( extractParam.TRTCP_BYE.reason );
+ }
+ parseResult = ERTCP_FOUND_RXSTREAM;
+ }
+
+ return parseResult;
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpSession::ProcessAPPSection()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpSession::ProcessAPPSectionL( TInt aTotalPacketLen,
+ TInt aSubType )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam extractParam;
+ TRtpRtcpEnum parseResult = ERTCP_NO_ERROR;
+
+ streamParam.TRTCP_APP.totalPacketLen = aTotalPacketLen;
+ parseResult = iPktRtcpRcv->RtpPacketProcessL( &streamParam, &extractParam );
+
+ if ( parseResult < ERTCP_NO_ERROR )
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+ // find the receiving stream that belongs to remote participant SSRC
+ TStreamType streamType;
+ TUint rcvStreamAddress = NULL;
+ TRtpId rcvStreamId = 0;
+ TInt ret = KErrNone;
+ CRtpRecvStream* rcvStream;
+ ret = MatchSSRCToStream( rcvStreamAddress, streamParam.TRTCP_APP.SSRC,
+ streamType );
+ if ( streamType == ERxStream )
+ {
+ rcvStream = reinterpret_cast<CRtpRecvStream*>( rcvStreamAddress );
+ }
+ else
+ {
+ return ERTCP_PACKET_ERROR;
+ }
+
+ if ( ret == KErrNone )
+ {
+ rcvStreamId = rcvStream->GetStreamID();
+
+ TRtcpApp app;
+ app.iSubType = aSubType;
+ Mem::Copy( app.iName, extractParam.TRTCP_APP.name,
+ sizeof( TRtcpAppName ) );
+ Mem::Copy( app.iAppData, extractParam.TRTCP_APP.appData,
+ extractParam.TRTCP_APP.appDataLen );
+ app.iAppDataLen = extractParam.TRTCP_APP.appDataLen;
+
+ if ( iRtcpObserver )
+ {
+ iRtcpObserver->AppReceived( rcvStreamId,
+ streamParam.TRTCP_APP.SSRC, app );
+ }
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RECEIVE: Receiving APP message RX stream ID ", rcvStreamId );
+ RTCP_DEBUG_DETAIL( extractParam.TRTCP_APP.appData );
+
+
+ User::Free( extractParam.TRTCP_APP.appData );
+ parseResult = ERTCP_FOUND_RXSTREAM;
+ }
+
+ return parseResult;
+ }
+
+// ---------------------------------------------------------------------------
+// void CRtpSession::StopRtcpSending()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::StopRtcpSending()
+ {
+ TInt result( KErrNotSupported );
+ if ( iRtcpEnabled )
+ {
+ iSndRtcpTimer->Cancel();
+ iRtcpSendingSuspended = ETrue;
+ result = KErrNone;
+ }
+ return result;
+ }
+
+// ---------------------------------------------------------------------------
+// void CRtpSession::IsRtcpSendingSuspended()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::IsRtcpSendingSuspended( TBool& aAutoSending )
+ {
+ TInt result( KErrNotSupported );
+ if ( iRtcpEnabled )
+ {
+ aAutoSending = !iRtcpSendingSuspended;
+ result = KErrNone;
+ }
+ return result;
+ }
+
+// ---------------------------------------------------------------------------
+// void CRtpSession::ResumeRtcpSending()
+//
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::ResumeRtcpSending()
+ {
+ TInt result( KErrNotSupported );
+ if ( iRtcpEnabled )
+ {
+ iRtcpSendingSuspended = EFalse;
+ result = KErrNone;
+ if ( iSessionStarted )
+ {
+ if ( !iSndRtcpTimer->IsActive() )
+ {
+ iSndRtcpTimer->After( iRtcpTimeInterval *
+ KMicrosecondPerMillSecond );
+ }
+ else
+ {
+ result = KErrInUse;
+ }
+ }
+ }
+ return result;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::ScheduleRtcpSend()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::ScheduleRtcpSendL()
+ {
+ if ( iRtcpEnabled && !iRtcpSendingSuspended )
+ {
+ BuildSendRTCPReportL();
+ NextRtcpInterval();
+ iSndRtcpTimer->After( iRtcpTimeInterval * KMicrosecondPerMillSecond );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::OnExpiredL()
+// Rtcp scheduler time out call back
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::OnExpiredL( TInt /*aStatus*/ )
+ {
+ if ( iRtcpEnabled )
+ {
+ ScheduleRtcpSendL();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::OnRtpReceivedL()
+// Rtp received callback
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::OnRtpReceivedL()
+ {
+ RTP_DEBUG_DETAIL( "CRtpSession::OnRtpReceivedL Entry" );
+
+ TInt ret;
+ if ( iStandardRtp )
+ {
+ if ( iRtpRecvBuf.Size() < KMinRtpHeaderSize )
+ {
+ // The packet is too short to be valid (min 96 bits in header).
+ // Discard and continue to issue packet receiving.
+
+ RTP_DEBUG_DETAIL( "Rtp packet too small, discarded" );
+
+
+ // if someone is interested receiving non-RTP control packets
+ if (iNonRTPDataObserver != NULL)
+ {
+ // notify user
+ iNonRTPDataObserver->NonRTPDataReceived(GetRtpSocket()->LocalPort(),
+ ETrue, iRtpRecvBuf);
+ }
+ }
+ else
+ {
+
+ iPktRcv->SetSize( iRtpRecvBuf.Size() );
+
+ RTP_DEBUG_DETAIL_DVALUE( "Rtp Packet size = ", iRtpRecvBuf.Size() );
+
+ // Give the packet to each Rx stream until the stream SSRC matches
+ // the SSRC of the RTP packet
+
+ RTP_DEBUG_DETAIL( "FindRtpRxStream by SSRC" );
+
+ ret = FindRtpRxStreamL();
+
+ if ( ret != KErrNone )
+ {
+ // If no RX streams match remote SSRC, then allow any RX stream
+ // with Null SSRC to accept RTP packet
+
+ RTP_DEBUG_DETAIL( "No RX streams match set remote SSRC" );
+
+ RTP_DEBUG_DETAIL( "Check if any RX stream with Null SSRC to accept RTP packet" );
+ ret = AssignRtpRxStreamL();
+
+ if ( ret != KErrNone )
+ {
+ //FindAnotherSSRC
+
+ if( ret == KErrNotFound )
+ {
+
+ RTP_DEBUG_DETAIL( "Find another remote SSRC " );
+
+ RTP_DEBUG_DETAIL( "Either is NonRtp data or a new RTP SSRC stream has to be created" );
+
+ iPktRcv->RtpPacketResetPtr();
+
+ TRtpPacketStreamParam streamParam;
+ TRtpPacketIOParam extractParam;
+
+ // process RTP packet
+ iPktRcv->SetType( ERTP );
+
+ extractParam.TRTP.extension.data = NULL;
+
+ if ( iPktRcv->RtpPacketProcessL( &streamParam, &extractParam ) < 0 )
+ {
+ RTP_DEBUG_DETAIL( "Invalid Rtp packet is received" );
+
+ if (iNonRTPDataObserver != NULL)
+ {
+ // notify user
+ iNonRTPDataObserver->NonRTPDataReceived(GetRtpSocket()->LocalPort(),
+ ETrue, iRtpRecvBuf);
+ }
+ }
+ else
+ {
+ //Valid RTP packet only
+ RTP_DEBUG_DETAIL( "Create new Recv Stream for valid RTP packet " );
+ CreateNewRecvStreamL();
+ }
+
+ }
+
+ else
+ {
+ // Maybe invalid packet received, continue to receive
+ // if someone is interested receiving non-RTP control packets
+
+ if (iNonRTPDataObserver != NULL)
+ {
+ RTP_DEBUG_DETAIL( "NonRtpDataReceived" );
+ // notify user
+ iNonRTPDataObserver->NonRTPDataReceived(GetRtpSocket()->LocalPort(),
+ ETrue, iRtpRecvBuf);
+ }
+ }
+
+ }
+
+ }
+ }
+ }
+ else
+ {
+ RTP_DEBUG_DETAIL( "Not standard RTP packets" );
+
+ iPktExtRcv->SetSize( iRtpRecvBuf.Size() );
+ TUint8* buf = 0;
+ TInt length;
+ ret = iPktExtRcv->RtpPacketProcess( buf, &length );
+ }
+ RTP_DEBUG_DETAIL( "CRtpSession::OnRtpReceivedL Exit" );
+
+ IssueRtpRecv();
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::OnRtcpReceivedL()
+// Rtcp received call back
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::OnRtcpReceivedL()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TRtpRtcpEnum errPacket;
+ iPktRtcpRcv->SetSize( iRtcpRecvBuf.Size() );
+
+ errPacket = ProcessRTCPReportL();
+
+ // if someone is interested receiving non-RTP control packets
+ if (errPacket == ERTCP_PACKET_ERROR && iNonRTPDataObserver != NULL)
+ {
+ // notify user
+ iNonRTPDataObserver->NonRTPDataReceived(GetRtcpSocket()->LocalPort(), EFalse,
+ iRtcpRecvBuf);
+ }
+
+ IssueRtcpRecv();
+
+ if ( errPacket == ERTCP_PACKET_ERROR )
+ {
+ iRtcpErrors++;
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "ERROR: Packet error Session ID = ", iSessionId );
+
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::OnReceptionError()
+// Rtcp reception error call back
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::OnReceptionError( TPortType aPort, TInt aError )
+ {
+
+ RTP_DEBUG_DETAIL( "CRtpSession::OnReceptionError" );
+
+
+ switch ( aError )
+ {
+ case KErrDisconnected:
+
+ RTP_DEBUG_DETAIL( "Socket Disconnected" );
+
+ break;
+
+ default:
+ if ( aPort == ERTCPPort )
+ {
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RTCP reception error",
+ aError );
+
+ IssueRtcpRecv();
+ }
+ else
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "RTP reception error",
+ aError );
+
+ IssueRtpRecv();
+ }
+
+ RTP_DEBUG_DETAIL( "Restarting reception" );
+
+ break;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpSSRC CRtpSession::OnPacketRejected()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::OnPacketRejected(TPortType aPort)
+ {
+
+ RTP_DEBUG_DETAIL( "OnPacketRejected" );
+
+
+ if ( aPort == ERTPPort )
+ {
+ IssueRtpRecv();
+ }
+ else
+ {
+ IssueRtcpRecv();
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// TRtpSSRC CRtpSession::GenerateSSRC()
+//
+// ---------------------------------------------------------------------------
+//
+TRtpSSRC CRtpSession::GenerateSSRC()
+ {
+ return static_cast<TUint32>( Random() );
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::AddStream()
+// Add Stream object to array
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::AddStream( const TStream aArrayID, TStreamType aStreamType )
+ {
+ if ( aStreamType == ERxStream )
+ {
+ TRAPD( ret, iStreamRxArray->AppendL( aArrayID ) );
+ return ret;
+ }
+ else //ETxStream
+ {
+ TRAPD( ret, iStreamTxArray->AppendL( aArrayID ) );
+ return ret;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::FindStream()
+// Find Stream Object in array
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::FindStream( const TRtpId aMagicKey, TUint& aStreamAddress )
+ {
+ TKeyArrayFix magicKey( TStream::iOffset, ECmpTUint );
+ TInt index = -1;
+
+ TStream match( aMagicKey, 0 );
+ if ( ( iStreamRxArray->Find( match, magicKey, index ) == KErrNone )
+ && ( index >= 0 ) )
+ {
+ aStreamAddress = iStreamRxArray->At( index ).GetStreamAddress();
+ }
+ else if ( ( iStreamTxArray->Find( match, magicKey, index ) == KErrNone )
+ && ( index >= 0 ) )
+ {
+ aStreamAddress = iStreamTxArray->At( index ).GetStreamAddress();
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::FindStream()
+// Find Stream Object in array
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::FindStream( const TRtpId aMagicKey, TUint& aStreamAddress,
+ TStreamType& aStreamType )
+ {
+ TKeyArrayFix magicKey( TStream::iOffset, ECmpTUint );
+ TUint temp = 0;
+ TInt index = -1;
+
+ TStream match( aMagicKey, temp );
+ if ( ( iStreamRxArray->Find( match, magicKey, index ) == KErrNone )
+ && ( index >= 0 ) )
+ {
+ aStreamAddress = iStreamRxArray->At( index ).GetStreamAddress();
+ aStreamType = ERxStream;
+ }
+ else if ( ( iStreamTxArray->Find( match, magicKey, index ) == KErrNone )
+ && ( index >= 0 ) )
+ {
+ aStreamAddress = iStreamTxArray->At( index ).GetStreamAddress();
+ aStreamType = ETxStream;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::RemoveStream()
+// Delete Stream object from array
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::RemoveStream( const TRtpId aMagicKey,
+ TStreamType& aStreamType )
+ {
+ TKeyArrayFix magicKey( TStream::iOffset, ECmpTUint );
+ TInt index = -1;
+
+ TStream match( aMagicKey );
+ if ( ( iStreamRxArray->Find( match, magicKey, index ) == KErrNone )
+ && ( index >= 0 ) )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "RX STREAM ARRAY: Remove Stream ID = ",
+ iStreamRxArray->At( index ).GetMagicKey() );
+
+
+ CRtpRecvStream* tempStream = reinterpret_cast<CRtpRecvStream*>(
+ ( iStreamRxArray->At( index ).GetStreamAddress() ) );
+
+
+ aStreamType = ERxStream;
+ delete tempStream;
+ iStreamRxArray->Delete( index );
+ iStreamRxArray->Compress();
+ }
+ else if ( ( iStreamTxArray->Find( match, magicKey, index ) == KErrNone )
+ && ( index >= 0 ) )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "TX STREAM ARRAY: Remove Stream ID = ",
+ iStreamTxArray->At( index ).GetMagicKey() );
+
+
+ CRtpTranStream* tempStream = reinterpret_cast<CRtpTranStream*>(
+ ( iStreamTxArray->At( index ).GetStreamAddress() ) );
+ aStreamType = ETxStream;
+ delete tempStream;
+ iStreamTxArray->Delete( index );
+ iStreamTxArray->Compress();
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::RemoveAllStreams()
+// Delete all stream objects from array
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::RemoveAllStreams()
+ {
+ if ( iStreamRxArray )
+ {
+ TInt totalRxStream( iStreamRxArray->Count() );
+
+ //Delete all RX Streams starting with the last one
+ while( totalRxStream > 0 )
+ {
+ //totalRxStream - 1 is the last element in the array
+
+ RTP_DEBUG_DETAIL_DVALUE("RX STREAM ARRAY: Remove ALL RX Stream ID = ",
+ iStreamRxArray->At( totalRxStream - 1 ).GetMagicKey() );
+
+
+ CRtpRecvStream* tempStream = reinterpret_cast<CRtpRecvStream*>(
+ ( iStreamRxArray->At( totalRxStream - 1 ).GetStreamAddress() ) );
+ delete tempStream;
+
+ iStreamRxArray->Delete( totalRxStream - 1 );
+ totalRxStream = iStreamRxArray->Count();
+ }
+
+ iStreamRxArray->Reset();
+ iStreamRxArray->Compress();
+ }
+
+ if ( iStreamTxArray )
+ {
+ TInt totalTxStream( iStreamTxArray->Count() );
+
+ //Delete all TX Streams starting with the last one
+ while ( totalTxStream > 0 )
+ {
+ //totalTxStream - 1 is the last element in the array
+
+ RTP_DEBUG_DETAIL_DVALUE( "TX STREAM ARRAY: Remove ALL TX Stream ID = ",
+ iStreamTxArray->At( totalTxStream - 1 ).GetMagicKey() );
+
+
+ CRtpTranStream* tempStream = reinterpret_cast<CRtpTranStream*>(
+ ( iStreamTxArray->At( totalTxStream - 1 ).GetStreamAddress() ) );
+ delete tempStream;
+
+ iStreamTxArray->Delete( totalTxStream - 1 );
+ totalTxStream = iStreamTxArray->Count();
+ }
+
+ iStreamTxArray->Reset();
+ iStreamTxArray->Compress();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::FindRtpRxStreamSSRC()
+// Find a RX stream that matches RTP packet SSRC
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::FindRtpRxStreamSSRC(TRtpSSRC& aSSRC)
+ {
+ aSSRC=0;
+ TInt totalStream = iStreamRxArray->Count();
+
+ if ( totalStream > 0 )
+ {
+ for ( TInt index = 0; index < totalStream; index++ )
+ {
+ CRtpRecvStream* tempStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+
+ iPktRcv->RtpPacketResetPtr();
+
+ TRtpSSRC aRemoteSSRC( NULL );
+ iPktRcv->SetType( ERTP );
+ aRemoteSSRC = iPktRcv->RtpPacketGetSSRC();
+ //first if the stream has been assigned else assign it with this packetSSRC
+ if ( tempStream->GetRemoteSSRC() == aRemoteSSRC )
+ {
+ aSSRC=aRemoteSSRC;
+
+ }
+ }
+ if (aSSRC==0)
+ {
+ for ( TInt index = 0; index < totalStream; index++ )
+ {
+ CRtpRecvStream* tempStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+
+ //find stream with emptly ssrc
+ if ( tempStream->GetRemoteSSRC()==NULL )
+ {
+ iPktRcv->RtpPacketResetPtr();
+ aSSRC = iPktRcv->RtpPacketGetSSRC();
+ }
+ }
+ }
+ }
+
+ }
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::FindRtpRxStreamL()
+// Find a RX stream that matches RTP packet SSRC
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::FindRtpRxStreamL()
+ {
+ TInt ret = KErrNotFound;
+ TBool assignRcvStream = EFalse;
+ TInt totalStream = iStreamRxArray->Count();
+
+ if ( totalStream > 0 )
+ {
+ for ( TInt index = 0; index < totalStream; index++ )
+ {
+ CRtpRecvStream* tempStream = ( CRtpRecvStream* )
+ ( iStreamRxArray->At( index ).GetStreamAddress() );
+ ret = tempStream->RtpStreamProcessRtpPacketL( iPktRcv,
+ assignRcvStream );
+ if ( ret == KErrNone )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "RX STREAM ARRAY: FOUND RX (RTP) stream ID = ",
+ tempStream->GetStreamID() );
+
+
+ return ret;
+ }
+ }
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::AssignRtpRxStreamL()
+// Assigns a RX stream to the RTP packet SSRC
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::AssignRtpRxStreamL()
+ {
+ RTP_DEBUG_DETAIL( "CRtpSession::AssignRtpRxStream Entry" );
+ TInt index;
+ TInt ret = KErrNotFound;
+ TBool assignRcvStream = ETrue;
+ TInt totalStream = iStreamRxArray->Count();
+
+ if ( totalStream > 0 )
+ {
+ for ( index = 0; index < totalStream; index++ )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE(
+ "RX STREAM ARRAY: Assigning RTP to RX stream ID = ",
+ iStreamRxArray->At( index ).GetMagicKey() );
+
+
+ CRtpRecvStream* tempStream = reinterpret_cast<CRtpRecvStream*>(
+ ( iStreamRxArray->At( index ).GetStreamAddress() ) );
+ ret = tempStream->RtpStreamProcessRtpPacketL( iPktRcv,
+ assignRcvStream );
+ if ( ret == KErrNone )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "RX STREAM ARRAY: ASSIGNED RX stream SSRC = ",
+ tempStream->GetLocalSSRC() );
+
+ RTP_DEBUG_DETAIL( "CRtpSession::AssignRtpRxStream Exit" );
+ return ret;
+ }
+ }
+ }
+ RTP_DEBUG_DETAIL( "no stream in RTP Sesssion" );
+
+ RTP_DEBUG_DETAIL( "CRtpSession::AssignRtpRxStream Exit" );
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::MatchSSRCToStream()
+// finds a stream for a given source SSRC
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::MatchSSRCToStream( TUint& aStreamAddress,
+ TRtpSSRC aSSRC,
+ TStreamType& aStreamType )
+ {
+ TInt index;
+ TInt totalRxStream = iStreamRxArray->Count();
+ TInt totalTxStream = iStreamTxArray->Count();
+
+ if ( totalRxStream > 0 )
+ {
+ for ( index = 0; index < totalRxStream; index++ )
+ {
+ TUint streamAddr( iStreamRxArray->At( index ).GetStreamAddress() );
+ CRtpRecvStream* tempStream =
+ reinterpret_cast<CRtpRecvStream*>( streamAddr );
+ if ( tempStream->GetRemoteSSRC() == aSSRC )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "RX STREAM ARRAY: MATCHED RX stream ID = ",
+ tempStream->GetStreamID() );
+ RTP_DEBUG_DETAIL_DVALUE( "RX STREAM ARRAY: MATCHED RX stream Key = ",
+ iStreamRxArray->At( index ).GetMagicKey() );
+ RTP_DEBUG_DETAIL_DVALUE( "RX STREAM ARRAY: MATCHED RX stream SSRC = ",
+ tempStream->GetLocalSSRC() );
+
+
+ aStreamAddress = streamAddr;
+ aStreamType = ERxStream;
+ return KErrNone;
+ }
+ }
+ }
+
+ if ( totalTxStream > 0 )
+ {
+ for ( index = 0; index < totalTxStream; index++ )
+ {
+ TUint streamAddr( iStreamTxArray->At( index ).GetStreamAddress() );
+ CRtpTranStream* tempStream =
+ reinterpret_cast<CRtpTranStream*>( streamAddr );
+ if ( tempStream->GetLocalSSRC() == aSSRC )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "TX STREAM ARRAY: MATCHED TX stream ID = ",
+ tempStream->GetStreamID() );
+ RTP_DEBUG_DETAIL_DVALUE( "TX STREAM ARRAY: MATCHED TX stream Key = ",
+ iStreamTxArray->At( index ).GetMagicKey() );
+ RTP_DEBUG_DETAIL_DVALUE( "TX STREAM ARRAY: MATCHED TX stream SSRC = ",
+ tempStream->GetLocalSSRC() );
+
+
+ aStreamAddress = streamAddr;
+ aStreamType = ETxStream;
+ return KErrNone;
+ }
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::FindStreamForSSRC()
+// Finds if a send stream is already using the given SSRC
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::FindStreamForSSRC( TRtpSSRC aSSRC )
+ {
+ TInt index;
+ TInt totalRxStream = iStreamRxArray->Count();
+ TInt totalTxStream = iStreamTxArray->Count();
+
+ if ( totalRxStream > 0 )
+ {
+ for ( index = 0; index < totalRxStream; index++ )
+ {
+ CRtpRecvStream* tempStream = reinterpret_cast<CRtpRecvStream*>(
+ iStreamRxArray->At( index ).GetStreamAddress() );
+ if ( tempStream->GetLocalSSRC() == aSSRC )
+ {
+
+ RTP_DEBUG_DETAIL_DVALUE( "RX STREAM ARRAY: SSRC Being Used = ", aSSRC );
+
+
+ return ETrue;
+ }
+ }
+ }
+
+ if ( totalTxStream > 0 )
+ {
+ for ( index = 0; index < totalTxStream; index++ )
+ {
+ CRtpTranStream* tempStream = reinterpret_cast<CRtpTranStream*>(
+ iStreamTxArray->At( index ).GetStreamAddress() );
+ if ( tempStream->GetLocalSSRC() == aSSRC )
+ {
+ RTP_DEBUG_DETAIL_DVALUE( "TX STREAM ARRAY: SSRC Being Used = ", aSSRC );
+
+
+ return ETrue;
+ }
+ }
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::FindTxStreamForSSRC()
+// Finds if a send stream is already using the given SSRC
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::FindTxStreamForSSRC( TRtpSSRC aSSRC,
+ CRtpTranStream** streamPointerPointer )
+ {
+ TInt index( 0 );
+ TInt totalTxStream( iStreamTxArray->Count() );
+
+ if ( totalTxStream > 0 )
+ {
+ for ( index = 0; index < totalTxStream; index++ )
+ {
+ CRtpTranStream* tempStream = reinterpret_cast<CRtpTranStream*>(
+ iStreamTxArray->At( index ).GetStreamAddress() );
+ if ( tempStream->GetLocalSSRC() == aSSRC )
+ {
+ RTP_DEBUG_DETAIL_DVALUE( "TX STREAM ARRAY: SSRC Being Used = ", aSSRC );
+
+ if ( streamPointerPointer )
+ {
+ // put the address of the CRtpTranStream object into the
+ // specified pointer
+ *streamPointerPointer = tempStream;
+ }
+ return ETrue;
+ }
+ }
+ }
+
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::RcvStreamActive()
+// checks if a receive stream is active
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::RcvStreamActive( TInt aIndex )
+ {
+ CRtpRecvStream* tempRcvStream = reinterpret_cast<CRtpRecvStream*>(
+ iStreamRxArray->At( aIndex ).GetStreamAddress() );
+ if ( !tempRcvStream->FirstPkg() )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::AnyRcvStreamReceivedRtpPacket()
+// checks if any receive stream has received an RTP packet
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::AnyRcvStreamReceivedRtpPacket()
+ {
+ TInt totalRcvStream = iStreamRxArray->Count();
+ for ( TInt index = 0; index < totalRcvStream; index++ )
+ {
+ CRtpRecvStream* tempRcvStream = reinterpret_cast<CRtpRecvStream*>(
+ iStreamRxArray->At( index ).GetStreamAddress() );
+ if ( tempRcvStream->ReceivedRTPPackets() )
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::RcvStreamReceivedRtpPacket()
+// checks if a receive stream has received an RTP packet
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::RcvStreamReceivedRtpPacket( TInt aIndex )
+ {
+ CRtpRecvStream* tempRcvStream = reinterpret_cast<CRtpRecvStream*>(
+ iStreamRxArray->At( aIndex ).GetStreamAddress() );
+ if ( tempRcvStream->ReceivedRTPPackets() )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpRecvStream* CRtpSession::GetRcvStreamByIndex()
+// gets a receive stream based on an index value
+// ---------------------------------------------------------------------------
+//
+CRtpRecvStream* CRtpSession::GetRcvStreamByIndex( TInt aIndex )
+ {
+ CRtpRecvStream* tempRcvStream = reinterpret_cast<CRtpRecvStream*>(
+ iStreamRxArray->At( aIndex ).GetStreamAddress() );
+ return tempRcvStream;
+ }
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::DoAddSdesToEmptyArrayL()
+// Adds a new SDES object to the SDES array
+// ---------------------------------------------------------------------------
+//
+CRtpSDES* CRtpSession::DoAddSdesToArrayL( TRtpPacketIOParam* aExtractParam )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return NULL;
+ }
+
+ CRtpSDES* tempSdes = CRtpSDES::NewL();
+ CleanupStack::PushL( tempSdes );
+ // check for empty SDES sections
+ for ( TInt k = 0; k < ERTCP_NUM_OF_SDES_ITEMS; k++ )
+ {
+ if ( ( aExtractParam->TRTCP_SDES.sdesItemsSize[k] ) > 0 )
+ {
+ TRtpUtil::Strcpy( tempSdes->iSDESItems[k],
+ aExtractParam->TRTCP_SDES.sdesItems[k] );
+ tempSdes->iSDESItemsSize[k] =
+ aExtractParam->TRTCP_SDES.sdesItemsSize[k];
+ }
+ }
+ iSdesArray->AppendL( tempSdes );
+ CleanupStack::Pop( tempSdes );
+ return tempSdes;
+ }
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::CompareAndUpdateSdes()
+// Compares the specified SDES values with the ones in the parameters and
+// updates the SDES where the values differ, starting from the specified index
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::CompareAndUpdateSdes( CRtpSDES* aTempSdes,
+ TRtpPacketIOParam* aExtractParam,
+ TBool aUpdateCName )
+ {
+ TBool updatedSdes( EFalse );
+ TInt startValue( 0 );
+ if ( !aUpdateCName )
+ {
+ startValue = 1;
+ }
+ for ( TInt k = startValue; k < ERTCP_NUM_OF_SDES_ITEMS; k++ )
+ {
+ if ( ( aExtractParam->TRTCP_SDES.sdesItemsSize[k] ) > 0 )
+ {
+ TPtrC8 s2( _L8( aTempSdes->iSDESItems[k] ) );
+ if ( s2.Compare( _L8( aExtractParam->TRTCP_SDES.sdesItems[k] ) )
+ != 0 )
+ {
+ TRtpUtil::Strcpy( aTempSdes->iSDESItems[k],
+ aExtractParam->TRTCP_SDES.sdesItems[k] );
+ aTempSdes->iSDESItemsSize[k] =
+ aExtractParam->TRTCP_SDES.sdesItemsSize[k];
+ updatedSdes = ETrue;
+ }
+ }
+ }
+ return updatedSdes;
+ }
+
+// ---------------------------------------------------------------------------
+// TBool CRtpSession::AddSdesToArrayL()
+// adds SDES object to SDES array if it is new SDES or updates SDES information
+// if it has changed
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::AddSdesToArrayL( TUint& aSdesAddress,
+ TRtpPacketIOParam* aExtractParam )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return EFalse;
+ }
+
+ TBool fFoundSDES( EFalse );
+ TBool fUpdatedSDES( EFalse );
+ CRtpSDES* tempSdes = NULL;
+ // find if SDES exists or has been changed
+ TInt totalSdes( iSdesArray->Count() );
+
+ if ( totalSdes == 0 )
+ {
+ // First SDES item, add it to the array
+ aSdesAddress =
+ reinterpret_cast<TUint>( DoAddSdesToArrayL( aExtractParam ) );
+ return ETrue;
+ }
+
+ // SDES items exist, check if this one needs to be added
+ TBool bExit = EFalse;
+
+ for ( TInt index = 0; index < totalSdes && !bExit; index++ )
+ {
+ tempSdes = iSdesArray->At( index );
+ // assuming CNAME is always included and does not change,
+ // then a new SDES will have a different CNAME
+
+ if ( ( aExtractParam->TRTCP_SDES.
+ sdesItemsSize[ERTCP_SDES_CNAME] ) == 0 )
+ {
+ return EFalse;
+ }
+
+ TPtrC8 s1( _L8( tempSdes->iSDESItems[ERTCP_SDES_CNAME] ) );
+ if ( s1.Compare( _L8( aExtractParam->TRTCP_SDES.
+ sdesItems[ERTCP_SDES_CNAME] ) ) == 0 )
+ {
+ fFoundSDES = ETrue;
+ bExit = ETrue;
+ // Update SDES, but exclude CName
+ fUpdatedSDES = CompareAndUpdateSdes( tempSdes, aExtractParam,
+ EFalse );
+ }
+ }
+
+ if ( !fFoundSDES ) // new SDES, must add it to the array
+ {
+ aSdesAddress =
+ reinterpret_cast<TUint>( DoAddSdesToArrayL( aExtractParam ) );
+ return ETrue;
+ }
+ else if ( fUpdatedSDES )
+ {
+ aSdesAddress = reinterpret_cast<TUint>( tempSdes );
+ return EFalse;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpSession::RemoveSdesFromArray()
+// Removes SDES object from SDES array
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::RemoveSdesFromArray( TRtpSSRC aSSRC )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return KErrGeneral;
+ }
+
+ TInt totalSdes( iSdesArray->Count() );
+
+ for ( TInt index = 0; index < totalSdes; index++ )
+ {
+ CRtpSDES* tempSdes = iSdesArray->At( index );
+ if ( tempSdes->GetSdesSsrc( aSSRC ) )
+ {
+ delete tempSdes;
+ iSdesArray->Delete( index );
+ iSdesArray->Compress();
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "SDES ARRAY: Remove SDES Info for SSRC = ", aSSRC );
+
+
+ return KErrNone;
+ }
+ }
+ return KErrNotFound;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::NextRtcpInterval()
+// calculates new RTCP interval which depends on number of
+// sender and receiver in session (see RFC 1889 for description)
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::NextRtcpInterval()
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ TUint senders( 0 );
+ TUint rtcpBandwidth( static_cast<TUint>( iBandWidth * iFraction ) );
+ TUint members( iTotalParticipantsSession );
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "CRtpSession::NextRtcpInterval - total participants = ",
+ iTotalParticipantsSession );
+
+
+ senders = iNumOfRxStreams + iNumOfTxStreams;
+
+ if ( senders > 0 && senders < members * KRtpDefaultSenderBWFrac )
+ {
+ if ( iNumOfTxStreams )
+ {
+ rtcpBandwidth = static_cast<TUint>
+ ( rtcpBandwidth * KRtpDefaultSenderBWFrac );
+ members = senders;
+ }
+ else
+ {
+ rtcpBandwidth = static_cast<TUint>
+ ( rtcpBandwidth * KRtpDefaultObserverBWFrac );
+ members -= senders;
+ }
+ }
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "CRtpSession::NextRtcpInterval - members = ",
+ members );
+
+ RTCP_DEBUG_DETAIL_DVALUE( "CRtpSession::NextRtcpInterval - rtcpBandwidth = ",
+ rtcpBandwidth );
+
+
+ // 1000 - milliseconds in one second
+ // 8 - bits in one byte
+ iRtcpTimeInterval = static_cast<TUint>( ( 1000 * iAverageRtcpSize * 8 * members )
+ / rtcpBandwidth );
+ if ( iRtcpTimeInterval < KMinRtcpTimeInterval )
+ {
+ iRtcpTimeInterval = KMinRtcpTimeInterval;
+ }
+ TReal rtcpTimeInterval64 = iRtcpTimeInterval * ( Random64() + 0.5 );
+ iRtcpTimeInterval = static_cast<TUint>( rtcpTimeInterval64 );
+ iRtcpTimeInterval = static_cast<TUint>( iRtcpTimeInterval / KCompensationRtcp );
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "CRtpSession::NextRtcpInterval - RTCP Interval (ms) = ",
+ iRtcpTimeInterval );
+
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::AverageRtcpSize()
+// updates average RTCP report size
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::AverageRtcpSize( TUint aRtcpReportSize )
+ {
+ if ( !iRtcpEnabled )
+ {
+ return;
+ }
+
+ iAverageRtcpSize = ( aRtcpReportSize ) * KRtcpSizeGain +
+ ( iAverageRtcpSize * KRtcpSizeGainRemainder );
+
+
+ RTCP_DEBUG_DETAIL_DVALUE( "RTCP: Actual RTCP report size ", aRtcpReportSize );
+ RTCP_DEBUG_DETAIL_DVALUE( "RTCP: Average RTCP report size ", (TInt) iAverageRtcpSize );
+
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::CheckRemoteSsrcL()
+// SSRC collision handling
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::CheckRemoteSsrcL( TRtpSSRC& aSSRC )
+ {
+ CRtpTranStream* tranStream;
+ TBuf8<15> buf;
+ TRtpSSRC ssrc( 0 );
+
+ // In case of collision, we change SSRC only once (RFC3550)
+ // So if we already jumped once, this function does nothing.
+ if ( iSSRCJumps > 0 )
+ {
+ return KErrNone;
+ }
+
+ if ( FindTxStreamForSSRC( aSSRC, &tranStream ) )
+ {
+ // One of our Tx streams uses an SSRC value that collides with the
+ // specified value.
+
+ RTCP_DEBUG_DETAIL( "RTCP: Jumping to new SSRC" );
+
+
+ // Send a BYE packet for this SSRC
+ buf.Format( _L8( "SSRC collision" ) );
+ buf.ZeroTerminate();
+ ( void ) SendRtcpByePacketL( tranStream->GetStreamID(), buf );
+
+ // Find a new unoccupied SSRC
+ ssrc = GetUniqueSSRC();
+
+ // Take the new SSRC into use
+ tranStream->SetLocalSSRC( ssrc );
+ if ( iDefaultSSRC == aSSRC )
+ {
+ iDefaultSSRC = ssrc;
+ }
+ // Also let the receive stream know the new SSRC
+ aSSRC = ssrc;
+
+ // Increment jump counter
+ iSSRCJumps++;
+ return 1; // a value larger than 0 indicates that the SSRC changed
+ }
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::Random()
+// Get a random 32-bit number
+// ---------------------------------------------------------------------------
+//
+TInt CRtpSession::Random()
+ {
+ if ( iSeed == 0 )
+ {
+ TTime tmp_time;
+ tmp_time.HomeTime();
+ iSeed = tmp_time.Int64();
+ }
+ return TRtpUtil::Random( iSeed );
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::Random64()
+// Get a random 64-bit number
+// ---------------------------------------------------------------------------
+//
+TReal CRtpSession::Random64()
+ {
+ if ( iSeed == 0 )
+ {
+ TTime tmp_time;
+ tmp_time.HomeTime();
+ iSeed = tmp_time.Int64();
+ }
+ return TRtpUtil::FloatRandom( iSeed );
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::SSRC()
+// Get Session default ssrc
+// ---------------------------------------------------------------------------
+//
+TRtpSSRC CRtpSession::SSRC() const
+ {
+ return iDefaultSSRC;
+ };
+
+// ---------------------------------------------------------------------------
+// CRtpSession::GetSessionId()
+// Get Session ID
+// ---------------------------------------------------------------------------
+//
+TRtpId CRtpSession::GetSessionId()
+ {
+ return iSessionId;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::SendRTCPByewithBanedSSRCL()
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::SendRTCPByewithBanedSSRCL()
+ {
+ TInt count = iStreamTxArray->Count();
+
+ for ( TInt index( 0 ); index < count; index++ )
+ {
+
+ TBuf8<15> buf;
+ CRtpTranStream* tempStream = ( CRtpTranStream* )
+ ( iStreamTxArray->At( index ).GetStreamAddress() );
+ //when sending RTCP report will use the localSSRC
+ //here we want to sendRTCPBye with specific SSRC which baned
+ //so set back the original value at the end
+ TRtpSSRC originSSRC= tempStream->GetLocalSSRC();
+ tempStream->SetLocalSSRC(iPktRcv->RtpPacketGetSSRC());
+ buf.Format( _L8( "SSRC baned" ) );
+ buf.ZeroTerminate();
+ ( void ) SendRtcpByePacketL( tempStream->GetStreamID(), buf );
+ tempStream->SetLocalSSRC(originSSRC);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::IsSrtp()
+//
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::IsSrtp()
+ {
+ return iIsSrtp;
+ }
+// ---------------------------------------------------------------------------
+// CRtpSession::SendSRTCPReport(TRtpSSRC aSSRC)
+// virtual function
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::SendSRTCPReportL(TRtpSSRC /*aSSRC*/)
+ {
+ //should not called base class
+ User::Leave(KErrNotSupported);
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::CheckifBanded(TRtpSSRC aSSRC)
+//
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::CheckifBanded()
+ {
+ TBool idFound = EFalse;
+ RTP_DEBUG_DETAIL( "CRtpSession::CheckifBanded Entry" );
+ RTP_DEBUG_DETAIL_DVALUE( "iPktRcv->RtpPacketGetSSRC() =", iPktRcv->RtpPacketGetSSRC() );
+ for ( TInt i=0; ( i<iRxSSRCArray.Count() && !idFound ); i++)
+ {
+ if( iRxSSRCArray[i] == iPktRcv->RtpPacketGetSSRC())
+ {
+ idFound = ETrue;
+ }
+ }
+ //baned the packet send RTCP bye
+ // Originally it sent here but now it has to be removed
+ // in case of RTCP Bye packet flooding causing by intrusion
+ // also in RFC, it is not required.
+ RTP_DEBUG_DETAIL( "CRtpSession::CheckifBanded Exit" );
+ return idFound;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::CheckRemoteAddr()
+//
+// ---------------------------------------------------------------------------
+//
+TBool CRtpSession::CheckRemoteAddr()
+ {
+ TBool isSetRemoteAddr=iCommNet->iReceiver[ERTPPort]->IsSetRemoteAdress();
+ return isSetRemoteAddr;
+ }
+
+// ---------------------------------------------------------------------------
+// CRtpSession::CreateRecvStream(TRtpSSRC aSSRC)
+//
+// ---------------------------------------------------------------------------
+//
+void CRtpSession::CreateNewRecvStreamL()
+ {
+ //create new rcvstream
+ //Related to RFC 3550 8.2
+
+ RTP_DEBUG_DETAIL( "CRtpSession::CreateNewRecvStream entry" );
+
+ if(iCommNet->iReceiver[ERTPPort]->IsSetRemoteAdress())
+ {
+ RTP_DEBUG_DETAIL( "Packet comes from set remote address" );
+
+ if (iNumOfRxStreams<= KRtpLimitNumberOfRecvStream)
+ {
+ TRtpId newStreamId= iAssignUniqueID.AssignUniqueID();
+ if (!iAssignUniqueID.AddStreamToSession(iSessionId, newStreamId))
+ {
+ // It is valid RTP packet, not checking if stream created
+ TRAPD( err, CreateReceiveStreamL( newStreamId, iPktRcv->RtpPacketGetPayloadType() ));
+ if ( err != KErrNone )
+ {
+ RTP_DEBUG_DETAIL( "error occured when tried to create Recv Stream" );
+ return;
+ }
+ RTP_DEBUG_DETAIL( "Assign new Rx stream" );
+ AssignRtpRxStreamL();
+ }
+ }
+ //Can not create the Recv once it runs to the limit
+ //This is in case of device running out of memory
+ RTP_DEBUG_DETAIL( "Can not create new recv stream!" );
+ RTP_DEBUG_DETAIL( "The number of Recv streams is over 100" );
+ }
+
+ else
+ {
+ //baned
+ RTP_DEBUG_DETAIL( "Band SSRC" );
+ iPktRcv->SetType( ERTP );
+ TRtpSSRC remoteSSRC( NULL );
+ remoteSSRC = iPktRcv->RtpPacketGetSSRC();
+ //Add to baned SSRC list
+ if (remoteSSRC )
+ {
+ if (!CheckifBanded())
+ {
+ //In the future it might also checked with SDES or CSRC
+ TRAPD( err, iRxSSRCArray.Append(remoteSSRC) ) ;
+ if ( err != KErrNone )
+ {
+ RTP_DEBUG_DETAIL( "Error ocured where to append banded ssrc" );
+ return;
+ }
+ RTP_DEBUG_DETAIL_DVALUE( "Band ssrc =", remoteSSRC );
+ SendRTCPByewithBanedSSRCL();
+ }
+ //abort packet
+ }
+ //abort packet
+ }
+ RTP_DEBUG_DETAIL( "CRtpSession::CreateNewRecvStream exit" );
+ }
+// End of File
+