rtp/rtpstack/src/rtprecvstream.cpp
changeset 0 307788aac0a8
child 29 5f12516512fa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rtp/rtpstack/src/rtprecvstream.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,669 @@
+/*
+* 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 "rtprecvstream.h"
+ 
+
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CRtpRecvStream::CRtpRecvStream( MSsrcCheckCallback* aCallback,
+                                const TRtpPayloadType aPayloadType,
+                                const TRtpId aSessionId,
+                                const TRtpId aReceiveStreamId,
+                                MRtpObserver** aRtpObserver,
+                                MRtcpObserver* aRtcpObserver,
+                                const TUint32* aProfileRTPTimeRates )
+    :
+    CRtpStream( aReceiveStreamId,
+             aSessionId,
+             aProfileRTPTimeRates,
+             aRtcpObserver,
+             aPayloadType ),
+    iNumWrapAround( 0 ),
+    iRtpObserver( aRtpObserver ),
+    iCallback( aCallback )
+    {
+    // set syncInfo values to zero 
+    RtpStreamJitterInit();
+    RtpStreamSyncInfoInit();
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CRtpRecvStream::ConstructL()
+    {
+    iRemoteSDES = CRtpSDES::NewL();
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CRtpRecvStream* CRtpRecvStream::NewL( const TRtpPayloadType aPayloadType,
+                                      const TRtpId aSessionId,
+                                      const TRtpId aReceiveStreamId,
+                                      MRtpObserver** aRtpObserver,
+                                      MRtcpObserver* aRtcpObserver,
+                                      const TUint32* aProfileRTPTimeRates,
+                                      MSsrcCheckCallback* aCallback )
+    {
+    CRtpRecvStream* self =
+        new ( ELeave ) CRtpRecvStream( aCallback,
+                                       aPayloadType,
+                                       aSessionId,
+                                       aReceiveStreamId,
+                                       aRtpObserver,
+                                       aRtcpObserver,
+                                       aProfileRTPTimeRates );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop(); // self 
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CRtpRecvStream::~CRtpRecvStream()
+    {
+	delete iRemoteSDES;
+    }
+
+
+// ---------------------------------------------------------------------------
+// RegisterRtpObserver
+// ---------------------------------------------------------------------------
+//
+void CRtpRecvStream::RegisterRtpObserver(MRtpObserver* aRtpObserver)
+    {
+    *iRtpObserver = aRtpObserver; 
+    }
+
+
+// ---------------------------------------------------------------------------
+// UnRegisterRtpObserver
+// ---------------------------------------------------------------------------
+//
+void CRtpRecvStream::UnRegisterRtpObserver()
+    {
+    *iRtpObserver = NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpRecvStream::ResetStreamStat()
+// ---------------------------------------------------------------------------
+//
+TInt CRtpRecvStream::ResetStreamStat()
+    {
+    TRtcpStats rtcpStat;
+
+    RtcpStats( rtcpStat );
+    
+    rtcpStat.iRtcpReceiverStats.iFractionLost = 0;
+    rtcpStat.iRtcpReceiverStats.iCumNumPacketsLost = 0;
+    rtcpStat.iRtcpReceiverStats.iSeqNumReceived = 0; 
+    rtcpStat.iRtcpReceiverStats.iArrivalJitter = 0;
+    rtcpStat.iRtcpReceiverStats.iRoundTripDelay = 0;
+    rtcpStat.iRtcpReceiverStats.iChannelBufferSize = 0;
+   
+    // The sender stats are updated when receiving SR packets, so reset 
+    rtcpStat.iRtcpSenderStats.iSSRC = 0;
+    rtcpStat.iRtcpSenderStats.iCumNumOctetsSent = 0;
+    rtcpStat.iRtcpSenderStats.iNumPacketsSent = 0;
+    rtcpStat.iRtcpSenderStats.iNTPTimeStampSec = 0;
+    rtcpStat.iRtcpSenderStats.iNTPTimeStampFrac = 0;
+    rtcpStat.iRtcpSenderStats.iTimeStamp = 0;
+
+    iRtcpStats = rtcpStat;
+    
+    iNumReceivedPackets = 0;
+    iNumWrapAround = 0;   
+    
+    // set syncInfo values to zero 
+    RtpStreamJitterInit();
+    RtpStreamSyncInfoInit();
+    
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpTranStream::GetStreamStat()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpRecvStream::GetStreamStat( TRtpPeerStat& aStat )
+    {
+    TRtcpStats rtcpStat;
+
+    RtcpStats( rtcpStat );
+
+    aStat.iCumNumOctetsSent = rtcpStat.iRtcpSenderStats.iCumNumOctetsSent;
+    aStat.iNumPacketsSent = rtcpStat.iRtcpSenderStats.iNumPacketsSent;
+
+    aStat.iTxBandwidth = rtcpStat.iRtcpReceiverStats.iTxBandwidth;
+    aStat.iArrivalJitter = rtcpStat.iRtcpReceiverStats.iArrivalJitter;
+    aStat.iCumNumPacketsLost = rtcpStat.iRtcpReceiverStats.iCumNumPacketsLost;
+    aStat.iFractionLost = rtcpStat.iRtcpReceiverStats.iFractionLost;
+    aStat.iRoundTripDelay = rtcpStat.iRtcpReceiverStats.iRoundTripDelay;
+    aStat.iRxBandwidth = rtcpStat.iRtcpReceiverStats.iBandwidth;
+    aStat.iChannelBufferSize = rtcpStat.iRtcpReceiverStats.iChannelBufferSize;
+    aStat.iNTPTimeStampSec = 0;
+    aStat.iNTPTimeStampFrac = 0;
+    aStat.iTimeStamp = 0;
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpRecvStream::RtpStreamProcessRtpPacketL()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpRecvStream::RtpStreamProcessRtpPacketL( CRtpPacket* aPktRcv, TBool aAssignStream )
+    {
+    RTP_DEBUG_DETAIL( "CRtpRecvStream::RtpStreamProcessRtpPacketL Entry" );
+    aPktRcv->RtpPacketResetPtr();
+
+    // Check if this packet belongs to this stream by looking at the source SSRC
+    if ( !aAssignStream )
+        {
+        TRtpSSRC aRemoteSSRC( NULL );
+        aPktRcv->SetType( ERTP );
+        aRemoteSSRC = aPktRcv->RtpPacketGetSSRC();
+        if ( iRemoteSSRC != aRemoteSSRC )
+            {
+            RTP_DEBUG_DETAIL( "RtpRecvStream: Wrong SSRC" );
+            return KErrNotFound;
+            }
+        }
+    else
+        {
+        //assigned RTP packet SSRC if this stream's remote SSRC is NULL
+        // if it is not null then return KErrNotFound
+        if ( iRemoteSSRC )
+            {
+            RTP_DEBUG_DETAIL( "RtpRecvStream: Did not expect own SSRC" );
+            return KErrNotFound;
+            }
+        }
+
+    TRtpPacketStreamParam streamParam;
+    TRtpPacketIOParam extractParam;
+
+    // process RTP packet
+    aPktRcv->SetType( ERTP );
+
+    extractParam.TRTP.extension.data = NULL;
+
+    if ( aPktRcv->RtpPacketProcessL( &streamParam, &extractParam ) < 0 )
+        {
+        RTP_DEBUG_DETAIL( "Invalid Rtp packet is received" );
+        return KErrCorrupt;
+        }
+	if (!iCallback->CheckRemoteAddr())
+		{
+		RTP_DEBUG_DETAIL( "Packet comes from wrong remote address" );
+		return KErrNotFound;
+		}
+    // update and check stream parameters
+    if ( RtpStreamUpdateParamL( aPktRcv->Type(), &streamParam ) < 0 )
+        {
+        
+        RTP_DEBUG_PACKET("RtpRecvStream: Could not update params" );
+        
+        return KErrNotFound;
+        }
+
+    iHdr.iPadding = extractParam.TRTP.padding;
+    iHdr.iExtension = extractParam.TRTP.fHeaderExtension;
+    iHdr.iCsrcCount = extractParam.TRTP.numCSRC;
+
+    iHdr.iMarker = extractParam.TRTP.marker;
+    iHdr.iTimestamp = streamParam.TRTP.timeStamp;
+    iHdr.iPayloadType = streamParam.TRTP.payload; // iPayload; pass payload type to app,even if it changed
+
+    if ( iHdr.iExtension )
+        {
+		iHdr.iHeaderExtension = &iHeaderExtension;
+        iHdr.iHeaderExtension->iType = extractParam.TRTP.extension.type;
+        iHdr.iHeaderExtension->iLength = extractParam.TRTP.extension.length;
+        iHdr.iHeaderExtension->iData = extractParam.TRTP.extension.data;
+        }
+
+    iFlagReceivedRTPPackets = ETrue;
+
+    // calculate jitter, maybe it eats a big portion of CPU time?
+    RtpStreamUpdateJitter( iHdr.iTimestamp );
+
+    iHdr.iSeqNum = streamParam.TRTP.seqNum;
+    
+    RTP_DEBUG_DETAIL_DVALUE( "The received RTP packet size = ", extractParam.TRTP.payloadDataLen );
+    RTP_DEBUG_DETAIL_DVALUE( "The received RTP packet Seq Num = ", streamParam.TRTP.seqNum );
+    
+    TPtrC8 payloadData( extractParam.TRTP.payloadData, extractParam.TRTP.payloadDataLen );
+
+    if ( *iRtpObserver )
+        {
+        RTP_DEBUG_PACKET("RTP packet received and pass to upper application" );
+        
+        (*iRtpObserver)->RtpPacketReceived( iStreamId, iHdr, payloadData );
+        }
+    else
+        {
+        RTP_DEBUG_PACKET( "RtpRecvStream: No observer registered" );
+        }
+   	if(aPktRcv->iExdataAlloc )
+      	{
+       	User::Free( extractParam.TRTP.extension.data );
+       	}
+   	if (aPktRcv->iCsrcAlloc)
+   		{
+   		User::Free( extractParam.TRTP.CSRCarray);
+   		}    
+   	RTP_DEBUG_DETAIL( "CRtpRecvStream::RtpStreamProcessRtpPacketL Exit" );
+    	
+    return KErrNone;
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// CRtpRecvStream::RtpStreamSyncInfoInit()
+// For receiving stream, iSyncInfo is initialized to zero
+// and will be updated by SR received for the future RR creating
+// iSyncInfo.timeStamp & iSyncInfo.lastUpdateLocalTime are
+// not useful actually.
+// ---------------------------------------------------------------------------
+// 
+void CRtpRecvStream::RtpStreamSyncInfoInit()
+    {
+    iSyncInfo.iNTPTimeStampFrac = 0;
+    iSyncInfo.iNTPTimeStampSec = 0;
+    iSyncInfo.iTimeStamp = 0;
+    iSyncInfo.iLastUpdateLocalTime = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// CRtpRecvStream::RtpStreamJitterInit()
+// 
+// ---------------------------------------------------------------------------
+//
+void CRtpRecvStream::RtpStreamJitterInit()
+    {
+    iSyncJitter.iLastPacketS = 0;
+    iSyncJitter.iLastPacketR = 0;
+    iSyncJitter.iJitterTime = 0;
+
+    iSyncJitter.iWaitTime = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// CRtpRecvStream::RtpStreamUpdateJitter()
+// 
+// ---------------------------------------------------------------------------
+//
+void CRtpRecvStream::RtpStreamUpdateJitter( TRtpTimeStamp aCurrentTimeStamp )
+    {
+    TUint32 gtTime = TRtpUtil::GtGetTime();
+    TRtpTimeStamp packetRTP( aCurrentTimeStamp );
+    TInt jitterTime = 0;
+
+    if ( packetRTP == iSyncJitter.iLastPacketS )
+        {
+        return;
+        }
+
+    jitterTime = ( ( ( gtTime - iSyncJitter.iLastPacketR ) * iSyncJitter.iTimeStampResolution ) 
+                 / KTenthOfmsPerSecond ) - ( packetRTP - iSyncJitter.iLastPacketS );
+
+    iSyncJitter.iJitterTime = iSyncJitter.iJitterTime + 
+        ( ( ( TReal64 ) Abs( jitterTime ) - iSyncJitter.iJitterTime ) / 16.0 );
+
+    // if jitter > 100 seconds, reset it. 
+    if ( iSyncJitter.iJitterTime > 1000000 ) // 100 * KTenthOfmsPerSecond 
+        {
+        iSyncJitter.iJitterTime = 0;
+        }
+    iSyncJitter.iLastPacketR = gtTime;
+    iSyncJitter.iLastPacketS = packetRTP;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpRecvStream::RtpStreamUpdateParamL()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpRecvStream::RtpStreamUpdateParamL( TRtpPacketType aPType, 
+                                           TRtpPacketStreamParam* aStreamParam )
+    {
+    TUint32 timerate;
+    TInt error( KErrNone );
+
+    if ( aPType == ERTP )
+        {
+        // Check if there is an SSRC collision
+        if ( iCallback )
+            {
+            error = iCallback->CheckRemoteSsrcL( aStreamParam->TRTP.SSRC );
+            }
+        if ( error < KErrNone )
+            {
+            return KErrCorrupt;
+            }
+        if ( error > KErrNone )
+            {
+            // There was an SSRC collision, and TRTP.SSRC now contains the
+            // updated SSRC value.
+            iRemoteSSRC = aStreamParam->TRTP.SSRC;
+            }
+
+        if ( iFlagFirstPkg )
+            {
+            iRemoteSSRC = aStreamParam->TRTP.SSRC;
+            iPayload = aStreamParam->TRTP.payload;
+            iBaseSeqNum = aStreamParam->TRTP.seqNum;
+
+            timerate = *( iProfileRTPTimeRates + iPayload );
+            if ( timerate != 0 )
+                {
+                iSyncJitter.iTimeStampResolution = KMicrosecondPerSecond / timerate;
+                }
+            else
+                {
+                iSyncJitter.iTimeStampResolution = 0;
+                }
+            }
+        else if ( iRemoteSSRC != aStreamParam->TRTP.SSRC )
+            {
+            // SSRC and seqNum change. start monitoring if this change is intentional, 
+            // if several packets received sequentionally, and then re-initialize the stream 
+            
+            RTP_DEBUG_DETAIL( "SSRC changed" );
+            
+            
+            return KErrNotFound;
+            }
+        else
+            {
+            if ( iPayload != aStreamParam->TRTP.payload )
+                {
+                // payload type changed, inform application somehow 
+                RTP_DEBUG_DETAIL( "payload type changed" );
+                
+                }
+            }
+
+        if ( aStreamParam->TRTP.seqNum == TRtpUtil::Min16( aStreamParam->TRTP.seqNum, iSeqNum ) && !iFlagFirstPkg )
+            {
+            // if there is no buffering, out of order and duplicate packets
+            // have to be discarded
+            return KErrNone; // give this packet to the application as there is no buffer in RTP
+            }
+        else
+            {
+            //update the highest received SN and TS
+            if ( TRtpUtil::Wrap16( iSeqNum, aStreamParam->TRTP.seqNum ) && !iFlagFirstPkg )
+                {
+                iSeqNumCycles++;
+                }
+            iSeqNum = aStreamParam->TRTP.seqNum;
+            iTimeStamp = aStreamParam->TRTP.timeStamp;
+            iFlagFirstPkg = 0;
+            iNumReceivedPackets++;
+            }
+        }
+    else
+        {
+        return KErrNotFound;
+        }
+
+    return KErrNone;
+    } 
+
+
+// ---------------------------------------------------------------------------
+// CRtpRecvStream::RtpStreamCreateRtcpReportSection()
+// For receiving stream, it only creates RR packet
+// ---------------------------------------------------------------------------
+// 
+void CRtpRecvStream::RtpStreamCreateRtcpReportSection( CRtpPacket* aPkt )
+    {
+    TRtpPacketStreamParam streamParam;
+    TRtpPacketIOParam inParam;
+
+    TUint32 numPacketsExpected;
+    TUint32 numPacketsIntervalLost;
+    TUint32 numPacketsIntervalExpected;
+
+    streamParam.TRTCP_RR.SSRC = iRemoteSSRC;
+
+    // iSeqNum is 16 bit, but streamParam.TRTCP_RR.seqNumReceived is 32 bits. 
+    // Check RFC1889 for RTCP part 
+
+    streamParam.TRTCP_RR.seqNumReceived = iSeqNum + ( iSeqNumCycles << 16 );
+    numPacketsExpected = streamParam.TRTCP_RR.seqNumReceived - iBaseSeqNum + 1;
+
+    if ( numPacketsExpected < iNumReceivedPackets )
+        {
+        streamParam.TRTCP_RR.cumNumPacketsLost = 0;
+        }
+    else
+        {
+        if ( ( numPacketsExpected + ( 1 << 16 ) * iNumWrapAround ) < iLastRR_numExpectedPackets )
+            {
+            iNumWrapAround++;
+            numPacketsExpected += ( 1 << 16 ) * iNumWrapAround;
+            }
+        else
+            {
+            numPacketsExpected += ( 1 << 16 ) * iNumWrapAround;
+            }
+        streamParam.TRTCP_RR.cumNumPacketsLost = numPacketsExpected - iNumReceivedPackets;
+        }
+
+    numPacketsIntervalExpected = numPacketsExpected - iLastRR_numExpectedPackets;
+    numPacketsIntervalLost = numPacketsIntervalExpected - ( iNumReceivedPackets - iLastRR_numReceivedPackets );
+
+    //
+    // From RFC 1889
+    // fraction lost: 8 bits
+    // The fraction of RTP data packets from source SSRC_n lost since the previous SR or RR packet was sent, 
+    // expressed as a fixed point number with the binary point at the left edge of the field. (That is 
+    // equivalent to taking the integer part after multiplying the loss fraction by 256.) This fraction is
+    // defined to be the number of packets lost divided by the number of packets expected.
+    //
+
+    if ( ( numPacketsIntervalExpected == 0 ) || ( numPacketsIntervalLost == 0 ) )
+        {
+        streamParam.TRTCP_RR.fractionLost = 0;
+        }
+    else
+        {
+        streamParam.TRTCP_RR.fractionLost = static_cast<TUint8>(
+            ( numPacketsIntervalLost << 8 ) / numPacketsIntervalExpected );
+        }
+
+    iLastRR_numReceivedPackets = iNumReceivedPackets;
+    iLastRR_numExpectedPackets = numPacketsExpected;
+
+    streamParam.TRTCP_RR.arrivalJitter = static_cast<TUint32>( iSyncJitter.iJitterTime );
+
+    // add receiver statistics to sender of SR packet 
+    iRtcpStats.iRtcpReceiverStats.iRoundTripDelay = 0;
+    iRtcpStats.iRtcpReceiverStats.iFractionLost = streamParam.TRTCP_RR.fractionLost;
+    iRtcpStats.iRtcpReceiverStats.iCumNumPacketsLost = streamParam.TRTCP_RR.cumNumPacketsLost;
+    iRtcpStats.iRtcpReceiverStats.iSeqNumReceived = streamParam.TRTCP_RR.seqNumReceived;
+    iRtcpStats.iRtcpReceiverStats.iBandwidth = 0;
+    iRtcpStats.iRtcpReceiverStats.iChannelBufferSize = 0;
+
+    if ( iSyncJitter.iTimeStampResolution > 0 )
+        {
+        iRtcpStats.iRtcpReceiverStats.iArrivalJitter = ( streamParam.TRTCP_RR.arrivalJitter * KTenthOfmsPerSecond ) /
+                                                      iSyncJitter.iTimeStampResolution;
+        }
+    else
+        {
+        iRtcpStats.iRtcpReceiverStats.iArrivalJitter = 0;
+        }
+
+    iRtcpStats.iRtcpReceiverStats.iSSRC = streamParam.TRTCP_RR.SSRC; // SSRC sender (coming source)
+    
+    
+    RTP_DEBUG_STAT( "----- RX: Create RTCP Report Statistics -----" );
+    RTP_DEBUG_STAT_DVALUE( "RX: roundTripDelay = ", iRtcpStats.iRtcpReceiverStats.iRoundTripDelay );
+    RTP_DEBUG_STAT_DVALUE( "RX: fractionLost = ", (TInt)iRtcpStats.iRtcpReceiverStats.iFractionLost );
+    RTP_DEBUG_STAT_DVALUE( "RX: cumNumPacketsLost = ", iRtcpStats.iRtcpReceiverStats.iCumNumPacketsLost );
+    RTP_DEBUG_STAT_DVALUE( "RX: seqNumReceived = ", iRtcpStats.iRtcpReceiverStats.iSeqNumReceived );
+    RTP_DEBUG_STAT_DVALUE( "RX: bandwidth = ", iRtcpStats.iRtcpReceiverStats.iBandwidth );
+    RTP_DEBUG_STAT_DVALUE( "RX: channelBufferSize = ", iRtcpStats.iRtcpReceiverStats.iChannelBufferSize );
+    RTP_DEBUG_STAT_DVALUE( "RX: arrivalJitter = ", iRtcpStats.iRtcpReceiverStats.iArrivalJitter );
+    RTP_DEBUG_STAT_DVALUE( "RX: SSRC (Tx) = ", iRtcpStats.iRtcpReceiverStats.iSSRC );
+
+    TUint32 gtTime = TRtpUtil::GtGetTime();
+    // lastSRTimeStamp: use the middle 32 bits of the 64-bit NTP timestamp
+    // This results in value where the 16-MSB is the amount of seconds, and
+    // the 16-LSB is the fraction of seconds (in tenths of milliseconds).
+    // See RFC3550 page 34 for details.
+    inParam.TRTCP_RR.lastSRTimeStamp = ( iSyncInfo.iNTPTimeStampSec << 16 ) + ( iSyncInfo.iNTPTimeStampFrac >> 16 );
+    inParam.TRTCP_RR.delaySinceLSR = 
+        ( static_cast<TUint32>( ( gtTime - iSyncInfo.iLastUpdateLocalTime ) / KTenthOfmsPerSecond ) << 16 );
+    inParam.TRTCP_RR.delaySinceLSR += 
+    ( ( ( ( TUint32 ) ( ( gtTime - iSyncInfo.iLastUpdateLocalTime ) % KTenthOfmsPerSecond ) ) << 16 ) / KTenthOfmsPerSecond );
+
+    // For receiving stream, it only generates RR packet. 
+    aPkt->SetType( ERTCP_RR );
+    aPkt->RtpPacketBuild( &streamParam, &inParam );
+    }
+
+
+// ---------------------------------------------------------------------------
+// TRtpRtcpEnum CRtpRecvStream::RtpStreamProcessRtcpReportSectionL()
+// For receiving stream, it only process SR packet
+// ---------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpRecvStream::RtpStreamProcessRtcpReportSectionL( CRtpPacket* aPkt )
+    {
+    TRtpPacketStreamParam streamParam;
+    TRtpPacketIOParam extractParam;
+    TRtpRtcpEnum parseResult = ERTCP_NO_ERROR;
+    TUint32 gtTime = TRtpUtil::GtGetTime();
+
+    parseResult = aPkt->RtpPacketProcessL( &streamParam, &extractParam );
+    if ( parseResult < 0 )
+        {
+        return ERTCP_PACKET_ERROR; 
+        }
+
+    // For receiving stream, it only processes SR packet.
+    if ( aPkt->Type() == ERTCP_SR )
+        {
+        // give this information to receiver on RTCP callback
+        iSyncInfo.iLastUpdateLocalTime = gtTime;
+        iSyncInfo.iNTPTimeStampSec = extractParam.TRTCP_SR.NTPTimeStampSec;
+        iSyncInfo.iNTPTimeStampFrac = extractParam.TRTCP_SR.NTPTimeStampFrac;
+        iSyncInfo.iTimeStamp = extractParam.TRTCP_SR.timeStamp;
+        
+        // do something with numPacketsSent and cumNumOctetsSent 
+        iRtcpStats.iRtcpSenderStats.iSSRC = streamParam.TRTCP_SR.SSRC;
+        iRtcpStats.iRtcpSenderStats.iCumNumOctetsSent = streamParam.TRTCP_SR.cumNumOctetsSent;
+        iRtcpStats.iRtcpSenderStats.iNumPacketsSent = streamParam.TRTCP_SR.numPacketsSent;
+        iRtcpStats.iRtcpSenderStats.iNTPTimeStampSec = iSyncInfo.iNTPTimeStampSec;
+        iRtcpStats.iRtcpSenderStats.iNTPTimeStampFrac = iSyncInfo.iNTPTimeStampFrac;
+        iRtcpStats.iRtcpSenderStats.iTimeStamp = iSyncInfo.iTimeStamp;
+        
+        
+        RTP_DEBUG_STAT( "----- RX: Process RTCP Report Statistics -----" );
+        RTP_DEBUG_STAT_DVALUE( "RX: cumNumOctetsSent = ", iRtcpStats.iRtcpSenderStats.iCumNumOctetsSent );
+        RTP_DEBUG_STAT_DVALUE( "RX: numPacketsSent = ", iRtcpStats.iRtcpSenderStats.iNumPacketsSent );
+        RTP_DEBUG_STAT_DVALUE( "RX: SSRC (Tx) = ", iRtcpStats.iRtcpSenderStats.iSSRC );
+        RTP_DEBUG_STAT_DVALUE( "RX: NTPTimeStampSec = ", iRtcpStats.iRtcpSenderStats.iNTPTimeStampSec );
+        RTP_DEBUG_STAT_DVALUE( "RX: NTPTimeStampFrac = ", iRtcpStats.iRtcpSenderStats.iNTPTimeStampFrac );
+        RTP_DEBUG_STAT_DVALUE( "RX: timeStamp = ", iRtcpStats.iRtcpSenderStats.iTimeStamp );
+   
+        
+        TTimeStamps timeStamps;
+        timeStamps.iNTPTimeStampFrac = iRtcpStats.iRtcpSenderStats.iNTPTimeStampFrac;
+        timeStamps.iNTPTimeStampSec = iRtcpStats.iRtcpSenderStats.iNTPTimeStampSec;
+        timeStamps.iTimeStamp = iRtcpStats.iRtcpSenderStats.iTimeStamp;
+
+        if ( iRtcpObserver )
+            {
+            iRtcpObserver->SrReceived( iStreamId, iRtcpStats.iRtcpSenderStats.iSSRC, timeStamps );
+            }
+        }
+    else
+        {
+        // the received report can not be associated with the stream 
+        return ERTCP_PACKET_ERROR;
+        }
+
+    return parseResult;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpRecvStream::GetRemoteStreamInfo()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpRecvStream::GetRemoteStreamInfo( TRtpSdesParams& aSdes )
+    {
+    iRemoteSDES->GetSDES( aSdes );
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpRecvStream::SetReceivedRTPPackets()
+// 
+// ---------------------------------------------------------------------------
+//
+void CRtpRecvStream::SetReceivedRTPPackets( TBool aFlag )
+    {
+    iFlagReceivedRTPPackets = aFlag;
+    };
+
+
+// ---------------------------------------------------------------------------
+// TInt CRtpRecvStream::ReceivedRTPPackets()
+// 
+// ---------------------------------------------------------------------------
+//
+TBool CRtpRecvStream::ReceivedRTPPackets() const
+    {
+    return iFlagReceivedRTPPackets;
+    };
+
+// ---------------------------------------------------------------------------
+// TInt CRtpRecvStream::GetRemoteSSRC()
+// 
+// ---------------------------------------------------------------------------
+//
+TRtpSSRC CRtpRecvStream::GetRemoteSSRC()
+    {
+    return iRemoteSSRC;
+    }
+
+