Add support for updating histogram for received fraction loss ("WebRTC.Video.ReceivedPacketsLostInPercent") when running new video api.
Add tests for verifying that video histograms are updated.
BUG=
R=pbos@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/44309004
Cr-Commit-Position: refs/heads/master@{#9085}
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 389d773..abe7f1d 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -78,6 +78,7 @@
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
void TestRtpStatePreservation(bool use_rtx);
void TestReceivedFecPacketsNotNacked(const FakeNetworkPipe::Config& config);
+ void VerifyHistogramStats(bool use_rtx, bool use_red);
};
TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
@@ -1497,11 +1498,12 @@
int64_t start_runtime_ms_;
} test;
+ test::ClearHistograms();
RunBaseTest(&test);
- EXPECT_NE(-1, test::LastHistogramSample(
+ EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.UniqueNackRequestsSentInPercent"));
- EXPECT_NE(-1, test::LastHistogramSample(
+ EXPECT_EQ(1, test::NumHistogramSamples(
"WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
EXPECT_GT(test::LastHistogramSample(
"WebRTC.Video.NackPacketsSentPerMinute"), 0);
@@ -1509,6 +1511,165 @@
"WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
}
+void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
+ class StatsObserver : public test::EndToEndTest, public PacketReceiver {
+ public:
+ StatsObserver(bool use_rtx, bool use_red)
+ : EndToEndTest(kLongTimeoutMs),
+ use_rtx_(use_rtx),
+ use_red_(use_red),
+ sender_call_(nullptr),
+ receiver_call_(nullptr),
+ start_runtime_ms_(-1) {}
+
+ private:
+ Action OnSendRtp(const uint8_t* packet, size_t length) override {
+ if (MinMetricRunTimePassed())
+ observation_complete_->Set();
+
+ return SEND_PACKET;
+ }
+
+ DeliveryStatus DeliverPacket(const uint8_t* packet,
+ size_t length) override {
+ // GetStats calls GetSendChannelRtcpStatistics
+ // (via VideoSendStream::GetRtt) which updates ReportBlockStats used by
+ // WebRTC.Video.SentPacketsLostInPercent.
+ // TODO(asapersson): Remove dependency on calling GetStats.
+ sender_call_->GetStats();
+ return receiver_call_->Receiver()->DeliverPacket(packet, length);
+ }
+
+ bool MinMetricRunTimePassed() {
+ int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
+ if (start_runtime_ms_ == -1) {
+ start_runtime_ms_ = now;
+ return false;
+ }
+ int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
+ return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
+ }
+
+ void ModifyConfigs(VideoSendStream::Config* send_config,
+ std::vector<VideoReceiveStream::Config>* receive_configs,
+ VideoEncoderConfig* encoder_config) override {
+ // NACK
+ send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ // FEC
+ if (use_red_) {
+ send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ send_config->rtp.fec.red_payload_type = kRedPayloadType;
+ (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
+ (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ }
+ // RTX
+ if (use_rtx_) {
+ send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
+ send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
+ (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].ssrc =
+ kSendRtxSsrcs[0];
+ (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
+ kSendRtxPayloadType;
+ }
+ }
+
+ void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
+ sender_call_ = sender_call;
+ receiver_call_ = receiver_call;
+ }
+
+ void SetReceivers(PacketReceiver* send_transport_receiver,
+ PacketReceiver* receive_transport_receiver) override {
+ test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
+ }
+
+ void PerformTest() override {
+ EXPECT_EQ(kEventSignaled, Wait())
+ << "Timed out waiting for packet to be NACKed.";
+ }
+
+ bool use_rtx_;
+ bool use_red_;
+ Call* sender_call_;
+ Call* receiver_call_;
+ int64_t start_runtime_ms_;
+ } test(use_rtx, use_red);
+
+ test::ClearHistograms();
+ RunBaseTest(&test);
+
+ // Verify that stats have been updated once.
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.NackPacketsSentPerMinute"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.NackPacketsReceivedPerMinute"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.FirPacketsSentPerMinute"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.FirPacketsReceivedPerMinute"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.PliPacketsSentPerMinute"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.PliPacketsReceivedPerMinute"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.KeyFramesSentInPermille"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.KeyFramesReceivedInPermille"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.SentPacketsLostInPercent"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.ReceivedPacketsLostInPercent"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.DecodedFramesPerSecond"));
+
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.BitrateSentInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.BitrateReceivedInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.MediaBitrateSentInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.MediaBitrateReceivedInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.PaddingBitrateSentInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.PaddingBitrateReceivedInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.RetransmittedBitrateSentInKbps"));
+ EXPECT_EQ(1, test::NumHistogramSamples(
+ "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
+
+ int num_rtx_samples = use_rtx ? 1 : 0;
+ EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
+ "WebRTC.Video.RtxBitrateSentInKbps"));
+ EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
+ "WebRTC.Video.RtxBitrateReceivedInKbps"));
+
+ int num_red_samples = use_red ? 1 : 0;
+ EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
+ "WebRTC.Video.FecBitrateSentInKbps"));
+ EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
+ "WebRTC.Video.FecBitrateReceivedInKbps"));
+ EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
+ "WebRTC.Video.ReceivedFecPacketsInPercent"));
+}
+
+TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
+ const bool kEnabledRtx = true;
+ const bool kEnabledRed = false;
+ VerifyHistogramStats(kEnabledRtx, kEnabledRed);
+}
+
+TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
+ const bool kEnabledRtx = false;
+ const bool kEnabledRed = true;
+ VerifyHistogramStats(kEnabledRtx, kEnabledRed);
+}
+
void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
static const int kNumRtcpReportPacketsToObserve = 5;
class RtcpXrObserver : public test::EndToEndTest {
diff --git a/webrtc/video/receive_statistics_proxy.cc b/webrtc/video/receive_statistics_proxy.cc
index 83b34dd..3637bc1 100644
--- a/webrtc/video/receive_statistics_proxy.cc
+++ b/webrtc/video/receive_statistics_proxy.cc
@@ -12,6 +12,7 @@
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/metrics.h"
namespace webrtc {
@@ -24,7 +25,21 @@
stats_.ssrc = ssrc;
}
-ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {}
+ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
+ UpdateHistograms();
+}
+
+void ReceiveStatisticsProxy::UpdateHistograms() const {
+ int fraction_lost;
+ {
+ CriticalSectionScoped lock(crit_.get());
+ fraction_lost = report_block_stats_.FractionLostInPercent();
+ }
+ if (fraction_lost != -1) {
+ RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent",
+ fraction_lost);
+ }
+}
VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
CriticalSectionScoped lock(crit_.get());
@@ -74,6 +89,7 @@
if (stats_.ssrc != ssrc)
return;
stats_.rtcp_stats = statistics;
+ report_block_stats_.Store(statistics, ssrc, 0);
}
void ReceiveStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
diff --git a/webrtc/video/receive_statistics_proxy.h b/webrtc/video/receive_statistics_proxy.h
index e27a19c..00ed786 100644
--- a/webrtc/video/receive_statistics_proxy.h
+++ b/webrtc/video/receive_statistics_proxy.h
@@ -20,6 +20,7 @@
#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
#include "webrtc/video_engine/include/vie_codec.h"
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
+#include "webrtc/video_engine/report_block_stats.h"
#include "webrtc/video_receive_stream.h"
#include "webrtc/video_renderer.h"
@@ -78,12 +79,14 @@
uint32_t ssrc) override;
private:
+ void UpdateHistograms() const;
Clock* const clock_;
rtc::scoped_ptr<CriticalSectionWrapper> crit_;
VideoReceiveStream::Stats stats_ GUARDED_BY(crit_);
RateStatistics decode_fps_estimator_ GUARDED_BY(crit_);
RateStatistics renders_fps_estimator_ GUARDED_BY(crit_);
+ ReportBlockStats report_block_stats_ GUARDED_BY(crit_);
};
} // namespace webrtc