rtp/rtpstack/src/rtpsession.cpp
changeset 0 307788aac0a8
child 16 43c4dec3cb1f
--- /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
+