diff -r 000000000000 -r 307788aac0a8 rtp/rtpstack/src/rtprecvstream.cpp --- /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( + ( numPacketsIntervalLost << 8 ) / numPacketsIntervalExpected ); + } + + iLastRR_numReceivedPackets = iNumReceivedPackets; + iLastRR_numExpectedPackets = numPacketsExpected; + + streamParam.TRTCP_RR.arrivalJitter = static_cast( 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( ( 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; + } + +