diff --git a/src/voice_engine/channel.cc b/src/voice_engine/channel.cc index d46a8d5aa..b4889e29e 100644 --- a/src/voice_engine/channel.cc +++ b/src/voice_engine/channel.cc @@ -5404,6 +5404,66 @@ Channel::GetRTPStatistics( return 0; } +int Channel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) { + if (sender_info == NULL) { + _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetRemoteRTCPSenderInfo() invalid sender_info."); + return -1; + } + + // Get the sender info from the latest received RTCP Sender Report. + RTCPSenderInfo rtcp_sender_info; + if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_sender_info) != 0) { + _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError, + "GetRemoteRTCPSenderInfo() failed to read RTCP SR sender info."); + return -1; + } + + sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds; + sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction; + sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp; + sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount; + sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount; + return 0; +} + +int Channel::GetRemoteRTCPReportBlocks( + std::vector* report_blocks) { + if (report_blocks == NULL) { + _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetRemoteRTCPReportBlock()s invalid report_blocks."); + return -1; + } + + // Get the report blocks from the latest received RTCP Sender or Receiver + // Report. Each element in the vector contains the sender's SSRC and a + // report block according to RFC 3550. + std::vector rtcp_report_blocks; + if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) { + _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError, + "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block."); + return -1; + } + + if (rtcp_report_blocks.empty()) + return 0; + + std::vector::const_iterator it = rtcp_report_blocks.begin(); + for (; it != rtcp_report_blocks.end(); ++it) { + ReportBlock report_block; + report_block.sender_SSRC = it->remoteSSRC; + report_block.source_SSRC = it->sourceSSRC; + report_block.fraction_lost = it->fractionLost; + report_block.cumulative_num_packets_lost = it->cumulativeLost; + report_block.extended_highest_sequence_number = it->extendedHighSeqNum; + report_block.interarrival_jitter = it->jitter; + report_block.last_SR_timestamp = it->lastSR; + report_block.delay_since_last_SR = it->delaySinceLastSR; + report_blocks->push_back(report_block); + } + return 0; +} + int Channel::GetRTPStatistics(CallStatistics& stats) { diff --git a/src/voice_engine/channel.h b/src/voice_engine/channel.h index f9e4bf959..8889bc233 100644 --- a/src/voice_engine/channel.h +++ b/src/voice_engine/channel.h @@ -51,6 +51,8 @@ class VoERTPObserver; class VoERTCPObserver; struct CallStatistics; +struct ReportBlock; +struct SenderInfo; namespace voe { @@ -341,6 +343,8 @@ public: int GetRTPStatistics(unsigned int& averageJitterMs, unsigned int& maxJitterMs, unsigned int& discardedPackets); + int GetRemoteRTCPSenderInfo(SenderInfo* sender_info); + int GetRemoteRTCPReportBlocks(std::vector* report_blocks); int GetRTPStatistics(CallStatistics& stats); int SetFECStatus(bool enable, int redPayloadtype); int GetFECStatus(bool& enabled, int& redPayloadtype); diff --git a/src/voice_engine/include/voe_rtp_rtcp.h b/src/voice_engine/include/voe_rtp_rtcp.h index 0af5bac9e..fd0ca0b4d 100644 --- a/src/voice_engine/include/voe_rtp_rtcp.h +++ b/src/voice_engine/include/voe_rtp_rtcp.h @@ -40,6 +40,7 @@ #ifndef WEBRTC_VOICE_ENGINE_VOE_RTP_RTCP_H #define WEBRTC_VOICE_ENGINE_VOE_RTP_RTCP_H +#include #include "common_types.h" namespace webrtc { @@ -87,6 +88,27 @@ struct CallStatistics int packetsReceived; }; +// See section 6.4.1 in http://www.ietf.org/rfc/rfc3550.txt for details. +struct SenderInfo { + uint32_t NTP_timestamp_high; + uint32_t NTP_timestamp_low; + uint32_t RTP_timestamp; + uint32_t sender_packet_count; + uint32_t sender_octet_count; +}; + +// See section 6.4.2 in http://www.ietf.org/rfc/rfc3550.txt for details. +struct ReportBlock { + uint32_t sender_SSRC; // SSRC of sender + uint32_t source_SSRC; + uint8_t fraction_lost; + uint32_t cumulative_num_packets_lost; + uint32_t extended_highest_sequence_number; + uint32_t interarrival_jitter; + uint32_t last_SR_timestamp; + uint32_t delay_since_last_SR; +}; + // VoERTP_RTCP class WEBRTC_DLLEXPORT VoERTP_RTCP { @@ -173,6 +195,18 @@ public: // Gets RTCP statistics for a specific |channel|. virtual int GetRTCPStatistics(int channel, CallStatistics& stats) = 0; + // Gets the sender info part of the last received RTCP Sender Report (SR) + // on a specified |channel|. + virtual int GetRemoteRTCPSenderInfo( + int channel, SenderInfo* sender_info) = 0; + + // Gets the report block parts of the last received RTCP Sender Report (SR), + // or RTCP Receiver Report (RR) on a specified |channel|. Each vector + // element also contains the SSRC of the sender in addition to a report + // block. + virtual int GetRemoteRTCPReportBlocks( + int channel, std::vector* receive_blocks) = 0; + // Sends an RTCP APP packet on a specific |channel|. virtual int SendApplicationDefinedRTCPPacket( int channel, const unsigned char subType, unsigned int name, diff --git a/src/voice_engine/voe_rtp_rtcp_impl.cc b/src/voice_engine/voe_rtp_rtcp_impl.cc index 737d6ba5f..d21f722de 100644 --- a/src/voice_engine/voe_rtp_rtcp_impl.cc +++ b/src/voice_engine/voe_rtp_rtcp_impl.cc @@ -476,6 +476,42 @@ int VoERTP_RTCPImpl::GetRTCPStatistics(int channel, CallStatistics& stats) return channelPtr->GetRTPStatistics(stats); } +int VoERTP_RTCPImpl::GetRemoteRTCPSenderInfo(int channel, + SenderInfo* sender_info) { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetRemoteRTCPSenderInfo(channel=%d)", channel); + if (!_shared->statistics().Initialized()) { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channel_ptr = sc.ChannelPtr(); + if (channel_ptr == NULL) { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetRemoteRTCPSenderInfo() failed to locate channel"); + return -1; + } + return channel_ptr->GetRemoteRTCPSenderInfo(sender_info); +} + +int VoERTP_RTCPImpl::GetRemoteRTCPReportBlocks( + int channel, std::vector* report_blocks) { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetRemoteRTCPReportBlocks(channel=%d)", channel); + if (!_shared->statistics().Initialized()) { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channel_ptr = sc.ChannelPtr(); + if (channel_ptr == NULL) { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetRemoteRTCPReportBlocks() failed to locate channel"); + return -1; + } + return channel_ptr->GetRemoteRTCPReportBlocks(report_blocks); +} + int VoERTP_RTCPImpl::SetFECStatus(int channel, bool enable, int redPayloadtype) { WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), diff --git a/src/voice_engine/voe_rtp_rtcp_impl.h b/src/voice_engine/voe_rtp_rtcp_impl.h index aa060b44f..721499cf5 100644 --- a/src/voice_engine/voe_rtp_rtcp_impl.h +++ b/src/voice_engine/voe_rtp_rtcp_impl.h @@ -82,6 +82,11 @@ public: virtual int GetRTCPStatistics(int channel, CallStatistics& stats); + virtual int GetRemoteRTCPSenderInfo(int channel, SenderInfo* sender_info); + + virtual int GetRemoteRTCPReportBlocks( + int channel, std::vector* report_blocks); + // FEC virtual int SetFECStatus(int channel, bool enable,