Move RTP stats histograms from VieChannel to SendStatisticsProxy.
Also slice for screensharing.
BUG=
R=mflodman@webrtc.org, pbos@webrtc.org
Review URL: https://codereview.webrtc.org/1734933002 .
Cr-Commit-Position: refs/heads/master@{#11822}
diff --git a/webrtc/common_types.h b/webrtc/common_types.h
index 16174dc..191d9aa 100644
--- a/webrtc/common_types.h
+++ b/webrtc/common_types.h
@@ -11,6 +11,7 @@
#ifndef WEBRTC_COMMON_TYPES_H_
#define WEBRTC_COMMON_TYPES_H_
+#include <assert.h>
#include <stddef.h>
#include <string.h>
@@ -791,6 +792,17 @@
packets += other.packets;
}
+ void Subtract(const RtpPacketCounter& other) {
+ assert(header_bytes >= other.header_bytes);
+ header_bytes -= other.header_bytes;
+ assert(payload_bytes >= other.payload_bytes);
+ payload_bytes -= other.payload_bytes;
+ assert(padding_bytes >= other.padding_bytes);
+ padding_bytes -= other.padding_bytes;
+ assert(packets >= other.packets);
+ packets -= other.packets;
+ }
+
void AddPacket(size_t packet_length, const RTPHeader& header) {
++packets;
header_bytes += header.headerLength;
@@ -825,6 +837,18 @@
}
}
+ void Subtract(const StreamDataCounters& other) {
+ transmitted.Subtract(other.transmitted);
+ retransmitted.Subtract(other.retransmitted);
+ fec.Subtract(other.fec);
+ if (other.first_packet_time_ms != -1 &&
+ (other.first_packet_time_ms > first_packet_time_ms ||
+ first_packet_time_ms == -1)) {
+ // Use youngest time.
+ first_packet_time_ms = other.first_packet_time_ms;
+ }
+ }
+
int64_t TimeSinceFirstPacketInMs(int64_t now_ms) const {
return (first_packet_time_ms == -1) ? -1 : (now_ms - first_packet_time_ms);
}
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 94a87d8..2a88e28 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -2246,20 +2246,19 @@
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
- EXPECT_EQ(1, test::NumHistogramSamples(
- "WebRTC.Video.BitrateSentInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "BitrateSentInKbps"));
EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.BitrateReceivedInKbps"));
- EXPECT_EQ(1, test::NumHistogramSamples(
- "WebRTC.Video.MediaBitrateSentInKbps"));
+ EXPECT_EQ(1,
+ test::NumHistogramSamples(video_prefix + "MediaBitrateSentInKbps"));
EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.MediaBitrateReceivedInKbps"));
- EXPECT_EQ(1, test::NumHistogramSamples(
- "WebRTC.Video.PaddingBitrateSentInKbps"));
+ EXPECT_EQ(
+ 1, test::NumHistogramSamples(video_prefix + "PaddingBitrateSentInKbps"));
EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.PaddingBitrateReceivedInKbps"));
- EXPECT_EQ(1, test::NumHistogramSamples(
- "WebRTC.Video.RetransmittedBitrateSentInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(video_prefix +
+ "RetransmittedBitrateSentInKbps"));
EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc
index 729c775..6407cdc 100644
--- a/webrtc/video/send_statistics_proxy.cc
+++ b/webrtc/video/send_statistics_proxy.cc
@@ -98,10 +98,26 @@
input_frame_rate_tracker_(100u, 10u),
sent_frame_rate_tracker_(100u, 10u),
first_rtcp_stats_time_ms_(-1),
+ first_rtp_stats_time_ms_(-1),
start_stats_(stats) {}
SendStatisticsProxy::UmaSamplesContainer::~UmaSamplesContainer() {}
+void AccumulateRtpStats(const VideoSendStream::Stats& stats,
+ const VideoSendStream::Config& config,
+ StreamDataCounters* total_rtp_stats,
+ StreamDataCounters* rtx_stats) {
+ for (auto it : stats.substreams) {
+ const std::vector<uint32_t> rtx_ssrcs = config.rtp.rtx.ssrcs;
+ if (std::find(rtx_ssrcs.begin(), rtx_ssrcs.end(), it.first) !=
+ rtx_ssrcs.end()) {
+ rtx_stats->Add(it.second.rtp_stats);
+ } else {
+ total_rtp_stats->Add(it.second.rtp_stats);
+ }
+ }
+}
+
void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms(
const VideoSendStream::Config& config,
const VideoSendStream::Stats& current_stats) {
@@ -223,6 +239,51 @@
}
}
}
+
+ if (first_rtp_stats_time_ms_ != -1) {
+ int64_t elapsed_sec =
+ (clock_->TimeInMilliseconds() - first_rtp_stats_time_ms_) / 1000;
+ if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
+ StreamDataCounters rtp;
+ StreamDataCounters rtx;
+ AccumulateRtpStats(current_stats, config, &rtp, &rtx);
+ StreamDataCounters start_rtp;
+ StreamDataCounters start_rtx;
+ AccumulateRtpStats(start_stats_, config, &start_rtp, &start_rtx);
+ rtp.Subtract(start_rtp);
+ rtx.Subtract(start_rtx);
+ StreamDataCounters rtp_rtx = rtp;
+ rtp_rtx.Add(rtx);
+
+ RTC_HISTOGRAMS_COUNTS_10000(
+ kIndex, uma_prefix_ + "BitrateSentInKbps",
+ static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
+ 1000));
+ RTC_HISTOGRAMS_COUNTS_10000(
+ kIndex, uma_prefix_ + "MediaBitrateSentInKbps",
+ static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000));
+ RTC_HISTOGRAMS_COUNTS_10000(
+ kIndex, uma_prefix_ + "PaddingBitrateSentInKbps",
+ static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec /
+ 1000));
+ RTC_HISTOGRAMS_COUNTS_10000(
+ kIndex, uma_prefix_ + "RetransmittedBitrateSentInKbps",
+ static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 /
+ elapsed_sec / 1000));
+ if (!config.rtp.rtx.ssrcs.empty()) {
+ RTC_HISTOGRAMS_COUNTS_10000(
+ kIndex, uma_prefix_ + "RtxBitrateSentInKbps",
+ static_cast<int>(rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
+ 1000));
+ }
+ if (config.rtp.fec.red_payload_type != -1) {
+ RTC_HISTOGRAMS_COUNTS_10000(kIndex,
+ uma_prefix_ + "FecBitrateSentInKbps",
+ static_cast<int>(rtp_rtx.fec.TotalBytes() *
+ 8 / elapsed_sec / 1000));
+ }
+ }
+ }
}
void SendStatisticsProxy::SetContentType(
@@ -429,6 +490,8 @@
<< "DataCountersUpdated reported for unknown ssrc: " << ssrc;
stats->rtp_stats = counters;
+ if (uma_container_->first_rtp_stats_time_ms_ == -1)
+ uma_container_->first_rtp_stats_time_ms_ = clock_->TimeInMilliseconds();
}
void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h
index 0d0d0e0..24a09b0 100644
--- a/webrtc/video/send_statistics_proxy.h
+++ b/webrtc/video/send_statistics_proxy.h
@@ -169,6 +169,7 @@
rtc::RateTracker input_frame_rate_tracker_;
rtc::RateTracker sent_frame_rate_tracker_;
int64_t first_rtcp_stats_time_ms_;
+ int64_t first_rtp_stats_time_ms_;
ReportBlockStats report_block_stats_;
const VideoSendStream::Stats start_stats_;
};
diff --git a/webrtc/video/send_statistics_proxy_unittest.cc b/webrtc/video/send_statistics_proxy_unittest.cc
index c112013..b3da5e9 100644
--- a/webrtc/video/send_statistics_proxy_unittest.cc
+++ b/webrtc/video/send_statistics_proxy_unittest.cc
@@ -47,6 +47,7 @@
config.rtp.ssrcs.push_back(kSecondSsrc);
config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
+ config.rtp.fec.red_payload_type = 17;
return config;
}
@@ -525,4 +526,136 @@
"WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
}
+TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
+ StreamDataCountersCallback* proxy =
+ static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
+ StreamDataCounters counters;
+ StreamDataCounters rtx_counters;
+ counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
+ proxy->DataCountersUpdated(counters, kFirstSsrc);
+ proxy->DataCountersUpdated(counters, kSecondSsrc);
+ proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
+ proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
+
+ counters.transmitted.header_bytes = 400;
+ counters.transmitted.packets = 20;
+ counters.transmitted.padding_bytes = 1000;
+ counters.transmitted.payload_bytes = 2000;
+
+ counters.retransmitted.header_bytes = 40;
+ counters.retransmitted.packets = 2;
+ counters.retransmitted.padding_bytes = 100;
+ counters.retransmitted.payload_bytes = 200;
+
+ counters.fec = counters.retransmitted;
+
+ rtx_counters.transmitted = counters.transmitted;
+
+ fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
+ proxy->DataCountersUpdated(counters, kFirstSsrc);
+ proxy->DataCountersUpdated(counters, kSecondSsrc);
+ proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
+ proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
+
+ // Changing content type causes histograms to be reported.
+ statistics_proxy_->SetContentType(VideoEncoderConfig::ContentType::kScreen);
+
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.BitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((counters.transmitted.TotalBytes() * 4 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample("WebRTC.Video.BitrateSentInKbps"));
+
+ EXPECT_EQ(1,
+ test::NumHistogramSamples("WebRTC.Video.MediaBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((counters.MediaPayloadBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample("WebRTC.Video.MediaBitrateSentInKbps"));
+
+ EXPECT_EQ(1,
+ test::NumHistogramSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((counters.transmitted.padding_bytes * 4 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample("WebRTC.Video.PaddingBitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.RetransmittedBitrateSentInKbps"));
+ EXPECT_EQ(
+ static_cast<int>((counters.retransmitted.TotalBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample("WebRTC.Video.RetransmittedBitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RtxBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((rtx_counters.transmitted.TotalBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample("WebRTC.Video.RtxBitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.FecBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((rtx_counters.fec.TotalBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample("WebRTC.Video.FecBitrateSentInKbps"));
+
+ // New start time but same counter values.
+ proxy->DataCountersUpdated(counters, kFirstSsrc);
+ proxy->DataCountersUpdated(counters, kSecondSsrc);
+ proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
+ proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
+
+ // Double counter values, this should result in the same counts as before but
+ // with new histogram names.
+ StreamDataCounters new_counters = counters;
+ new_counters.Add(counters);
+ StreamDataCounters new_rtx_counters = rtx_counters;
+ new_rtx_counters.Add(rtx_counters);
+
+ fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
+ proxy->DataCountersUpdated(new_counters, kFirstSsrc);
+ proxy->DataCountersUpdated(new_counters, kSecondSsrc);
+ proxy->DataCountersUpdated(new_rtx_counters, kFirstRtxSsrc);
+ proxy->DataCountersUpdated(new_rtx_counters, kSecondRtxSsrc);
+
+ SetUp(); // Reset stats proxy also causes histograms to be reported.
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.Screenshare.BitrateSentInKbps"));
+ EXPECT_EQ(
+ static_cast<int>((counters.transmitted.TotalBytes() * 4 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample("WebRTC.Video.Screenshare.BitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((counters.MediaPayloadBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample(
+ "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((counters.transmitted.padding_bytes * 4 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample(
+ "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((counters.retransmitted.TotalBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample(
+ "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((rtx_counters.transmitted.TotalBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample(
+ "WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
+ EXPECT_EQ(static_cast<int>((rtx_counters.fec.TotalBytes() * 2 * 8) /
+ metrics::kMinRunTimeInSeconds / 1000),
+ test::LastHistogramSample(
+ "WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
+}
+
} // namespace webrtc
diff --git a/webrtc/video/vie_channel.cc b/webrtc/video/vie_channel.cc
index 3099286..2b601ed 100644
--- a/webrtc/video/vie_channel.cc
+++ b/webrtc/video/vie_channel.cc
@@ -163,7 +163,6 @@
}
ViEChannel::~ViEChannel() {
- UpdateHistograms();
// Make sure we don't get more callbacks from the RTP module.
module_process_thread_->DeRegisterModule(
vie_receiver_.GetReceiveStatistics());
@@ -177,52 +176,6 @@
}
}
-void ViEChannel::UpdateHistograms() {
- if (sender_) {
- StreamDataCounters rtp;
- StreamDataCounters rtx;
- GetSendStreamDataCounters(&rtp, &rtx);
- StreamDataCounters rtp_rtx = rtp;
- rtp_rtx.Add(rtx);
- int64_t elapsed_sec = rtp_rtx.TimeSinceFirstPacketInMs(
- Clock::GetRealTimeClock()->TimeInMilliseconds()) /
- 1000;
- if (elapsed_sec > metrics::kMinRunTimeInSeconds) {
- RTC_HISTOGRAM_COUNTS_100000(
- "WebRTC.Video.BitrateSentInKbps",
- static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
- 1000));
- RTC_HISTOGRAM_COUNTS_10000(
- "WebRTC.Video.MediaBitrateSentInKbps",
- static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000));
- RTC_HISTOGRAM_COUNTS_10000(
- "WebRTC.Video.PaddingBitrateSentInKbps",
- static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec /
- 1000));
- RTC_HISTOGRAM_COUNTS_10000(
- "WebRTC.Video.RetransmittedBitrateSentInKbps",
- static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 /
- elapsed_sec / 1000));
- if (rtp_rtcp_modules_[0]->RtxSendStatus() != kRtxOff) {
- RTC_HISTOGRAM_COUNTS_10000(
- "WebRTC.Video.RtxBitrateSentInKbps",
- static_cast<int>(rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
- 1000));
- }
- bool fec_enabled = false;
- uint8_t pltype_red;
- uint8_t pltype_fec;
- rtp_rtcp_modules_[0]->GenericFECStatus(&fec_enabled, &pltype_red,
- &pltype_fec);
- if (fec_enabled) {
- RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FecBitrateSentInKbps",
- static_cast<int>(rtp_rtx.fec.TotalBytes() *
- 8 / elapsed_sec / 1000));
- }
- }
- }
-}
-
int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
bool new_stream) {
RTC_DCHECK(sender_);
diff --git a/webrtc/video/vie_channel.h b/webrtc/video/vie_channel.h
index 2cb623c..afb8d89 100644
--- a/webrtc/video/vie_channel.h
+++ b/webrtc/video/vie_channel.h
@@ -200,8 +200,6 @@
// Compute NACK list parameters for the buffering mode.
int GetRequiredNackListSize(int target_delay_ms);
- void UpdateHistograms();
-
// ViEChannel exposes methods that allow to modify observers and callbacks
// to be modified. Such an API-style is cumbersome to implement and maintain
// at all the levels when comparing to only setting them at construction. As