blob: 4dbfc03a746307488b38fc6d21ab26302ab6f023 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
13#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080014#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000015#include <string>
16#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "system_wrappers/include/metrics.h"
19#include "system_wrappers/include/metrics_default.h"
asapersson8d75ac72017-09-15 06:41:15 -070020#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000022
23namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070024namespace {
25const uint32_t kFirstSsrc = 17;
26const uint32_t kSecondSsrc = 42;
27const uint32_t kFirstRtxSsrc = 18;
28const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080029const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080030const int kFpsPeriodicIntervalMs = 2000;
31const int kWidth = 640;
32const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070033const int kQpIdx0 = 21;
34const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010035const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080036const CodecSpecificInfo kDefaultCodecInfo = []() {
37 CodecSpecificInfo codec_info;
38 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080039 return codec_info;
40}();
asapersson5265fed2016-04-18 02:58:47 -070041} // namespace
sprang07fb9be2016-02-24 07:55:00 -080042
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000043class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000044 public:
asapersson8d75ac72017-09-15 06:41:15 -070045 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
46 explicit SendStatisticsProxyTest(const std::string& field_trials)
47 : override_field_trials_(field_trials),
48 fake_clock_(1234),
49 config_(GetTestConfig()),
50 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070051 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000052 virtual ~SendStatisticsProxyTest() {}
53
54 protected:
55 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070056 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080057 statistics_proxy_.reset(new SendStatisticsProxy(
58 &fake_clock_, GetTestConfig(),
59 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000060 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070061 for (const auto& ssrc : config_.rtp.ssrcs)
62 expected_.substreams[ssrc].is_rtx = false;
63 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
64 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000065 }
66
67 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070068 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080069 config.rtp.ssrcs.push_back(kFirstSsrc);
70 config.rtp.ssrcs.push_back(kSecondSsrc);
71 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
72 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070073 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000074 return config;
75 }
76
asaperssona6a699a2016-11-25 03:52:46 -080077 VideoSendStream::Config GetTestConfigWithFlexFec() {
78 VideoSendStream::Config config(nullptr);
79 config.rtp.ssrcs.push_back(kFirstSsrc);
80 config.rtp.ssrcs.push_back(kSecondSsrc);
81 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
82 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080083 config.rtp.flexfec.payload_type = 50;
84 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080085 return config;
86 }
87
88 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
89 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
90 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
91 stats.substreams.find(ssrc);
92 EXPECT_NE(it, stats.substreams.end());
93 return it->second;
94 }
95
asapersson66d4b372016-12-19 06:50:53 -080096 void UpdateDataCounters(uint32_t ssrc) {
97 StreamDataCountersCallback* proxy =
98 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
99 StreamDataCounters counters;
100 proxy->DataCountersUpdated(counters, ssrc);
101 }
102
sprang@webrtc.org09315702014-02-07 12:06:29 +0000103 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000104 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
105 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000106 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000107 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000108
109 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000110 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000111 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000112 it != one.substreams.end(); ++it) {
113 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
114 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000115 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000116 const VideoSendStream::StreamStats& a = it->second;
117 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000118
asapersson2e5cfcd2016-08-11 08:41:18 -0700119 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000120 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
121 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000122 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000123 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
124 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000125
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000126 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
127 b.rtp_stats.transmitted.payload_bytes);
128 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
129 b.rtp_stats.transmitted.header_bytes);
130 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
131 b.rtp_stats.transmitted.padding_bytes);
132 EXPECT_EQ(a.rtp_stats.transmitted.packets,
133 b.rtp_stats.transmitted.packets);
134 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
135 b.rtp_stats.retransmitted.packets);
136 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000137
138 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700139 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
140 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
141 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
143 }
144 }
145
asapersson8d75ac72017-09-15 06:41:15 -0700146 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000147 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800148 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000149 VideoSendStream::Config config_;
150 int avg_delay_ms_;
151 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000152 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000153 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
154 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000155};
156
157TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
158 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700159 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000160 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000161
162 // Add statistics with some arbitrary, but unique, numbers.
163 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700164 ssrc_stats.rtcp_stats.packets_lost = offset;
165 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000166 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
167 ssrc_stats.rtcp_stats.jitter = offset + 3;
168 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
169 }
asapersson35151f32016-05-02 23:44:01 -0700170 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000171 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000172
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000173 // Add statistics with some arbitrary, but unique, numbers.
174 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700175 ssrc_stats.rtcp_stats.packets_lost = offset;
176 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000177 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
178 ssrc_stats.rtcp_stats.jitter = offset + 3;
179 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
180 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000181 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000182 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000183}
184
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000185TEST_F(SendStatisticsProxyTest, Suspended) {
186 // Verify that the value is false by default.
187 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
188
189 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200190 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000191 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
192
193 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200194 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000195 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
196}
197
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000198TEST_F(SendStatisticsProxyTest, FrameCounts) {
199 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700200 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000201 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000202 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
203 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000204 FrameCounts frame_counts;
205 frame_counts.key_frames = offset;
206 frame_counts.delta_frames = offset + 1;
207 stats.frame_counts = frame_counts;
208 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000209 }
asapersson35151f32016-05-02 23:44:01 -0700210 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000211 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000212 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
213 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000214 FrameCounts frame_counts;
215 frame_counts.key_frames = offset;
216 frame_counts.delta_frames = offset + 1;
217 stats.frame_counts = frame_counts;
218 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000219 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000220
221 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000222 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000223}
224
225TEST_F(SendStatisticsProxyTest, DataCounters) {
226 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700227 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000228 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
229 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000230 size_t offset = ssrc * sizeof(StreamDataCounters);
231 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000232 counters.transmitted.payload_bytes = offset;
233 counters.transmitted.header_bytes = offset + 1;
234 counters.fec.packets = offset_uint32 + 2;
235 counters.transmitted.padding_bytes = offset + 3;
236 counters.retransmitted.packets = offset_uint32 + 4;
237 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000238 callback->DataCountersUpdated(counters, ssrc);
239 }
asapersson35151f32016-05-02 23:44:01 -0700240 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000241 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
242 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000243 size_t offset = ssrc * sizeof(StreamDataCounters);
244 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000245 counters.transmitted.payload_bytes = offset;
246 counters.transmitted.header_bytes = offset + 1;
247 counters.fec.packets = offset_uint32 + 2;
248 counters.transmitted.padding_bytes = offset + 3;
249 counters.retransmitted.packets = offset_uint32 + 4;
250 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000251 callback->DataCountersUpdated(counters, ssrc);
252 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000253
254 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000255 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000256}
257
258TEST_F(SendStatisticsProxyTest, Bitrate) {
259 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700260 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700261 uint32_t total;
262 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000263 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700264 total = ssrc;
265 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000266 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700267 expected_.substreams[ssrc].total_bitrate_bps = total;
268 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000269 }
asapersson35151f32016-05-02 23:44:01 -0700270 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700271 uint32_t total;
272 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000273 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700274 total = ssrc;
275 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000276 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700277 expected_.substreams[ssrc].total_bitrate_bps = total;
278 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000279 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000280
281 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000282 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000283}
284
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000285TEST_F(SendStatisticsProxyTest, SendSideDelay) {
286 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700287 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000288 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
289 // stream.
290 int avg_delay_ms = ssrc;
291 int max_delay_ms = ssrc + 1;
292 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
293 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
294 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
295 }
asapersson35151f32016-05-02 23:44:01 -0700296 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000297 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
298 // stream.
299 int avg_delay_ms = ssrc;
300 int max_delay_ms = ssrc + 1;
301 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
302 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
303 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
304 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000305 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000306 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000307}
308
Peter Boströme4499152016-02-05 11:13:28 +0100309TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800310 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200311 int encode_usage_percent = 80;
312 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
313 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800314
315 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
316 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200317 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800318}
319
sakal43536c32016-10-24 01:46:43 -0700320TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
321 EncodedImage encoded_image;
322 CodecSpecificInfo codec_info;
323 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
324 for (uint32_t i = 1; i <= 3; ++i) {
325 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
326 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
327 }
328}
329
sakal87da4042016-10-31 06:53:47 -0700330TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
331 EncodedImage encoded_image;
332 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200333 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700334 encoded_image.qp_ = 3;
335 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100336 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700337 encoded_image.qp_ = 127;
338 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100339 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700340}
341
342TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
343 EncodedImage encoded_image;
344 CodecSpecificInfo codec_info;
345 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200346 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700347 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200348 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700349}
350
asapersson09f05612017-05-15 23:40:18 -0700351TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200352 SendStatisticsProxy::AdaptationSteps cpu_counts;
353 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700354 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700355 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200356 cpu_counts.num_framerate_reductions = 1;
357 cpu_counts.num_resolution_reductions = 0;
358 statistics_proxy_->OnAdaptationChanged(
359 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
360 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700361 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700362 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200363 cpu_counts.num_framerate_reductions = 0;
364 cpu_counts.num_resolution_reductions = 1;
365 statistics_proxy_->OnAdaptationChanged(
366 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
367 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700368 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700369 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200370 cpu_counts.num_framerate_reductions = 1;
371 cpu_counts.num_resolution_reductions = absl::nullopt;
372 statistics_proxy_->OnAdaptationChanged(
373 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
374 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700375 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700376 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200377 cpu_counts.num_framerate_reductions = absl::nullopt;
378 cpu_counts.num_resolution_reductions = absl::nullopt;
379 statistics_proxy_->OnAdaptationChanged(
380 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
381 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700382 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
383 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
384}
385
386TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200387 SendStatisticsProxy::AdaptationSteps cpu_counts;
388 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700389 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
390 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200391 quality_counts.num_framerate_reductions = 1;
392 quality_counts.num_resolution_reductions = 0;
393 statistics_proxy_->OnAdaptationChanged(
394 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
395 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700396 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
397 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200398 quality_counts.num_framerate_reductions = 0;
399 quality_counts.num_resolution_reductions = 1;
400 statistics_proxy_->OnAdaptationChanged(
401 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
402 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700403 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
404 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200405 quality_counts.num_framerate_reductions = 1;
406 quality_counts.num_resolution_reductions = absl::nullopt;
407 statistics_proxy_->OnAdaptationChanged(
408 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
409 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700410 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
411 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200412 quality_counts.num_framerate_reductions = absl::nullopt;
413 quality_counts.num_resolution_reductions = absl::nullopt;
414 statistics_proxy_->OnAdaptationChanged(
415 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
416 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700417 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
418 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
419}
420
421TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200422 SendStatisticsProxy::AdaptationSteps cpu_counts;
423 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700424 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
425
Niels Möller213618e2018-07-24 09:29:58 +0200426 cpu_counts.num_resolution_reductions = 1;
427 statistics_proxy_->OnAdaptationChanged(
428 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
429 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700430 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700431 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
432 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
433
Niels Möller213618e2018-07-24 09:29:58 +0200434 cpu_counts.num_resolution_reductions = 2;
435 statistics_proxy_->OnAdaptationChanged(
436 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
437 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700438 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
439 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700440 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700441 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700442}
443
asapersson09f05612017-05-15 23:40:18 -0700444TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200445 SendStatisticsProxy::AdaptationSteps cpu_counts;
446 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700447 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
448
Niels Möller213618e2018-07-24 09:29:58 +0200449 quality_counts.num_framerate_reductions = 1;
450 statistics_proxy_->OnAdaptationChanged(
451 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
452 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700453 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
454 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700455 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
456
Niels Möller213618e2018-07-24 09:29:58 +0200457 quality_counts.num_framerate_reductions = 0;
458 statistics_proxy_->OnAdaptationChanged(
459 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
460 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700461 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700462 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700463 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
464 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700465}
466
asapersson09f05612017-05-15 23:40:18 -0700467TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700468 // First RTP packet sent.
469 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700470 // Min runtime has passed.
471 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
472 statistics_proxy_.reset();
473 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
474 EXPECT_EQ(0,
475 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
476}
477
478TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700479 // First RTP packet sent.
480 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700481 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200482 SendStatisticsProxy::AdaptationSteps cpu_counts;
483 SendStatisticsProxy::AdaptationSteps quality_counts;
484 statistics_proxy_->OnAdaptationChanged(
485 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
486 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700487 // Min runtime has not passed.
488 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
489 statistics_proxy_.reset();
490 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
491 EXPECT_EQ(0,
492 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
493}
494
asapersson09f05612017-05-15 23:40:18 -0700495TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700496 // First RTP packet sent.
497 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700498 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200499 SendStatisticsProxy::AdaptationSteps cpu_counts;
500 SendStatisticsProxy::AdaptationSteps quality_counts;
501 statistics_proxy_->OnAdaptationChanged(
502 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
503 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700504 // Min runtime has passed.
505 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
506 statistics_proxy_.reset();
507 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
508 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700509 EXPECT_EQ(1,
510 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
511 EXPECT_EQ(
512 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
513}
514
515TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700516 // First RTP packet sent.
517 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700518 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200519 SendStatisticsProxy::AdaptationSteps cpu_counts;
520 SendStatisticsProxy::AdaptationSteps quality_counts;
521 statistics_proxy_->OnAdaptationChanged(
522 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
523 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700524 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200525 statistics_proxy_->OnAdaptationChanged(
526 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
527 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700528 fake_clock_.AdvanceTimeMilliseconds(10000);
529 statistics_proxy_.reset();
530 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
531 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
532}
533
Åsa Persson875841d2018-01-08 08:49:53 +0100534TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
535 // First RTP packet sent.
536 UpdateDataCounters(kFirstSsrc);
537 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200538 SendStatisticsProxy::AdaptationSteps cpu_counts;
539 SendStatisticsProxy::AdaptationSteps quality_counts;
540 statistics_proxy_->OnAdaptationChanged(
541 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
542 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100543 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200544 statistics_proxy_->OnAdaptationChanged(
545 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
546 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100547 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
548 fake_clock_.AdvanceTimeMilliseconds(10000);
549 statistics_proxy_.reset();
550 EXPECT_EQ(1,
551 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
552 EXPECT_EQ(
553 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
554}
555
556TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
557 // First RTP packet sent.
558 UpdateDataCounters(kFirstSsrc);
559 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200560 SendStatisticsProxy::AdaptationSteps cpu_counts;
561 SendStatisticsProxy::AdaptationSteps quality_counts;
562 statistics_proxy_->OnAdaptationChanged(
563 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
564 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100565 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200566 quality_counts.num_resolution_reductions = 1;
567 statistics_proxy_->OnAdaptationChanged(
568 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
569 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100570 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200571 quality_counts.num_resolution_reductions = 2;
572 statistics_proxy_->OnAdaptationChanged(
573 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
574 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100575 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200576 quality_counts.num_resolution_reductions = 3;
577 statistics_proxy_->OnAdaptationChanged(
578 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
579 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100580 fake_clock_.AdvanceTimeMilliseconds(10000);
581 statistics_proxy_.reset();
582 EXPECT_EQ(1,
583 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
584 EXPECT_EQ(
585 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
586}
587
588TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
589 // First RTP packet sent.
590 UpdateDataCounters(kFirstSsrc);
591 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200592 SendStatisticsProxy::AdaptationSteps cpu_counts;
593 SendStatisticsProxy::AdaptationSteps quality_counts;
594 statistics_proxy_->OnAdaptationChanged(
595 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
596 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100597 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200598 statistics_proxy_->OnAdaptationChanged(
599 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
600 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100601 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
602 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
603 fake_clock_.AdvanceTimeMilliseconds(10000);
604 statistics_proxy_.reset();
605 EXPECT_EQ(1,
606 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
607 EXPECT_EQ(
608 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
609}
610
611TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
612 // First RTP packet sent.
613 UpdateDataCounters(kFirstSsrc);
614 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200615 SendStatisticsProxy::AdaptationSteps cpu_counts;
616 SendStatisticsProxy::AdaptationSteps quality_counts;
617 statistics_proxy_->OnAdaptationChanged(
618 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
619 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100620 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200621 quality_counts.num_resolution_reductions = 1;
622 statistics_proxy_->OnAdaptationChanged(
623 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
624 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100625 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200626 quality_counts.num_resolution_reductions = 2;
627 statistics_proxy_->OnAdaptationChanged(
628 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
629 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100630 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200631 quality_counts.num_resolution_reductions = 3;
632 statistics_proxy_->OnAdaptationChanged(
633 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
634 quality_counts);
635 quality_counts.num_framerate_reductions = 1;
636 statistics_proxy_->OnAdaptationChanged(
637 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
638 quality_counts);
639 quality_counts.num_framerate_reductions = 0;
640 statistics_proxy_->OnAdaptationChanged(
641 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
642 quality_counts);
643 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
644 statistics_proxy_->OnAdaptationChanged(
645 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
646 quality_counts);
647 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
648 statistics_proxy_->OnAdaptationChanged(
649 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
650 quality_counts);
651 quality_counts.num_resolution_reductions = 0;
652 statistics_proxy_->OnAdaptationChanged(
653 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
654 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100655
656 fake_clock_.AdvanceTimeMilliseconds(10000);
657 statistics_proxy_.reset();
658 EXPECT_EQ(1,
659 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
660 EXPECT_EQ(
661 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
662}
663
asapersson6eca98b2017-04-04 23:40:50 -0700664TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700665 // First RTP packet sent.
666 UpdateDataCounters(kFirstSsrc);
667
asapersson09f05612017-05-15 23:40:18 -0700668 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200669 SendStatisticsProxy::AdaptationSteps cpu_counts;
670 SendStatisticsProxy::AdaptationSteps quality_counts;
671 quality_counts.num_framerate_reductions = absl::nullopt;
672 quality_counts.num_resolution_reductions = absl::nullopt;
673 statistics_proxy_->OnAdaptationChanged(
674 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
675 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700676 fake_clock_.AdvanceTimeMilliseconds(10000);
677
asapersson09f05612017-05-15 23:40:18 -0700678 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700679 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200680 quality_counts.num_framerate_reductions = 0;
681 statistics_proxy_->OnAdaptationChanged(
682 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
683 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700684 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200685 statistics_proxy_->OnAdaptationChanged(
686 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
687 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700688 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200689 statistics_proxy_->OnAdaptationChanged(
690 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
691 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700692 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200693 statistics_proxy_->OnAdaptationChanged(
694 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
695 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700696
asapersson09f05612017-05-15 23:40:18 -0700697 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200698 quality_counts.num_framerate_reductions = absl::nullopt;
699 statistics_proxy_->OnAdaptationChanged(
700 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
701 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700702 fake_clock_.AdvanceTimeMilliseconds(30000);
703
asapersson09f05612017-05-15 23:40:18 -0700704 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700705 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200706 quality_counts.num_resolution_reductions = 0;
707 statistics_proxy_->OnAdaptationChanged(
708 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
709 quality_counts);
710 statistics_proxy_->OnAdaptationChanged(
711 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
712 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700713 fake_clock_.AdvanceTimeMilliseconds(10000);
714
asapersson09f05612017-05-15 23:40:18 -0700715 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200716 quality_counts.num_resolution_reductions = absl::nullopt;
717 statistics_proxy_->OnAdaptationChanged(
718 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
719 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700720 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200721 statistics_proxy_->OnAdaptationChanged(
722 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
723 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700724 fake_clock_.AdvanceTimeMilliseconds(20000);
725
asapersson0944a802017-04-07 00:57:58 -0700726 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700727 statistics_proxy_.reset();
728 EXPECT_EQ(1,
729 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
730 EXPECT_EQ(
731 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
732}
733
asapersson0944a802017-04-07 00:57:58 -0700734TEST_F(SendStatisticsProxyTest,
735 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
736 // First RTP packet sent.
737 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700738
asapersson0944a802017-04-07 00:57:58 -0700739 // Suspend and resume video.
740 statistics_proxy_->OnSuspendChange(true);
741 fake_clock_.AdvanceTimeMilliseconds(5000);
742 statistics_proxy_->OnSuspendChange(false);
743
744 // Min runtime has passed but scaling not enabled.
745 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
746 statistics_proxy_.reset();
747 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
748 EXPECT_EQ(0,
749 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
750}
751
752TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
753 // First RTP packet sent.
754 UpdateDataCounters(kFirstSsrc);
755
asapersson09f05612017-05-15 23:40:18 -0700756 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200757 SendStatisticsProxy::AdaptationSteps cpu_counts;
758 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700759 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200760 statistics_proxy_->OnAdaptationChanged(
761 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
762 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700763 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200764 statistics_proxy_->OnAdaptationChanged(
765 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
766 quality_counts);
767 statistics_proxy_->OnAdaptationChanged(
768 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
769 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700770
771 // Suspend and resume video.
772 statistics_proxy_->OnSuspendChange(true);
773 fake_clock_.AdvanceTimeMilliseconds(30000);
774 statistics_proxy_->OnSuspendChange(false);
775
776 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200777 statistics_proxy_->OnAdaptationChanged(
778 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
779 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700780 fake_clock_.AdvanceTimeMilliseconds(10000);
781
782 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
783 statistics_proxy_.reset();
784 EXPECT_EQ(1,
785 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
786 EXPECT_EQ(
787 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
788}
789
790TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
791 // First RTP packet sent.
792 UpdateDataCounters(kFirstSsrc);
793
794 // Video not suspended.
795 statistics_proxy_->OnSuspendChange(false);
796 fake_clock_.AdvanceTimeMilliseconds(30000);
797
asapersson09f05612017-05-15 23:40:18 -0700798 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200799 SendStatisticsProxy::AdaptationSteps cpu_counts;
800 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700801 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200802 statistics_proxy_->OnAdaptationChanged(
803 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
804 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700805 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200806 statistics_proxy_->OnAdaptationChanged(
807 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
808 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700809
810 // Video not suspended, stats time already started.
811 statistics_proxy_->OnSuspendChange(false);
812 fake_clock_.AdvanceTimeMilliseconds(10000);
813
asapersson09f05612017-05-15 23:40:18 -0700814 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200815 cpu_counts.num_framerate_reductions = absl::nullopt;
816 cpu_counts.num_resolution_reductions = absl::nullopt;
817 statistics_proxy_->OnAdaptationChanged(
818 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
819 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700820 fake_clock_.AdvanceTimeMilliseconds(30000);
821
822 // Suspend and resume video, stats time not started when scaling not enabled.
823 statistics_proxy_->OnSuspendChange(true);
824 fake_clock_.AdvanceTimeMilliseconds(30000);
825 statistics_proxy_->OnSuspendChange(false);
826 fake_clock_.AdvanceTimeMilliseconds(30000);
827
asapersson09f05612017-05-15 23:40:18 -0700828 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700829 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200830 cpu_counts.num_framerate_reductions = 0;
831 cpu_counts.num_resolution_reductions = 0;
832 statistics_proxy_->OnAdaptationChanged(
833 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
834 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700835 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200836 statistics_proxy_->OnAdaptationChanged(
837 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
838 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700839
840 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
841 statistics_proxy_.reset();
842 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
843 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
844}
845
846TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
847 // First RTP packet sent.
848 UpdateDataCounters(kFirstSsrc);
849
850 // Video suspended.
851 statistics_proxy_->OnSuspendChange(true);
852
asapersson09f05612017-05-15 23:40:18 -0700853 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200854 SendStatisticsProxy::AdaptationSteps cpu_counts;
855 SendStatisticsProxy::AdaptationSteps quality_counts;
856 statistics_proxy_->OnAdaptationChanged(
857 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
858 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700859 fake_clock_.AdvanceTimeMilliseconds(10000);
860
861 // Resume video, stats time started.
862 // Adapt changes: 1, elapsed time: 10 sec.
863 statistics_proxy_->OnSuspendChange(false);
864 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200865 statistics_proxy_->OnAdaptationChanged(
866 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
867 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700868
869 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
870 statistics_proxy_.reset();
871 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
872 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
873}
874
875TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700876 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700877 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200878 SendStatisticsProxy::AdaptationSteps cpu_counts;
879 SendStatisticsProxy::AdaptationSteps quality_counts;
880 statistics_proxy_->OnAdaptationChanged(
881 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
882 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700883 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700884 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700885
asapersson0944a802017-04-07 00:57:58 -0700886 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700887 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200888 statistics_proxy_->OnAdaptationChanged(
889 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
890 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700891 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700892
asapersson0944a802017-04-07 00:57:58 -0700893 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700894 statistics_proxy_.reset();
895 EXPECT_EQ(1,
896 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
897 EXPECT_EQ(
898 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
899}
900
901TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700902 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200903 SendStatisticsProxy::AdaptationSteps cpu_counts;
904 SendStatisticsProxy::AdaptationSteps quality_counts;
905 statistics_proxy_->OnAdaptationChanged(
906 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
907 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700908 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200909 cpu_counts.num_framerate_reductions = absl::nullopt;
910 cpu_counts.num_resolution_reductions = absl::nullopt;
911 statistics_proxy_->OnAdaptationChanged(
912 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
913 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700914
915 // Send first packet, scaling disabled.
916 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700917 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700918 fake_clock_.AdvanceTimeMilliseconds(60000);
919
asapersson09f05612017-05-15 23:40:18 -0700920 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200921 cpu_counts.num_resolution_reductions = 0;
922 statistics_proxy_->OnAdaptationChanged(
923 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
924 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700925 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700926 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700927
asapersson0944a802017-04-07 00:57:58 -0700928 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700929 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200930 statistics_proxy_->OnAdaptationChanged(
931 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
932 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700933
asapersson0944a802017-04-07 00:57:58 -0700934 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700935 statistics_proxy_.reset();
936 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
937 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
938}
939
940TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700941 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700942 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200943 SendStatisticsProxy::AdaptationSteps cpu_counts;
944 SendStatisticsProxy::AdaptationSteps quality_counts;
945 quality_counts.num_framerate_reductions = absl::nullopt;
946 quality_counts.num_resolution_reductions = absl::nullopt;
947 statistics_proxy_->OnAdaptationChanged(
948 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
949 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700950
asapersson0944a802017-04-07 00:57:58 -0700951 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200952 statistics_proxy_->OnAdaptationChanged(
953 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
954 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700955 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200956 statistics_proxy_->OnAdaptationChanged(
957 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
958 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700959 fake_clock_.AdvanceTimeMilliseconds(9000);
960
961 // Switch content type, real-time stats should be updated.
962 VideoEncoderConfig config;
963 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +0200964 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -0700965 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
966 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
967 EXPECT_EQ(0,
968 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
969
asapersson0944a802017-04-07 00:57:58 -0700970 // First RTP packet sent, scaling enabled.
971 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200972 statistics_proxy_->OnAdaptationChanged(
973 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
974 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700975
asapersson0944a802017-04-07 00:57:58 -0700976 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200977 statistics_proxy_->OnAdaptationChanged(
978 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
979 quality_counts);
980 statistics_proxy_->OnAdaptationChanged(
981 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
982 quality_counts);
983 statistics_proxy_->OnAdaptationChanged(
984 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
985 quality_counts);
986 statistics_proxy_->OnAdaptationChanged(
987 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
988 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700989 fake_clock_.AdvanceTimeMilliseconds(120000);
990
991 statistics_proxy_.reset();
992 EXPECT_EQ(1, metrics::NumSamples(
993 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
994 EXPECT_EQ(1, metrics::NumEvents(
995 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
996 EXPECT_EQ(0, metrics::NumSamples(
997 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
998}
999
asapersson59bac1a2016-01-07 23:36:00 -08001000TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001001 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001002 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1003
Pera48ddb72016-09-29 11:48:50 +02001004 // No switch, stats should not be updated.
1005 VideoEncoderConfig config;
1006 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001007 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001008 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001009
1010 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001011 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001012 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001013 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001014}
1015
asapersson320e45a2016-11-29 01:40:35 -08001016TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1017 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1018 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001019
asapersson320e45a2016-11-29 01:40:35 -08001020 statistics_proxy_.reset();
1021 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1022 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1023 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1024 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1025}
1026
1027TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001028 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001029 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001030 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1031 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1032 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001033 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001034
1035 // Not enough samples, stats should not be updated.
1036 for (int i = 0; i < kMinSamples - 1; ++i) {
1037 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001038 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001039 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1040 }
Åsa Persson0122e842017-10-16 12:19:23 +02001041 SetUp(); // Reset stats proxy also causes histograms to be reported.
1042 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1043 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1044
1045 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001046 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001047 for (int i = 0; i < kMinSamples; ++i) {
1048 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001049 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001050 encoded_image._encodedWidth = kWidth;
1051 encoded_image._encodedHeight = kHeight;
1052 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1053 encoded_image._encodedWidth = kWidth / 2;
1054 encoded_image._encodedHeight = kHeight / 2;
1055 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1056 }
1057
asapersson320e45a2016-11-29 01:40:35 -08001058 statistics_proxy_.reset();
1059 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1060 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1061 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1062 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1063}
1064
1065TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1066 const int kFps = 20;
1067 const int kMinPeriodicSamples = 6;
1068 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1069 for (int i = 0; i <= frames; ++i) {
1070 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1071 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1072 }
1073 statistics_proxy_.reset();
1074 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1075 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1076}
1077
1078TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1079 EncodedImage encoded_image;
1080 const int kFps = 20;
1081 const int kMinPeriodicSamples = 6;
1082 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001083 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001084 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001085 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001086 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1087 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001088 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1089 }
1090 statistics_proxy_.reset();
1091 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1092 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1093}
1094
1095TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1096 const int kFps = 20;
1097 const int kSuspendTimeMs = 10000;
1098 const int kMinPeriodicSamples = 6;
1099 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1100 for (int i = 0; i < frames; ++i) {
1101 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1102 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1103 }
1104 // Suspend.
1105 statistics_proxy_->OnSuspendChange(true);
1106 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1107
1108 for (int i = 0; i < frames; ++i) {
1109 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1110 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1111 }
1112 // Suspended time interval should not affect the framerate.
1113 statistics_proxy_.reset();
1114 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1115 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1116}
1117
1118TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1119 EncodedImage encoded_image;
1120 const int kFps = 20;
1121 const int kSuspendTimeMs = 10000;
1122 const int kMinPeriodicSamples = 6;
1123 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001124 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001125 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001126 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001127 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1128 }
1129 // Suspend.
1130 statistics_proxy_->OnSuspendChange(true);
1131 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1132
Åsa Persson0122e842017-10-16 12:19:23 +02001133 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001134 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001135 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001136 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1137 }
1138 // Suspended time interval should not affect the framerate.
1139 statistics_proxy_.reset();
1140 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1141 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1142}
1143
asaperssonf4e44af2017-04-19 02:01:06 -07001144TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001145 SendStatisticsProxy::AdaptationSteps cpu_counts;
1146 SendStatisticsProxy::AdaptationSteps quality_counts;
1147 cpu_counts.num_resolution_reductions = absl::nullopt;
1148 statistics_proxy_->OnAdaptationChanged(
1149 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1150 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001151
1152 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1153 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1154
1155 statistics_proxy_.reset();
1156 EXPECT_EQ(0,
1157 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1158}
1159
1160TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001161 SendStatisticsProxy::AdaptationSteps cpu_counts;
1162 SendStatisticsProxy::AdaptationSteps quality_counts;
1163 cpu_counts.num_resolution_reductions = 0;
1164 statistics_proxy_->OnAdaptationChanged(
1165 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1166 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001167
perkj803d97f2016-11-01 11:45:46 -07001168 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1169 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1170
Niels Möller213618e2018-07-24 09:29:58 +02001171 cpu_counts.num_resolution_reductions = 1;
1172 statistics_proxy_->OnAdaptationChanged(
1173 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1174 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001175
1176 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1177 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1178
1179 statistics_proxy_.reset();
1180 EXPECT_EQ(1,
1181 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1182 EXPECT_EQ(
1183 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1184}
1185
asapersson4374a092016-07-27 00:39:09 -07001186TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1187 const int64_t kTimeSec = 3;
1188 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1189 statistics_proxy_.reset();
1190 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1191 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1192 kTimeSec));
1193}
1194
1195TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1196 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1197 statistics_proxy_.reset();
1198 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1199}
1200
asapersson66d4b372016-12-19 06:50:53 -08001201TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1202 // First RTP packet sent.
1203 UpdateDataCounters(kFirstSsrc);
1204
1205 // Min runtime has passed.
1206 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1207 statistics_proxy_.reset();
1208 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1209 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1210}
1211
1212TEST_F(SendStatisticsProxyTest,
1213 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1214 // First RTP packet sent.
1215 UpdateDataCounters(kFirstSsrc);
1216
1217 // Min runtime has not passed.
1218 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1219 statistics_proxy_.reset();
1220 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1221 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1222}
1223
1224TEST_F(SendStatisticsProxyTest,
1225 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1226 // First RTP packet not sent.
1227 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1228 statistics_proxy_.reset();
1229 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1230}
1231
1232TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1233 // First RTP packet sent and min runtime passed.
1234 UpdateDataCounters(kFirstSsrc);
1235
1236 // No change. Video: 10000 ms, paused: 0 ms (0%).
1237 statistics_proxy_->OnSetEncoderTargetRate(50000);
1238 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1239 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1240
1241 statistics_proxy_.reset();
1242 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1243 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1244 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1245 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1246}
1247
1248TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1249 // First RTP packet sent and min runtime passed.
1250 UpdateDataCounters(kFirstSsrc);
1251
1252 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1253 statistics_proxy_->OnSetEncoderTargetRate(50000);
1254 fake_clock_.AdvanceTimeMilliseconds(7000);
1255 statistics_proxy_->OnSetEncoderTargetRate(0);
1256 fake_clock_.AdvanceTimeMilliseconds(3000);
1257 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1258
1259 statistics_proxy_.reset();
1260 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1261 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1262 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1263 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1264}
1265
1266TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1267 // First RTP packet sent.
1268 UpdateDataCounters(kFirstSsrc);
1269
1270 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1271 statistics_proxy_->OnSetEncoderTargetRate(0);
1272 fake_clock_.AdvanceTimeMilliseconds(1000);
1273 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1274 fake_clock_.AdvanceTimeMilliseconds(7000);
1275 statistics_proxy_->OnSetEncoderTargetRate(60000);
1276 fake_clock_.AdvanceTimeMilliseconds(3000);
1277 statistics_proxy_->OnSetEncoderTargetRate(0);
1278 fake_clock_.AdvanceTimeMilliseconds(250);
1279 statistics_proxy_->OnSetEncoderTargetRate(0);
1280 fake_clock_.AdvanceTimeMilliseconds(750);
1281 statistics_proxy_->OnSetEncoderTargetRate(60000);
1282 fake_clock_.AdvanceTimeMilliseconds(5000);
1283 statistics_proxy_->OnSetEncoderTargetRate(50000);
1284 fake_clock_.AdvanceTimeMilliseconds(4000);
1285 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1286
1287 statistics_proxy_.reset();
1288 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1289 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1290 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1291 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1292}
1293
1294TEST_F(SendStatisticsProxyTest,
1295 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1296 // First RTP packet sent.
1297 UpdateDataCounters(kFirstSsrc);
1298 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1299
1300 // Min runtime has not passed.
1301 statistics_proxy_->OnSetEncoderTargetRate(50000);
1302 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1303 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1304
1305 statistics_proxy_.reset();
1306 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1307}
1308
asapersson118ef002016-03-31 00:00:19 -07001309TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001310 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001311 CodecSpecificInfo codec_info;
1312 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001313
perkj803d97f2016-11-01 11:45:46 -07001314 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001315 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001316 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001317 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001318 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001319 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001320 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001321 }
1322 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001323 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1324 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1325 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1326 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001327}
1328
1329TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1330 VideoSendStream::Config config(nullptr);
1331 config.rtp.ssrcs.push_back(kFirstSsrc);
1332 statistics_proxy_.reset(new SendStatisticsProxy(
1333 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1334
asapersson118ef002016-03-31 00:00:19 -07001335 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001336 CodecSpecificInfo codec_info;
1337 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001338
perkj803d97f2016-11-01 11:45:46 -07001339 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001340 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001341 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001342 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001343 }
1344 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001345 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1346 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001347}
1348
asapersson5265fed2016-04-18 02:58:47 -07001349TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001350 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001351 CodecSpecificInfo codec_info;
1352 codec_info.codecType = kVideoCodecVP9;
1353 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001354
perkj803d97f2016-11-01 11:45:46 -07001355 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001356 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001357 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001358 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001359 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001360 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001361 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001362 }
1363 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001364 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1365 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1366 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1367 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001368}
1369
1370TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1371 VideoSendStream::Config config(nullptr);
1372 config.rtp.ssrcs.push_back(kFirstSsrc);
1373 statistics_proxy_.reset(new SendStatisticsProxy(
1374 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1375
asapersson5265fed2016-04-18 02:58:47 -07001376 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001377 CodecSpecificInfo codec_info;
1378 codec_info.codecType = kVideoCodecVP9;
1379 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001380
perkj803d97f2016-11-01 11:45:46 -07001381 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001382 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001383 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001384 }
1385 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001386 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1387 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001388}
1389
asapersson827cab32016-11-02 09:08:47 -07001390TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1391 EncodedImage encoded_image;
1392 CodecSpecificInfo codec_info;
1393 codec_info.codecType = kVideoCodecH264;
1394
1395 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001396 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001397 encoded_image.qp_ = kQpIdx0;
1398 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001399 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001400 encoded_image.qp_ = kQpIdx1;
1401 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001402 }
1403 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001404 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1405 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1406 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1407 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001408}
1409
asapersson4ee70462016-10-31 04:05:12 -07001410TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001411 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1412 // Configure one stream.
1413 VideoEncoderConfig config;
1414 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1415 VideoStream stream1;
1416 stream1.width = kWidth;
1417 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001418 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001419
1420 const int64_t kMaxEncodedFrameWindowMs = 800;
1421 const int kFps = 20;
1422 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1423 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1424 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1425
1426 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001427 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001428 encoded_image._encodedWidth = kWidth;
1429 encoded_image._encodedHeight = kHeight;
1430 for (int i = 0; i < kMinSamples; ++i) {
1431 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001432 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1433 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001434 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001435 }
asapersson4ee70462016-10-31 04:05:12 -07001436
1437 // Histograms are updated when the statistics_proxy_ is deleted.
1438 statistics_proxy_.reset();
1439 EXPECT_EQ(0, metrics::NumSamples(
1440 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1441 EXPECT_EQ(0, metrics::NumSamples(
1442 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1443}
1444
1445TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001446 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1447 // Configure two streams.
1448 VideoEncoderConfig config;
1449 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1450 VideoStream stream1;
1451 stream1.width = kWidth / 2;
1452 stream1.height = kHeight / 2;
1453 VideoStream stream2;
1454 stream2.width = kWidth;
1455 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001456 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001457
1458 const int64_t kMaxEncodedFrameWindowMs = 800;
1459 const int kFps = 20;
1460 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1461 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1462 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1463
1464 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001465 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001466 for (int i = 0; i < kMinSamples; ++i) {
1467 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001468 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1469 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001470 encoded_image._encodedWidth = kWidth;
1471 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001472 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001473 encoded_image._encodedWidth = kWidth / 2;
1474 encoded_image._encodedHeight = kHeight / 2;
1475 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1476 }
asapersson4ee70462016-10-31 04:05:12 -07001477
1478 // Histograms are updated when the statistics_proxy_ is deleted.
1479 statistics_proxy_.reset();
1480 EXPECT_EQ(1, metrics::NumSamples(
1481 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1482 EXPECT_EQ(1, metrics::NumEvents(
1483 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1484 // No resolution disabled.
1485 EXPECT_EQ(0, metrics::NumSamples(
1486 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1487}
1488
1489TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001490 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1491 // Configure two streams.
1492 VideoEncoderConfig config;
1493 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1494 VideoStream stream1;
1495 stream1.width = kWidth / 2;
1496 stream1.height = kHeight / 2;
1497 VideoStream stream2;
1498 stream2.width = kWidth;
1499 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001500 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001501
1502 const int64_t kMaxEncodedFrameWindowMs = 800;
1503 const int kFps = 20;
1504 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1505 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1506 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1507
1508 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001509 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001510 encoded_image._encodedWidth = kWidth / 2;
1511 encoded_image._encodedHeight = kHeight / 2;
1512 for (int i = 0; i < kMinSamples; ++i) {
1513 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001514 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1515 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001516 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001517 }
asapersson4ee70462016-10-31 04:05:12 -07001518
1519 // Histograms are updated when the statistics_proxy_ is deleted.
1520 statistics_proxy_.reset();
1521 EXPECT_EQ(1, metrics::NumSamples(
1522 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1523 EXPECT_EQ(1, metrics::NumEvents(
1524 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001525 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001526 EXPECT_EQ(1, metrics::NumSamples(
1527 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001528 EXPECT_EQ(1, metrics::NumEvents(
1529 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001530}
1531
1532TEST_F(SendStatisticsProxyTest,
1533 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001534 SendStatisticsProxy::AdaptationSteps cpu_counts;
1535 SendStatisticsProxy::AdaptationSteps quality_counts;
1536 quality_counts.num_resolution_reductions = absl::nullopt;
1537 statistics_proxy_->OnAdaptationChanged(
1538 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1539 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001540 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001541 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001542 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001543 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001544
1545 // Histograms are updated when the statistics_proxy_ is deleted.
1546 statistics_proxy_.reset();
1547 EXPECT_EQ(
1548 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1549 EXPECT_EQ(0, metrics::NumSamples(
1550 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1551}
1552
1553TEST_F(SendStatisticsProxyTest,
1554 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001555 SendStatisticsProxy::AdaptationSteps cpu_counts;
1556 SendStatisticsProxy::AdaptationSteps quality_counts;
1557 quality_counts.num_resolution_reductions = 0;
1558 statistics_proxy_->OnAdaptationChanged(
1559 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1560 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001561 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001562 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001563 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001564 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001565
1566 // Histograms are updated when the statistics_proxy_ is deleted.
1567 statistics_proxy_.reset();
1568 EXPECT_EQ(
1569 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1570 EXPECT_EQ(1, metrics::NumEvents(
1571 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1572 // No resolution downscale.
1573 EXPECT_EQ(0, metrics::NumSamples(
1574 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1575}
1576
1577TEST_F(SendStatisticsProxyTest,
1578 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1579 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001580 SendStatisticsProxy::AdaptationSteps cpu_counts;
1581 SendStatisticsProxy::AdaptationSteps quality_counts;
1582 quality_counts.num_resolution_reductions = kDownscales;
1583 statistics_proxy_->OnAdaptationChanged(
1584 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1585 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001586 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001587 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001588 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001589 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001590 // Histograms are updated when the statistics_proxy_ is deleted.
1591 statistics_proxy_.reset();
1592 EXPECT_EQ(
1593 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1594 EXPECT_EQ(1, metrics::NumEvents(
1595 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1596 // Resolution downscales.
1597 EXPECT_EQ(1, metrics::NumSamples(
1598 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1599 EXPECT_EQ(
1600 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1601 kDownscales));
1602}
1603
1604TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1605 // Initially false.
1606 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001607
Åsa Perssonaa329e72017-12-15 15:54:44 +01001608 // Configure two streams.
1609 VideoEncoderConfig config;
1610 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1611 VideoStream stream1;
1612 stream1.width = kWidth / 2;
1613 stream1.height = kHeight / 2;
1614 VideoStream stream2;
1615 stream2.width = kWidth;
1616 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001617 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001618
1619 const int64_t kMaxEncodedFrameWindowMs = 800;
1620 const int kFps = 20;
1621 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1622 kFps * kMaxEncodedFrameWindowMs / 1000;
1623
1624 // One stream encoded.
1625 EncodedImage encoded_image;
1626 encoded_image._encodedWidth = kWidth / 2;
1627 encoded_image._encodedHeight = kHeight / 2;
1628 for (int i = 0; i < kMinSamples; ++i) {
1629 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001630 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1631 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001632 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1633 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1634 }
1635
1636 // First frame removed from EncodedFrameMap, stats updated.
1637 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001638 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08001639 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1640 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1641
Åsa Perssonaa329e72017-12-15 15:54:44 +01001642 // Two streams encoded.
1643 for (int i = 0; i < kMinSamples; ++i) {
1644 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001645 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1646 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001647 encoded_image._encodedWidth = kWidth;
1648 encoded_image._encodedHeight = kHeight;
1649 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1650 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1651 encoded_image._encodedWidth = kWidth / 2;
1652 encoded_image._encodedHeight = kHeight / 2;
1653 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1654 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1655 }
1656
1657 // First frame with two streams removed, expect no resolution limit.
1658 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001659 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1660 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001661 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1662 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001663
1664 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02001665 SendStatisticsProxy::AdaptationSteps cpu_counts;
1666 SendStatisticsProxy::AdaptationSteps quality_counts;
1667 quality_counts.num_resolution_reductions = 1;
1668 statistics_proxy_->OnAdaptationChanged(
1669 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1670 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001671 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1672 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1673}
1674
asapersson66d4b372016-12-19 06:50:53 -08001675TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1676 // Initially zero.
1677 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1678
1679 const int kBitrate = 100000;
1680 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1681 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1682
1683 statistics_proxy_->OnSetEncoderTargetRate(0);
1684 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1685}
1686
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001687TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001688 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001689 std::max(
1690 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1691 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1692 config_.rtp.rtx.ssrcs.end())) +
1693 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001694 // From RtcpStatisticsCallback.
1695 RtcpStatistics rtcp_stats;
1696 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001697 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001698
1699 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001700 uint32_t total = 0;
1701 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001702 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001703 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001704
1705 // From FrameCountObserver.
1706 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001707 FrameCounts frame_counts;
1708 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001709 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001710
1711 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1712 EXPECT_TRUE(stats.substreams.empty());
1713}
1714
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001715TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1716 static const int kEncodedWidth = 123;
1717 static const int kEncodedHeight = 81;
1718 EncodedImage encoded_image;
1719 encoded_image._encodedWidth = kEncodedWidth;
1720 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001721 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001722
kjellander02b3d272016-04-20 05:05:54 -07001723 CodecSpecificInfo codec_info;
1724 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001725
kjellander02b3d272016-04-20 05:05:54 -07001726 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001727 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001728 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001729
1730 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001731 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1732 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1733 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1734 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001735
1736 // Forward almost to timeout, this should not have removed stats.
1737 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1738 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001739 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1740 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001741
1742 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1743 // resolution still times out (no global timeout for all stats).
1744 RtcpStatistics rtcp_statistics;
1745 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1746 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1747
1748 // Report stats for second SSRC to make sure it's not outdated along with the
1749 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001750 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001751
1752 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1753 // reported, but substream 1 should.
1754 fake_clock_.AdvanceTimeMilliseconds(1);
1755 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001756 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1757 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1758 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1759 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001760}
1761
Peter Boström20f3f942015-05-15 11:33:39 +02001762TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1763 static const int kEncodedWidth = 123;
1764 static const int kEncodedHeight = 81;
1765 EncodedImage encoded_image;
1766 encoded_image._encodedWidth = kEncodedWidth;
1767 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001768 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02001769
kjellander02b3d272016-04-20 05:05:54 -07001770 CodecSpecificInfo codec_info;
1771 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02001772
kjellander02b3d272016-04-20 05:05:54 -07001773 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001774 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001775 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001776
1777 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1778 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1779 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1780 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1781 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1782 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1783}
1784
1785TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001786 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001787 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1788 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1789 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1790
1791 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1792
1793 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001794 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001795 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001796 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001797 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1798 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1799 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1800}
1801
sprang07fb9be2016-02-24 07:55:00 -08001802TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1803 RtcpPacketTypeCounterObserver* proxy =
1804 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1805 RtcpPacketTypeCounter counters;
1806 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1807 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1808 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1809
1810 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1811
1812 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1813 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1814 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1815 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1816 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1817
1818 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1819 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1820
1821 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001822 VideoEncoderConfig config;
1823 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001824 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001825
asapersson01d70a32016-05-20 06:29:46 -07001826 EXPECT_EQ(1,
1827 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1828 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1829 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1830 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001831 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1832
1833 const int kRate = 60 * 2; // Packets per minute with two streams.
1834
asapersson01d70a32016-05-20 06:29:46 -07001835 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1836 1 * kRate));
1837 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1838 2 * kRate));
1839 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1840 3 * kRate));
1841 EXPECT_EQ(
1842 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1843 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001844
1845 // New start time but same counter values.
1846 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1847 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1848
1849 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1850
1851 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1852 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1853 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1854 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1855 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1856
1857 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1858 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1859
1860 SetUp(); // Reset stats proxy also causes histograms to be reported.
1861
asapersson01d70a32016-05-20 06:29:46 -07001862 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001863 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001864 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001865 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001866 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001867 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1868 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001869 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001870 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1871
asapersson01d70a32016-05-20 06:29:46 -07001872 EXPECT_EQ(1, metrics::NumEvents(
1873 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1874 1 * kRate));
1875 EXPECT_EQ(1, metrics::NumEvents(
1876 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1877 2 * kRate));
1878 EXPECT_EQ(1, metrics::NumEvents(
1879 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1880 3 * kRate));
1881 EXPECT_EQ(1,
1882 metrics::NumEvents(
1883 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1884 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001885}
1886
asaperssona6a699a2016-11-25 03:52:46 -08001887TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1888 statistics_proxy_.reset(
1889 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1890 VideoEncoderConfig::ContentType::kRealtimeVideo));
1891
1892 StreamDataCountersCallback* proxy =
1893 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1894 StreamDataCounters counters;
1895 proxy->DataCountersUpdated(counters, kFirstSsrc);
1896 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1897
1898 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1899 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1900}
1901
1902TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1903 statistics_proxy_.reset(
1904 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1905 VideoEncoderConfig::ContentType::kRealtimeVideo));
1906
1907 StreamDataCountersCallback* proxy =
1908 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001909 StreamDataCounters counters;
1910 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001911
asapersson93e1e232017-02-06 05:18:35 -08001912 const int kMinRequiredPeriodSamples = 8;
1913 const int kPeriodIntervalMs = 2000;
1914 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1915 counters.transmitted.packets += 20;
1916 counters.transmitted.header_bytes += 500;
1917 counters.transmitted.padding_bytes += 1000;
1918 counters.transmitted.payload_bytes += 2000;
1919 counters.retransmitted.packets += 2;
1920 counters.retransmitted.header_bytes += 25;
1921 counters.retransmitted.padding_bytes += 100;
1922 counters.retransmitted.payload_bytes += 250;
1923 counters.fec = counters.retransmitted;
1924 rtx_counters.transmitted = counters.transmitted;
1925 // Advance one interval and update counters.
1926 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1927 proxy->DataCountersUpdated(counters, kFirstSsrc);
1928 proxy->DataCountersUpdated(counters, kSecondSsrc);
1929 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1930 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1931 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1932 }
asaperssona6a699a2016-11-25 03:52:46 -08001933
asaperssona6a699a2016-11-25 03:52:46 -08001934 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001935 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001936 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001937 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1938 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1939 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1940 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1941 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001942 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001943 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1944 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001945 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001946 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1947 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1948 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1949 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1950 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001951 EXPECT_EQ(1,
1952 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001953 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001954 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001955}
1956
Erik Språng22c2b482016-03-01 09:40:42 +01001957TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1958 StreamDataCountersCallback* proxy =
1959 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1960 StreamDataCounters counters;
1961 StreamDataCounters rtx_counters;
1962 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001963
asapersson93e1e232017-02-06 05:18:35 -08001964 const int kMinRequiredPeriodSamples = 8;
1965 const int kPeriodIntervalMs = 2000;
1966 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1967 counters.transmitted.packets += 20;
1968 counters.transmitted.header_bytes += 500;
1969 counters.transmitted.padding_bytes += 1000;
1970 counters.transmitted.payload_bytes += 2000;
1971 counters.retransmitted.packets += 2;
1972 counters.retransmitted.header_bytes += 25;
1973 counters.retransmitted.padding_bytes += 100;
1974 counters.retransmitted.payload_bytes += 250;
1975 counters.fec = counters.retransmitted;
1976 rtx_counters.transmitted = counters.transmitted;
1977 // Advance one interval and update counters.
1978 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1979 proxy->DataCountersUpdated(counters, kFirstSsrc);
1980 proxy->DataCountersUpdated(counters, kSecondSsrc);
1981 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1982 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1983 }
Erik Språng22c2b482016-03-01 09:40:42 +01001984
1985 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001986 VideoEncoderConfig config;
1987 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001988 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01001989
asapersson93e1e232017-02-06 05:18:35 -08001990 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001991 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001992 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1993 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1994 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1995 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1996 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001997 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001998 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1999 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002000 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002001 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2002 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2003 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2004 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2005 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002006 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002007 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002008 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002009 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002010
asapersson93e1e232017-02-06 05:18:35 -08002011 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002012 // Double counter values, this should result in the same counts as before but
2013 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002014 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2015 counters.transmitted.packets += 20;
2016 counters.transmitted.header_bytes += 500;
2017 counters.transmitted.padding_bytes += 1000;
2018 counters.transmitted.payload_bytes += 2000;
2019 counters.retransmitted.packets += 2;
2020 counters.retransmitted.header_bytes += 25;
2021 counters.retransmitted.padding_bytes += 100;
2022 counters.retransmitted.payload_bytes += 250;
2023 counters.fec = counters.retransmitted;
2024 rtx_counters.transmitted = counters.transmitted;
2025 // Advance one interval and update counters.
2026 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2027 proxy->DataCountersUpdated(counters, kFirstSsrc);
2028 proxy->DataCountersUpdated(counters, kSecondSsrc);
2029 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2030 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2031 }
Erik Språng22c2b482016-03-01 09:40:42 +01002032
asapersson93e1e232017-02-06 05:18:35 -08002033 // Reset stats proxy also causes histograms to be reported.
2034 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002035
asapersson93e1e232017-02-06 05:18:35 -08002036 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002037 EXPECT_EQ(1,
2038 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002039 EXPECT_EQ(
2040 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2041 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2042 EXPECT_EQ(
2043 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2044 EXPECT_EQ(1, metrics::NumEvents(
2045 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2046 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002047 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002048 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002049 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002050 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2051 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002052 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002053 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002054 EXPECT_EQ(1, metrics::NumEvents(
2055 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2056 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2057 EXPECT_EQ(
2058 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2059 EXPECT_EQ(1, metrics::NumEvents(
2060 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2061 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002062 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002063 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002064 EXPECT_EQ(1,
2065 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002066 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2067}
Erik Språng22c2b482016-03-01 09:40:42 +01002068
asapersson93e1e232017-02-06 05:18:35 -08002069TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2070 StreamDataCountersCallback* proxy =
2071 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2072 StreamDataCounters counters;
2073 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002074
asapersson93e1e232017-02-06 05:18:35 -08002075 const int kMinRequiredPeriodSamples = 8;
2076 const int kPeriodIntervalMs = 2000;
2077 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2078 counters.transmitted.packets += 20;
2079 counters.transmitted.header_bytes += 500;
2080 counters.transmitted.payload_bytes += 2000;
2081 counters.fec = counters.retransmitted;
2082 // Advance one interval and update counters.
2083 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2084 proxy->DataCountersUpdated(counters, kFirstSsrc);
2085 }
2086
2087 // RTX enabled. No data sent over RTX.
2088 statistics_proxy_.reset();
2089 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2090 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2091}
2092
2093TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2094 VideoSendStream::Config config(nullptr);
2095 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2096 statistics_proxy_.reset(new SendStatisticsProxy(
2097 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2098
2099 StreamDataCountersCallback* proxy =
2100 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2101 StreamDataCounters counters;
2102
2103 const int kMinRequiredPeriodSamples = 8;
2104 const int kPeriodIntervalMs = 2000;
2105 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2106 counters.transmitted.packets += 20;
2107 counters.transmitted.header_bytes += 500;
2108 counters.transmitted.payload_bytes += 2000;
2109 counters.fec = counters.retransmitted;
2110 // Advance one interval and update counters.
2111 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2112 proxy->DataCountersUpdated(counters, kFirstSsrc);
2113 }
2114
2115 // RTX not enabled.
2116 statistics_proxy_.reset();
2117 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2118}
2119
2120TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2121 StreamDataCountersCallback* proxy =
2122 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2123 StreamDataCounters counters;
2124 StreamDataCounters rtx_counters;
2125
2126 const int kMinRequiredPeriodSamples = 8;
2127 const int kPeriodIntervalMs = 2000;
2128 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2129 counters.transmitted.packets += 20;
2130 counters.transmitted.header_bytes += 500;
2131 counters.transmitted.payload_bytes += 2000;
2132 // Advance one interval and update counters.
2133 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2134 proxy->DataCountersUpdated(counters, kFirstSsrc);
2135 }
2136
2137 // FEC enabled. No FEC data sent.
2138 statistics_proxy_.reset();
2139 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2140 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2141}
2142
2143TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2144 VideoSendStream::Config config(nullptr);
2145 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2146 statistics_proxy_.reset(new SendStatisticsProxy(
2147 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2148
2149 StreamDataCountersCallback* proxy =
2150 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2151 StreamDataCounters counters;
2152
2153 const int kMinRequiredPeriodSamples = 8;
2154 const int kPeriodIntervalMs = 2000;
2155 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2156 counters.transmitted.packets += 20;
2157 counters.transmitted.header_bytes += 500;
2158 counters.transmitted.payload_bytes += 2000;
2159 counters.fec = counters.retransmitted;
2160 // Advance one interval and update counters.
2161 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2162 proxy->DataCountersUpdated(counters, kFirstSsrc);
2163 }
2164
2165 // FEC not enabled.
2166 statistics_proxy_.reset();
2167 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002168}
2169
asapersson8d75ac72017-09-15 06:41:15 -07002170TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
2171 const char* kName = "encoderName";
2172 EncodedImage encoded_image;
2173 CodecSpecificInfo codec_info;
2174 codec_info.codec_name = kName;
2175 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2176 EXPECT_STREQ(
2177 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str());
2178}
2179
2180class ForcedFallbackTest : public SendStatisticsProxyTest {
2181 public:
2182 explicit ForcedFallbackTest(const std::string& field_trials)
2183 : SendStatisticsProxyTest(field_trials) {
2184 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002185 codec_info_.codecSpecific.VP8.temporalIdx = 0;
2186 codec_info_.codec_name = "fake_codec";
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002187 encoded_image_._encodedWidth = kWidth;
2188 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002189 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002190 }
2191
2192 ~ForcedFallbackTest() override {}
2193
2194 protected:
2195 void InsertEncodedFrames(int num_frames, int interval_ms) {
2196 // First frame is not updating stats, insert initial frame.
2197 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2198 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2199 }
2200 for (int i = 0; i < num_frames; ++i) {
2201 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2202 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2203 }
2204 // Add frame to include last time interval.
2205 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2206 }
2207
2208 EncodedImage encoded_image_;
2209 CodecSpecificInfo codec_info_;
2210 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2211 const int kFrameIntervalMs = 1000;
2212 const int kMinFrames = 20; // Min run time 20 sec.
2213};
2214
2215class ForcedFallbackDisabled : public ForcedFallbackTest {
2216 public:
2217 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002218 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2219 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002220};
2221
2222class ForcedFallbackEnabled : public ForcedFallbackTest {
2223 public:
2224 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002225 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2226 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002227};
2228
2229TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2230 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2231 statistics_proxy_.reset();
2232 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2233 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2234}
2235
2236TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2237 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002238 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002239 statistics_proxy_.reset();
2240 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2241 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2242 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2243 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2244}
2245
2246TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2247 codec_info_.codecType = kVideoCodecVP9;
2248 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2249 statistics_proxy_.reset();
2250 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2251 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2252}
2253
2254TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2255 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2256 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2257 statistics_proxy_.reset();
2258 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2259 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2260}
2261
2262TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002263 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002264 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2265 statistics_proxy_.reset();
2266 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2267 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2268}
2269
2270TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2271 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2272 statistics_proxy_.reset();
2273 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2274 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2275}
2276
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002277TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2278 InsertEncodedFrames(1, kFrameIntervalMs);
2279 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2280}
2281
2282TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2283 InsertEncodedFrames(1, kFrameIntervalMs);
2284 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2285}
2286
2287TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
2288 codec_info_.codec_name = "libvpx";
2289 InsertEncodedFrames(1, kFrameIntervalMs);
2290 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2291}
2292
2293TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2294 encoded_image_._encodedWidth = kWidth + 1;
2295 InsertEncodedFrames(1, kFrameIntervalMs);
2296 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2297}
2298
2299TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
2300 codec_info_.codec_name = "libvpx";
2301 InsertEncodedFrames(1, kFrameIntervalMs);
2302 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2303}
2304
2305TEST_F(ForcedFallbackDisabled,
2306 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2307 encoded_image_._encodedWidth = kWidth + 1;
2308 statistics_proxy_->OnMinPixelLimitReached();
2309 InsertEncodedFrames(1, kFrameIntervalMs);
2310 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2311}
2312
asapersson8d75ac72017-09-15 06:41:15 -07002313TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2314 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002315 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002316 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002317 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002318 codec_info_.codec_name = "libvpx";
2319 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002320 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002321
2322 statistics_proxy_.reset();
2323 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2324 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2325 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2326 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2327}
2328
2329TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2330 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2331 const int kMaxFrameDiffMs = 2000;
2332
2333 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2334 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002335 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002336 codec_info_.codec_name = "libvpx";
2337 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002338 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002339 codec_info_.codec_name = "notlibvpx";
2340 InsertEncodedFrames(20, 1000);
2341 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2342 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002343 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002344 codec_info_.codec_name = "notlibvpx2";
2345 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002346 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002347 codec_info_.codec_name = "libvpx";
2348 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002349 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002350
2351 statistics_proxy_.reset();
2352 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2353 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2354 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2355 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2356}
2357
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002358TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2359 encoded_image_._encodedWidth = kWidth + 1;
asapersson8d75ac72017-09-15 06:41:15 -07002360 codec_info_.codec_name = "libvpx";
2361 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2362
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002363 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002364 statistics_proxy_.reset();
2365 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2366 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2367}
2368
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002369TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2370 encoded_image_._encodedWidth = kWidth;
asapersson8d75ac72017-09-15 06:41:15 -07002371 codec_info_.codec_name = "libvpx";
2372 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2373
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002374 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002375 statistics_proxy_.reset();
2376 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2377 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2378}
2379
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002380} // namespace webrtc