diff --git a/webrtc/modules/rtp_rtcp/include/receive_statistics.h b/webrtc/modules/rtp_rtcp/include/receive_statistics.h index 90a848ad63..edbaf8f6f8 100644 --- a/webrtc/modules/rtp_rtcp/include/receive_statistics.h +++ b/webrtc/modules/rtp_rtcp/include/receive_statistics.h @@ -12,15 +12,26 @@ #define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RECEIVE_STATISTICS_H_ #include +#include #include "webrtc/modules/include/module.h" #include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" #include "webrtc/typedefs.h" namespace webrtc { class Clock; +class ReceiveStatisticsProvider { + public: + virtual ~ReceiveStatisticsProvider() = default; + // Collects receive statistic in a form of rtcp report blocks. + // Returns at most |max_blocks| report blocks. + virtual std::vector RtcpReportBlocks( + size_t max_blocks) = 0; +}; + class StreamStatistician { public: virtual ~StreamStatistician(); @@ -46,9 +57,9 @@ class StreamStatistician { typedef std::map StatisticianMap; -class ReceiveStatistics { +class ReceiveStatistics : public ReceiveStatisticsProvider { public: - virtual ~ReceiveStatistics() {} + ~ReceiveStatistics() override = default; static ReceiveStatistics* Create(Clock* clock); @@ -78,6 +89,10 @@ class ReceiveStatistics { // Called on new RTP stats creation. virtual void RegisterRtpStatisticsCallback( StreamDataCountersCallback* callback) = 0; + + // TODO(danilchap): Make pure virtual when all implmentations of the + // ReceiveStatistics interface will implement it. + std::vector RtcpReportBlocks(size_t max_blocks) override; }; class NullReceiveStatistics : public ReceiveStatistics { diff --git a/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h b/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h index c2a0256432..427229472c 100644 --- a/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h @@ -29,7 +29,7 @@ namespace webrtc { // Forward declarations. class OverheadObserver; class RateLimiter; -class ReceiveStatistics; +class ReceiveStatisticsProvider; class RemoteBitrateEstimator; class RtcEventLog; class RtpReceiver; @@ -55,7 +55,7 @@ class RtpRtcp : public Module { // The clock to use to read time. If nullptr then system clock will be used. Clock* clock = nullptr; - ReceiveStatistics* receive_statistics = nullptr; + ReceiveStatisticsProvider* receive_statistics = nullptr; // Transport object that will be called when packets are ready to be sent // out on the network. diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc index fe5f02b45b..21f5b37c2f 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -13,10 +13,12 @@ #include #include +#include #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" #include "webrtc/modules/rtp_rtcp/source/time_util.h" +#include "webrtc/rtc_base/logging.h" #include "webrtc/system_wrappers/include/clock.h" namespace webrtc { @@ -492,6 +494,37 @@ void ReceiveStatisticsImpl::DataCountersUpdated(const StreamDataCounters& stats, } } +std::vector ReceiveStatistics::RtcpReportBlocks( + size_t max_blocks) { + StatisticianMap statisticians = GetActiveStatisticians(); + std::vector result; + result.reserve(std::min(max_blocks, statisticians.size())); + for (auto& statistician : statisticians) { + // TODO(danilchap): Select statistician subset across multiple calls using + // round-robin, as described in rfc3550 section 6.4 when single + // rtcp_module/receive_statistics will be used for more rtp streams. + if (result.size() == max_blocks) + break; + + // Do we have receive statistics to send? + RtcpStatistics stats; + if (!statistician.second->GetStatistics(&stats, true)) + continue; + result.emplace_back(); + rtcp::ReportBlock& block = result.back(); + block.SetMediaSsrc(statistician.first); + block.SetFractionLost(stats.fraction_lost); + if (!block.SetCumulativeLost(stats.cumulative_lost)) { + LOG(LS_WARNING) << "Cumulative lost is oversized."; + result.pop_back(); + continue; + } + block.SetExtHighestSeqNum(stats.extended_max_sequence_number); + block.SetJitter(stats.jitter); + } + return result; +} + void NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header, size_t packet_length, bool retransmitted) {} diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc index 84231e5a57..be78a4320f 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc @@ -139,7 +139,7 @@ class RTCPSender::RtcpContext { RTCPSender::RTCPSender( bool audio, Clock* clock, - ReceiveStatistics* receive_statistics, + ReceiveStatisticsProvider* receive_statistics, RtcpPacketTypeCounterObserver* packet_type_counter_observer, RtcEventLog* event_log, Transport* outgoing_transport) @@ -836,32 +836,10 @@ std::vector RTCPSender::CreateReportBlocks( if (!receive_statistics_) return result; - StatisticianMap statisticians = receive_statistics_->GetActiveStatisticians(); - result.reserve(statisticians.size()); - for (auto& statistician : statisticians) { - // Do we have receive statistics to send? - RtcpStatistics stats; - if (!statistician.second->GetStatistics(&stats, true)) - continue; - // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per - // compound rtcp packet when single rtcp module is used for multiple media - // streams. - if (result.size() >= RTCP_MAX_REPORT_BLOCKS) { - LOG(LS_WARNING) << "Too many report blocks."; - continue; - } - result.emplace_back(); - rtcp::ReportBlock& block = result.back(); - block.SetMediaSsrc(statistician.first); - block.SetFractionLost(stats.fraction_lost); - if (!block.SetCumulativeLost(stats.cumulative_lost)) { - LOG(LS_WARNING) << "Cumulative lost is oversized."; - result.pop_back(); - continue; - } - block.SetExtHighestSeqNum(stats.extended_max_sequence_number); - block.SetJitter(stats.jitter); - } + // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per + // compound rtcp packet when single rtcp module is used for multiple media + // streams. + result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS); if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) || (feedback_state.last_rr_ntp_frac != 0))) { diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h index abf2da1574..7b3ad496dd 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h @@ -77,7 +77,7 @@ class RTCPSender { RTCPSender(bool audio, Clock* clock, - ReceiveStatistics* receive_statistics, + ReceiveStatisticsProvider* receive_statistics, RtcpPacketTypeCounterObserver* packet_type_counter_observer, RtcEventLog* event_log, Transport* outgoing_transport); @@ -211,7 +211,7 @@ class RTCPSender { uint32_t remote_ssrc_ GUARDED_BY(critical_section_rtcp_sender_); std::string cname_ GUARDED_BY(critical_section_rtcp_sender_); - ReceiveStatistics* receive_statistics_ + ReceiveStatisticsProvider* receive_statistics_ GUARDED_BY(critical_section_rtcp_sender_); std::map csrc_cnames_ GUARDED_BY(critical_section_rtcp_sender_);