rtp/rtpstack/src/rtpsession.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:32:57 +0300
branchRCL_3
changeset 43 b5e99d8877c7
parent 16 43c4dec3cb1f
child 30 d7640adb246b
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* 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::ReadyToSendRtpPacket()
// 
// ---------------------------------------------------------------------------
//
void CRtpSession::ReadyToSendRtpPacket(TRtpId aTranStreamId)
    {
    if ( iRtpPacketObserver )
        {
        RTP_DEBUG_DETAIL("Giving ReadyToSendRtpPacket() Call Back " );
        TPtr8 pktPtr(iPktSnd->Data(), iPktSnd->Size(), iPktSnd->Size());
        iRtpPacketObserver->ReadyToSendRtpPacket( aTranStreamId , pktPtr );
        }   
    }


// ---------------------------------------------------------------------------
// TInt CRtpSession::SendRtpPacket()
// 
// ---------------------------------------------------------------------------
//
TInt CRtpSession::SendRtpPacket( TRtpId aTranStreamId,
                                 const TRtpSendHeader& aHeaderInfo, 
                                 const TDesC8& aPayloadData,
                                 const TArray<TRtpCSRC> *aCsrcList )
    {
    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, aCsrcList );
        
        ReadyToSendRtpPacket(aTranStreamId);
        
        ret = iCommNet->Send( ERTPPort, iPktSnd->Des() );
        }
    return ret;
    }


// ---------------------------------------------------------------------------
// TInt CRtpSession::SendRtpPacket()
// 
// ---------------------------------------------------------------------------
//
TInt CRtpSession::SendRtpPacket( TRtpId aTranStreamId,
                                 const TRtpSendHeader& aHeaderInfo,
                                 const TDesC8& aPayloadData,
                                 TRequestStatus& aStatus,
                                 const TArray<TRtpCSRC> *aCsrcList )
    {
    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, aCsrcList );
									
        ReadyToSendRtpPacket(aTranStreamId);
			
        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,
                                 const TArray<TRtpCSRC> *aCsrcList )
    {
    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, aCsrcList );
        
        ReadyToSendRtpPacket(aTranStreamId);								
									
        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::RegisterRtpPostProcessingObserver()
// 
// ---------------------------------------------------------------------------
//
TInt CRtpSession::RegisterRtpPostProcessingObserver( MRtpPostProcessingObserver& aRTPPacketObserver )
    {
    iRtpPacketObserver = &aRTPPacketObserver;  
    
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// CRtpSession::UnregisterRtpPostProcessingObserver()
// 
// ---------------------------------------------------------------------------
//
void CRtpSession::UnregisterRtpPostProcessingObserver()
    {
    iRtpPacketObserver = NULL;
    }

// ---------------------------------------------------------------------------
// 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:
        case KErrConnectionTerminated:
            
            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