blob: ded7fedc5efb9f06a7c6764774699a937b0c0255 [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
Steve Antonbd631a02019-03-28 10:51:27 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 10:51:27 -070019#include "absl/algorithm/container.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070021#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000023
24namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070025namespace {
26const uint32_t kFirstSsrc = 17;
27const uint32_t kSecondSsrc = 42;
28const uint32_t kFirstRtxSsrc = 18;
29const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080030const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080031const int kFpsPeriodicIntervalMs = 2000;
32const int kWidth = 640;
33const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070034const int kQpIdx0 = 21;
35const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010036const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080037const CodecSpecificInfo kDefaultCodecInfo = []() {
38 CodecSpecificInfo codec_info;
39 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080040 return codec_info;
41}();
asapersson5265fed2016-04-18 02:58:47 -070042} // namespace
sprang07fb9be2016-02-24 07:55:00 -080043
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000044class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000045 public:
asapersson8d75ac72017-09-15 06:41:15 -070046 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
47 explicit SendStatisticsProxyTest(const std::string& field_trials)
48 : override_field_trials_(field_trials),
49 fake_clock_(1234),
50 config_(GetTestConfig()),
51 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070052 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000053 virtual ~SendStatisticsProxyTest() {}
54
55 protected:
56 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070057 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080058 statistics_proxy_.reset(new SendStatisticsProxy(
59 &fake_clock_, GetTestConfig(),
60 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000061 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070062 for (const auto& ssrc : config_.rtp.ssrcs)
63 expected_.substreams[ssrc].is_rtx = false;
64 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
65 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000066 }
67
68 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070069 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080070 config.rtp.ssrcs.push_back(kFirstSsrc);
71 config.rtp.ssrcs.push_back(kSecondSsrc);
72 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
73 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070074 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000075 return config;
76 }
77
asaperssona6a699a2016-11-25 03:52:46 -080078 VideoSendStream::Config GetTestConfigWithFlexFec() {
79 VideoSendStream::Config config(nullptr);
80 config.rtp.ssrcs.push_back(kFirstSsrc);
81 config.rtp.ssrcs.push_back(kSecondSsrc);
82 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
83 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080084 config.rtp.flexfec.payload_type = 50;
85 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080086 return config;
87 }
88
89 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
90 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
91 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
92 stats.substreams.find(ssrc);
93 EXPECT_NE(it, stats.substreams.end());
94 return it->second;
95 }
96
asapersson66d4b372016-12-19 06:50:53 -080097 void UpdateDataCounters(uint32_t ssrc) {
98 StreamDataCountersCallback* proxy =
99 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
100 StreamDataCounters counters;
101 proxy->DataCountersUpdated(counters, ssrc);
102 }
103
sprang@webrtc.org09315702014-02-07 12:06:29 +0000104 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000105 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
106 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000107 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000108 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000109
110 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000111 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000112 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000113 it != one.substreams.end(); ++it) {
114 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
115 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000116 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000117 const VideoSendStream::StreamStats& a = it->second;
118 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000119
asapersson2e5cfcd2016-08-11 08:41:18 -0700120 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000121 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
122 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000123 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000124 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
125 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000126
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000127 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
128 b.rtp_stats.transmitted.payload_bytes);
129 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
130 b.rtp_stats.transmitted.header_bytes);
131 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
132 b.rtp_stats.transmitted.padding_bytes);
133 EXPECT_EQ(a.rtp_stats.transmitted.packets,
134 b.rtp_stats.transmitted.packets);
135 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
136 b.rtp_stats.retransmitted.packets);
137 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000138
139 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700140 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
141 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
142 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000143 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
144 }
145 }
146
asapersson8d75ac72017-09-15 06:41:15 -0700147 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000148 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800149 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000150 VideoSendStream::Config config_;
151 int avg_delay_ms_;
152 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000153 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000154 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
155 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156};
157
158TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
159 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700160 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000161 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000162
163 // Add statistics with some arbitrary, but unique, numbers.
164 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700165 ssrc_stats.rtcp_stats.packets_lost = offset;
166 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000167 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
168 ssrc_stats.rtcp_stats.jitter = offset + 3;
169 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
170 }
asapersson35151f32016-05-02 23:44:01 -0700171 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000172 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000174 // Add statistics with some arbitrary, but unique, numbers.
175 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700176 ssrc_stats.rtcp_stats.packets_lost = offset;
177 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000178 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
179 ssrc_stats.rtcp_stats.jitter = offset + 3;
180 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
181 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000183 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184}
185
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000186TEST_F(SendStatisticsProxyTest, Suspended) {
187 // Verify that the value is false by default.
188 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
189
190 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200191 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000192 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
193
194 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200195 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000196 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
197}
198
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000199TEST_F(SendStatisticsProxyTest, FrameCounts) {
200 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700201 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000202 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000203 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
204 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000205 FrameCounts frame_counts;
206 frame_counts.key_frames = offset;
207 frame_counts.delta_frames = offset + 1;
208 stats.frame_counts = frame_counts;
209 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000210 }
asapersson35151f32016-05-02 23:44:01 -0700211 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000212 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000213 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
214 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000215 FrameCounts frame_counts;
216 frame_counts.key_frames = offset;
217 frame_counts.delta_frames = offset + 1;
218 stats.frame_counts = frame_counts;
219 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000220 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000221
222 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000223 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224}
225
226TEST_F(SendStatisticsProxyTest, DataCounters) {
227 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700228 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000229 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
230 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000231 size_t offset = ssrc * sizeof(StreamDataCounters);
232 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000233 counters.transmitted.payload_bytes = offset;
234 counters.transmitted.header_bytes = offset + 1;
235 counters.fec.packets = offset_uint32 + 2;
236 counters.transmitted.padding_bytes = offset + 3;
237 counters.retransmitted.packets = offset_uint32 + 4;
238 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000239 callback->DataCountersUpdated(counters, ssrc);
240 }
asapersson35151f32016-05-02 23:44:01 -0700241 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000242 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
243 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000244 size_t offset = ssrc * sizeof(StreamDataCounters);
245 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000246 counters.transmitted.payload_bytes = offset;
247 counters.transmitted.header_bytes = offset + 1;
248 counters.fec.packets = offset_uint32 + 2;
249 counters.transmitted.padding_bytes = offset + 3;
250 counters.retransmitted.packets = offset_uint32 + 4;
251 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000252 callback->DataCountersUpdated(counters, ssrc);
253 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000254
255 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000256 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000257}
258
259TEST_F(SendStatisticsProxyTest, Bitrate) {
260 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700261 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700262 uint32_t total;
263 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000264 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700265 total = ssrc;
266 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000267 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700268 expected_.substreams[ssrc].total_bitrate_bps = total;
269 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000270 }
asapersson35151f32016-05-02 23:44:01 -0700271 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700272 uint32_t total;
273 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000274 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700275 total = ssrc;
276 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000277 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700278 expected_.substreams[ssrc].total_bitrate_bps = total;
279 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000281
282 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000283 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000284}
285
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000286TEST_F(SendStatisticsProxyTest, SendSideDelay) {
287 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700288 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000289 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
290 // stream.
291 int avg_delay_ms = ssrc;
292 int max_delay_ms = ssrc + 1;
293 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
294 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
295 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
296 }
asapersson35151f32016-05-02 23:44:01 -0700297 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000298 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
299 // stream.
300 int avg_delay_ms = ssrc;
301 int max_delay_ms = ssrc + 1;
302 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
303 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
304 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
305 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000306 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000307 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000308}
309
Peter Boströme4499152016-02-05 11:13:28 +0100310TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800311 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200312 int encode_usage_percent = 80;
313 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
314 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800315
316 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
317 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200318 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800319}
320
Henrik Boström5684af52019-04-02 15:05:21 +0200321TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
322 const int kEncodeUsagePercent = 0; // Don't care for this test.
323 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
324 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
325 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
326 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
327 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
328}
329
sakal43536c32016-10-24 01:46:43 -0700330TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
331 EncodedImage encoded_image;
332 CodecSpecificInfo codec_info;
333 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
334 for (uint32_t i = 1; i <= 3; ++i) {
335 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
336 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
337 }
338}
339
sakal87da4042016-10-31 06:53:47 -0700340TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
341 EncodedImage encoded_image;
342 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200343 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700344 encoded_image.qp_ = 3;
345 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100346 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700347 encoded_image.qp_ = 127;
348 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100349 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700350}
351
352TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
353 EncodedImage encoded_image;
354 CodecSpecificInfo codec_info;
355 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200356 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700357 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200358 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700359}
360
asapersson09f05612017-05-15 23:40:18 -0700361TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200362 SendStatisticsProxy::AdaptationSteps cpu_counts;
363 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700364 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700365 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200366 cpu_counts.num_framerate_reductions = 1;
367 cpu_counts.num_resolution_reductions = 0;
368 statistics_proxy_->OnAdaptationChanged(
369 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
370 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700371 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700372 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200373 cpu_counts.num_framerate_reductions = 0;
374 cpu_counts.num_resolution_reductions = 1;
375 statistics_proxy_->OnAdaptationChanged(
376 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
377 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700378 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700379 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200380 cpu_counts.num_framerate_reductions = 1;
381 cpu_counts.num_resolution_reductions = absl::nullopt;
382 statistics_proxy_->OnAdaptationChanged(
383 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
384 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700385 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700386 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200387 cpu_counts.num_framerate_reductions = absl::nullopt;
388 cpu_counts.num_resolution_reductions = absl::nullopt;
389 statistics_proxy_->OnAdaptationChanged(
390 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
391 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700392 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
393 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
394}
395
396TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200397 SendStatisticsProxy::AdaptationSteps cpu_counts;
398 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700399 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
400 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200401 quality_counts.num_framerate_reductions = 1;
402 quality_counts.num_resolution_reductions = 0;
403 statistics_proxy_->OnAdaptationChanged(
404 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
405 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700406 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
407 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200408 quality_counts.num_framerate_reductions = 0;
409 quality_counts.num_resolution_reductions = 1;
410 statistics_proxy_->OnAdaptationChanged(
411 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
412 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700413 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
414 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200415 quality_counts.num_framerate_reductions = 1;
416 quality_counts.num_resolution_reductions = absl::nullopt;
417 statistics_proxy_->OnAdaptationChanged(
418 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
419 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700420 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
421 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200422 quality_counts.num_framerate_reductions = absl::nullopt;
423 quality_counts.num_resolution_reductions = absl::nullopt;
424 statistics_proxy_->OnAdaptationChanged(
425 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
426 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700427 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
428 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
429}
430
431TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200432 SendStatisticsProxy::AdaptationSteps cpu_counts;
433 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700434 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
435
Niels Möller213618e2018-07-24 09:29:58 +0200436 cpu_counts.num_resolution_reductions = 1;
437 statistics_proxy_->OnAdaptationChanged(
438 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
439 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700440 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700441 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
442 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
443
Niels Möller213618e2018-07-24 09:29:58 +0200444 cpu_counts.num_resolution_reductions = 2;
445 statistics_proxy_->OnAdaptationChanged(
446 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
447 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700448 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
449 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700450 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700451 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700452}
453
asapersson09f05612017-05-15 23:40:18 -0700454TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200455 SendStatisticsProxy::AdaptationSteps cpu_counts;
456 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700457 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
458
Niels Möller213618e2018-07-24 09:29:58 +0200459 quality_counts.num_framerate_reductions = 1;
460 statistics_proxy_->OnAdaptationChanged(
461 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
462 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700463 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
464 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700465 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
466
Niels Möller213618e2018-07-24 09:29:58 +0200467 quality_counts.num_framerate_reductions = 0;
468 statistics_proxy_->OnAdaptationChanged(
469 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
470 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700471 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700472 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700473 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
474 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700475}
476
asapersson09f05612017-05-15 23:40:18 -0700477TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700478 // First RTP packet sent.
479 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700480 // Min runtime has passed.
481 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
482 statistics_proxy_.reset();
483 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
484 EXPECT_EQ(0,
485 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
486}
487
488TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700489 // First RTP packet sent.
490 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700491 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200492 SendStatisticsProxy::AdaptationSteps cpu_counts;
493 SendStatisticsProxy::AdaptationSteps quality_counts;
494 statistics_proxy_->OnAdaptationChanged(
495 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
496 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700497 // Min runtime has not passed.
498 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
499 statistics_proxy_.reset();
500 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
501 EXPECT_EQ(0,
502 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
503}
504
asapersson09f05612017-05-15 23:40:18 -0700505TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700506 // First RTP packet sent.
507 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700508 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200509 SendStatisticsProxy::AdaptationSteps cpu_counts;
510 SendStatisticsProxy::AdaptationSteps quality_counts;
511 statistics_proxy_->OnAdaptationChanged(
512 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
513 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700514 // Min runtime has passed.
515 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
516 statistics_proxy_.reset();
517 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
518 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700519 EXPECT_EQ(1,
520 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
521 EXPECT_EQ(
522 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
523}
524
525TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700526 // First RTP packet sent.
527 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700528 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200529 SendStatisticsProxy::AdaptationSteps cpu_counts;
530 SendStatisticsProxy::AdaptationSteps quality_counts;
531 statistics_proxy_->OnAdaptationChanged(
532 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
533 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700534 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200535 statistics_proxy_->OnAdaptationChanged(
536 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
537 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700538 fake_clock_.AdvanceTimeMilliseconds(10000);
539 statistics_proxy_.reset();
540 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
541 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
542}
543
Åsa Persson875841d2018-01-08 08:49:53 +0100544TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
545 // First RTP packet sent.
546 UpdateDataCounters(kFirstSsrc);
547 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200548 SendStatisticsProxy::AdaptationSteps cpu_counts;
549 SendStatisticsProxy::AdaptationSteps quality_counts;
550 statistics_proxy_->OnAdaptationChanged(
551 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
552 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100553 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200554 statistics_proxy_->OnAdaptationChanged(
555 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
556 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100557 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
558 fake_clock_.AdvanceTimeMilliseconds(10000);
559 statistics_proxy_.reset();
560 EXPECT_EQ(1,
561 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
562 EXPECT_EQ(
563 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
564}
565
566TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
567 // First RTP packet sent.
568 UpdateDataCounters(kFirstSsrc);
569 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200570 SendStatisticsProxy::AdaptationSteps cpu_counts;
571 SendStatisticsProxy::AdaptationSteps quality_counts;
572 statistics_proxy_->OnAdaptationChanged(
573 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
574 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100575 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200576 quality_counts.num_resolution_reductions = 1;
577 statistics_proxy_->OnAdaptationChanged(
578 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
579 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100580 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200581 quality_counts.num_resolution_reductions = 2;
582 statistics_proxy_->OnAdaptationChanged(
583 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
584 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100585 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200586 quality_counts.num_resolution_reductions = 3;
587 statistics_proxy_->OnAdaptationChanged(
588 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
589 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100590 fake_clock_.AdvanceTimeMilliseconds(10000);
591 statistics_proxy_.reset();
592 EXPECT_EQ(1,
593 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
594 EXPECT_EQ(
595 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
596}
597
598TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
599 // First RTP packet sent.
600 UpdateDataCounters(kFirstSsrc);
601 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200602 SendStatisticsProxy::AdaptationSteps cpu_counts;
603 SendStatisticsProxy::AdaptationSteps quality_counts;
604 statistics_proxy_->OnAdaptationChanged(
605 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
606 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100607 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200608 statistics_proxy_->OnAdaptationChanged(
609 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
610 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100611 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
612 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
613 fake_clock_.AdvanceTimeMilliseconds(10000);
614 statistics_proxy_.reset();
615 EXPECT_EQ(1,
616 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
617 EXPECT_EQ(
618 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
619}
620
621TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
622 // First RTP packet sent.
623 UpdateDataCounters(kFirstSsrc);
624 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200625 SendStatisticsProxy::AdaptationSteps cpu_counts;
626 SendStatisticsProxy::AdaptationSteps quality_counts;
627 statistics_proxy_->OnAdaptationChanged(
628 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
629 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100630 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200631 quality_counts.num_resolution_reductions = 1;
632 statistics_proxy_->OnAdaptationChanged(
633 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
634 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100635 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200636 quality_counts.num_resolution_reductions = 2;
637 statistics_proxy_->OnAdaptationChanged(
638 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
639 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100640 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200641 quality_counts.num_resolution_reductions = 3;
642 statistics_proxy_->OnAdaptationChanged(
643 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
644 quality_counts);
645 quality_counts.num_framerate_reductions = 1;
646 statistics_proxy_->OnAdaptationChanged(
647 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
648 quality_counts);
649 quality_counts.num_framerate_reductions = 0;
650 statistics_proxy_->OnAdaptationChanged(
651 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
652 quality_counts);
653 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
654 statistics_proxy_->OnAdaptationChanged(
655 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
656 quality_counts);
657 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
658 statistics_proxy_->OnAdaptationChanged(
659 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
660 quality_counts);
661 quality_counts.num_resolution_reductions = 0;
662 statistics_proxy_->OnAdaptationChanged(
663 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
664 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100665
666 fake_clock_.AdvanceTimeMilliseconds(10000);
667 statistics_proxy_.reset();
668 EXPECT_EQ(1,
669 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
670 EXPECT_EQ(
671 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
672}
673
asapersson6eca98b2017-04-04 23:40:50 -0700674TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700675 // First RTP packet sent.
676 UpdateDataCounters(kFirstSsrc);
677
asapersson09f05612017-05-15 23:40:18 -0700678 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200679 SendStatisticsProxy::AdaptationSteps cpu_counts;
680 SendStatisticsProxy::AdaptationSteps quality_counts;
681 quality_counts.num_framerate_reductions = absl::nullopt;
682 quality_counts.num_resolution_reductions = absl::nullopt;
683 statistics_proxy_->OnAdaptationChanged(
684 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
685 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700686 fake_clock_.AdvanceTimeMilliseconds(10000);
687
asapersson09f05612017-05-15 23:40:18 -0700688 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700689 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200690 quality_counts.num_framerate_reductions = 0;
691 statistics_proxy_->OnAdaptationChanged(
692 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
693 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700694 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200695 statistics_proxy_->OnAdaptationChanged(
696 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
697 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700698 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200699 statistics_proxy_->OnAdaptationChanged(
700 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
701 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700702 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200703 statistics_proxy_->OnAdaptationChanged(
704 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
705 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700706
asapersson09f05612017-05-15 23:40:18 -0700707 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200708 quality_counts.num_framerate_reductions = absl::nullopt;
709 statistics_proxy_->OnAdaptationChanged(
710 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
711 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700712 fake_clock_.AdvanceTimeMilliseconds(30000);
713
asapersson09f05612017-05-15 23:40:18 -0700714 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700715 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200716 quality_counts.num_resolution_reductions = 0;
717 statistics_proxy_->OnAdaptationChanged(
718 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
719 quality_counts);
720 statistics_proxy_->OnAdaptationChanged(
721 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
722 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700723 fake_clock_.AdvanceTimeMilliseconds(10000);
724
asapersson09f05612017-05-15 23:40:18 -0700725 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200726 quality_counts.num_resolution_reductions = absl::nullopt;
727 statistics_proxy_->OnAdaptationChanged(
728 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
729 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700730 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200731 statistics_proxy_->OnAdaptationChanged(
732 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
733 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700734 fake_clock_.AdvanceTimeMilliseconds(20000);
735
asapersson0944a802017-04-07 00:57:58 -0700736 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700737 statistics_proxy_.reset();
738 EXPECT_EQ(1,
739 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
740 EXPECT_EQ(
741 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
742}
743
asapersson0944a802017-04-07 00:57:58 -0700744TEST_F(SendStatisticsProxyTest,
745 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
746 // First RTP packet sent.
747 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700748
asapersson0944a802017-04-07 00:57:58 -0700749 // Suspend and resume video.
750 statistics_proxy_->OnSuspendChange(true);
751 fake_clock_.AdvanceTimeMilliseconds(5000);
752 statistics_proxy_->OnSuspendChange(false);
753
754 // Min runtime has passed but scaling not enabled.
755 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
756 statistics_proxy_.reset();
757 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
758 EXPECT_EQ(0,
759 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
760}
761
762TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
763 // First RTP packet sent.
764 UpdateDataCounters(kFirstSsrc);
765
asapersson09f05612017-05-15 23:40:18 -0700766 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200767 SendStatisticsProxy::AdaptationSteps cpu_counts;
768 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700769 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200770 statistics_proxy_->OnAdaptationChanged(
771 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
772 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700773 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200774 statistics_proxy_->OnAdaptationChanged(
775 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
776 quality_counts);
777 statistics_proxy_->OnAdaptationChanged(
778 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
779 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700780
781 // Suspend and resume video.
782 statistics_proxy_->OnSuspendChange(true);
783 fake_clock_.AdvanceTimeMilliseconds(30000);
784 statistics_proxy_->OnSuspendChange(false);
785
786 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200787 statistics_proxy_->OnAdaptationChanged(
788 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
789 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700790 fake_clock_.AdvanceTimeMilliseconds(10000);
791
792 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
793 statistics_proxy_.reset();
794 EXPECT_EQ(1,
795 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
796 EXPECT_EQ(
797 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
798}
799
800TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
801 // First RTP packet sent.
802 UpdateDataCounters(kFirstSsrc);
803
804 // Video not suspended.
805 statistics_proxy_->OnSuspendChange(false);
806 fake_clock_.AdvanceTimeMilliseconds(30000);
807
asapersson09f05612017-05-15 23:40:18 -0700808 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200809 SendStatisticsProxy::AdaptationSteps cpu_counts;
810 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700811 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200812 statistics_proxy_->OnAdaptationChanged(
813 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
814 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700815 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200816 statistics_proxy_->OnAdaptationChanged(
817 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
818 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700819
820 // Video not suspended, stats time already started.
821 statistics_proxy_->OnSuspendChange(false);
822 fake_clock_.AdvanceTimeMilliseconds(10000);
823
asapersson09f05612017-05-15 23:40:18 -0700824 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200825 cpu_counts.num_framerate_reductions = absl::nullopt;
826 cpu_counts.num_resolution_reductions = absl::nullopt;
827 statistics_proxy_->OnAdaptationChanged(
828 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
829 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700830 fake_clock_.AdvanceTimeMilliseconds(30000);
831
832 // Suspend and resume video, stats time not started when scaling not enabled.
833 statistics_proxy_->OnSuspendChange(true);
834 fake_clock_.AdvanceTimeMilliseconds(30000);
835 statistics_proxy_->OnSuspendChange(false);
836 fake_clock_.AdvanceTimeMilliseconds(30000);
837
asapersson09f05612017-05-15 23:40:18 -0700838 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700839 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200840 cpu_counts.num_framerate_reductions = 0;
841 cpu_counts.num_resolution_reductions = 0;
842 statistics_proxy_->OnAdaptationChanged(
843 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
844 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700845 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200846 statistics_proxy_->OnAdaptationChanged(
847 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
848 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700849
850 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
851 statistics_proxy_.reset();
852 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
853 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
854}
855
856TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
857 // First RTP packet sent.
858 UpdateDataCounters(kFirstSsrc);
859
860 // Video suspended.
861 statistics_proxy_->OnSuspendChange(true);
862
asapersson09f05612017-05-15 23:40:18 -0700863 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200864 SendStatisticsProxy::AdaptationSteps cpu_counts;
865 SendStatisticsProxy::AdaptationSteps quality_counts;
866 statistics_proxy_->OnAdaptationChanged(
867 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
868 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700869 fake_clock_.AdvanceTimeMilliseconds(10000);
870
871 // Resume video, stats time started.
872 // Adapt changes: 1, elapsed time: 10 sec.
873 statistics_proxy_->OnSuspendChange(false);
874 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200875 statistics_proxy_->OnAdaptationChanged(
876 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
877 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700878
879 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
880 statistics_proxy_.reset();
881 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
882 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
883}
884
885TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700886 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700887 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200888 SendStatisticsProxy::AdaptationSteps cpu_counts;
889 SendStatisticsProxy::AdaptationSteps quality_counts;
890 statistics_proxy_->OnAdaptationChanged(
891 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
892 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700893 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700894 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700895
asapersson0944a802017-04-07 00:57:58 -0700896 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700897 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200898 statistics_proxy_->OnAdaptationChanged(
899 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
900 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700901 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700902
asapersson0944a802017-04-07 00:57:58 -0700903 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700904 statistics_proxy_.reset();
905 EXPECT_EQ(1,
906 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
907 EXPECT_EQ(
908 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
909}
910
911TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700912 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200913 SendStatisticsProxy::AdaptationSteps cpu_counts;
914 SendStatisticsProxy::AdaptationSteps quality_counts;
915 statistics_proxy_->OnAdaptationChanged(
916 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
917 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700918 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200919 cpu_counts.num_framerate_reductions = absl::nullopt;
920 cpu_counts.num_resolution_reductions = absl::nullopt;
921 statistics_proxy_->OnAdaptationChanged(
922 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
923 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700924
925 // Send first packet, scaling disabled.
926 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700927 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700928 fake_clock_.AdvanceTimeMilliseconds(60000);
929
asapersson09f05612017-05-15 23:40:18 -0700930 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200931 cpu_counts.num_resolution_reductions = 0;
932 statistics_proxy_->OnAdaptationChanged(
933 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
934 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700935 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700936 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700937
asapersson0944a802017-04-07 00:57:58 -0700938 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700939 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200940 statistics_proxy_->OnAdaptationChanged(
941 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
942 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700943
asapersson0944a802017-04-07 00:57:58 -0700944 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700945 statistics_proxy_.reset();
946 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
947 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
948}
949
950TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700951 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700952 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200953 SendStatisticsProxy::AdaptationSteps cpu_counts;
954 SendStatisticsProxy::AdaptationSteps quality_counts;
955 quality_counts.num_framerate_reductions = absl::nullopt;
956 quality_counts.num_resolution_reductions = absl::nullopt;
957 statistics_proxy_->OnAdaptationChanged(
958 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
959 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700960
asapersson0944a802017-04-07 00:57:58 -0700961 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200962 statistics_proxy_->OnAdaptationChanged(
963 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
964 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700965 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200966 statistics_proxy_->OnAdaptationChanged(
967 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
968 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700969 fake_clock_.AdvanceTimeMilliseconds(9000);
970
971 // Switch content type, real-time stats should be updated.
972 VideoEncoderConfig config;
973 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +0200974 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -0700975 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
976 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
977 EXPECT_EQ(0,
978 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
979
asapersson0944a802017-04-07 00:57:58 -0700980 // First RTP packet sent, scaling enabled.
981 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200982 statistics_proxy_->OnAdaptationChanged(
983 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
984 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700985
asapersson0944a802017-04-07 00:57:58 -0700986 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200987 statistics_proxy_->OnAdaptationChanged(
988 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
989 quality_counts);
990 statistics_proxy_->OnAdaptationChanged(
991 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
992 quality_counts);
993 statistics_proxy_->OnAdaptationChanged(
994 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
995 quality_counts);
996 statistics_proxy_->OnAdaptationChanged(
997 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
998 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700999 fake_clock_.AdvanceTimeMilliseconds(120000);
1000
1001 statistics_proxy_.reset();
1002 EXPECT_EQ(1, metrics::NumSamples(
1003 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1004 EXPECT_EQ(1, metrics::NumEvents(
1005 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1006 EXPECT_EQ(0, metrics::NumSamples(
1007 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
1008}
1009
asapersson59bac1a2016-01-07 23:36:00 -08001010TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001011 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001012 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1013
Pera48ddb72016-09-29 11:48:50 +02001014 // No switch, stats should not be updated.
1015 VideoEncoderConfig config;
1016 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001017 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001018 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001019
1020 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001021 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001022 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001023 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001024}
1025
asapersson320e45a2016-11-29 01:40:35 -08001026TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1027 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1028 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001029
asapersson320e45a2016-11-29 01:40:35 -08001030 statistics_proxy_.reset();
1031 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1032 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1033 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1034 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1035}
1036
1037TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001038 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001039 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001040 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1041 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1042 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001043 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001044
1045 // Not enough samples, stats should not be updated.
1046 for (int i = 0; i < kMinSamples - 1; ++i) {
1047 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001048 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001049 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1050 }
Åsa Persson0122e842017-10-16 12:19:23 +02001051 SetUp(); // Reset stats proxy also causes histograms to be reported.
1052 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1053 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1054
1055 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001056 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001057 for (int i = 0; i < kMinSamples; ++i) {
1058 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001059 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001060 encoded_image._encodedWidth = kWidth;
1061 encoded_image._encodedHeight = kHeight;
1062 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1063 encoded_image._encodedWidth = kWidth / 2;
1064 encoded_image._encodedHeight = kHeight / 2;
1065 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1066 }
1067
asapersson320e45a2016-11-29 01:40:35 -08001068 statistics_proxy_.reset();
1069 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1070 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1071 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1072 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1073}
1074
1075TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1076 const int kFps = 20;
1077 const int kMinPeriodicSamples = 6;
1078 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1079 for (int i = 0; i <= frames; ++i) {
1080 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1081 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1082 }
1083 statistics_proxy_.reset();
1084 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1085 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1086}
1087
1088TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1089 EncodedImage encoded_image;
1090 const int kFps = 20;
1091 const int kMinPeriodicSamples = 6;
1092 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001093 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001094 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001095 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001096 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1097 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001098 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1099 }
1100 statistics_proxy_.reset();
1101 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1102 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1103}
1104
1105TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1106 const int kFps = 20;
1107 const int kSuspendTimeMs = 10000;
1108 const int kMinPeriodicSamples = 6;
1109 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1110 for (int i = 0; i < frames; ++i) {
1111 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1112 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1113 }
1114 // Suspend.
1115 statistics_proxy_->OnSuspendChange(true);
1116 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1117
1118 for (int i = 0; i < frames; ++i) {
1119 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1120 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1121 }
1122 // Suspended time interval should not affect the framerate.
1123 statistics_proxy_.reset();
1124 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1125 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1126}
1127
1128TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1129 EncodedImage encoded_image;
1130 const int kFps = 20;
1131 const int kSuspendTimeMs = 10000;
1132 const int kMinPeriodicSamples = 6;
1133 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001134 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001135 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001136 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001137 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1138 }
1139 // Suspend.
1140 statistics_proxy_->OnSuspendChange(true);
1141 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1142
Åsa Persson0122e842017-10-16 12:19:23 +02001143 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001144 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001145 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001146 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1147 }
1148 // Suspended time interval should not affect the framerate.
1149 statistics_proxy_.reset();
1150 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1151 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1152}
1153
asaperssonf4e44af2017-04-19 02:01:06 -07001154TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001155 SendStatisticsProxy::AdaptationSteps cpu_counts;
1156 SendStatisticsProxy::AdaptationSteps quality_counts;
1157 cpu_counts.num_resolution_reductions = absl::nullopt;
1158 statistics_proxy_->OnAdaptationChanged(
1159 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1160 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001161
1162 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1163 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1164
1165 statistics_proxy_.reset();
1166 EXPECT_EQ(0,
1167 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1168}
1169
1170TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001171 SendStatisticsProxy::AdaptationSteps cpu_counts;
1172 SendStatisticsProxy::AdaptationSteps quality_counts;
1173 cpu_counts.num_resolution_reductions = 0;
1174 statistics_proxy_->OnAdaptationChanged(
1175 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1176 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001177
perkj803d97f2016-11-01 11:45:46 -07001178 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1179 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1180
Niels Möller213618e2018-07-24 09:29:58 +02001181 cpu_counts.num_resolution_reductions = 1;
1182 statistics_proxy_->OnAdaptationChanged(
1183 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1184 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001185
1186 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1187 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1188
1189 statistics_proxy_.reset();
1190 EXPECT_EQ(1,
1191 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1192 EXPECT_EQ(
1193 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1194}
1195
asapersson4374a092016-07-27 00:39:09 -07001196TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1197 const int64_t kTimeSec = 3;
1198 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1199 statistics_proxy_.reset();
1200 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1201 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1202 kTimeSec));
1203}
1204
1205TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1206 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1207 statistics_proxy_.reset();
1208 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1209}
1210
asapersson66d4b372016-12-19 06:50:53 -08001211TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1212 // First RTP packet sent.
1213 UpdateDataCounters(kFirstSsrc);
1214
1215 // Min runtime has passed.
1216 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1217 statistics_proxy_.reset();
1218 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1219 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1220}
1221
1222TEST_F(SendStatisticsProxyTest,
1223 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1224 // First RTP packet sent.
1225 UpdateDataCounters(kFirstSsrc);
1226
1227 // Min runtime has not passed.
1228 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1229 statistics_proxy_.reset();
1230 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1231 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1232}
1233
1234TEST_F(SendStatisticsProxyTest,
1235 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1236 // First RTP packet not sent.
1237 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1238 statistics_proxy_.reset();
1239 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1240}
1241
1242TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1243 // First RTP packet sent and min runtime passed.
1244 UpdateDataCounters(kFirstSsrc);
1245
1246 // No change. Video: 10000 ms, paused: 0 ms (0%).
1247 statistics_proxy_->OnSetEncoderTargetRate(50000);
1248 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1249 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1250
1251 statistics_proxy_.reset();
1252 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1253 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1254 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1255 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1256}
1257
1258TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1259 // First RTP packet sent and min runtime passed.
1260 UpdateDataCounters(kFirstSsrc);
1261
1262 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1263 statistics_proxy_->OnSetEncoderTargetRate(50000);
1264 fake_clock_.AdvanceTimeMilliseconds(7000);
1265 statistics_proxy_->OnSetEncoderTargetRate(0);
1266 fake_clock_.AdvanceTimeMilliseconds(3000);
1267 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1268
1269 statistics_proxy_.reset();
1270 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1271 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1272 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1273 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1274}
1275
1276TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1277 // First RTP packet sent.
1278 UpdateDataCounters(kFirstSsrc);
1279
1280 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1281 statistics_proxy_->OnSetEncoderTargetRate(0);
1282 fake_clock_.AdvanceTimeMilliseconds(1000);
1283 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1284 fake_clock_.AdvanceTimeMilliseconds(7000);
1285 statistics_proxy_->OnSetEncoderTargetRate(60000);
1286 fake_clock_.AdvanceTimeMilliseconds(3000);
1287 statistics_proxy_->OnSetEncoderTargetRate(0);
1288 fake_clock_.AdvanceTimeMilliseconds(250);
1289 statistics_proxy_->OnSetEncoderTargetRate(0);
1290 fake_clock_.AdvanceTimeMilliseconds(750);
1291 statistics_proxy_->OnSetEncoderTargetRate(60000);
1292 fake_clock_.AdvanceTimeMilliseconds(5000);
1293 statistics_proxy_->OnSetEncoderTargetRate(50000);
1294 fake_clock_.AdvanceTimeMilliseconds(4000);
1295 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1296
1297 statistics_proxy_.reset();
1298 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1299 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1300 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1301 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1302}
1303
1304TEST_F(SendStatisticsProxyTest,
1305 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1306 // First RTP packet sent.
1307 UpdateDataCounters(kFirstSsrc);
1308 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1309
1310 // Min runtime has not passed.
1311 statistics_proxy_->OnSetEncoderTargetRate(50000);
1312 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1313 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1314
1315 statistics_proxy_.reset();
1316 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1317}
1318
asapersson118ef002016-03-31 00:00:19 -07001319TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001320 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001321 CodecSpecificInfo codec_info;
1322 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001323
perkj803d97f2016-11-01 11:45:46 -07001324 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001325 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001326 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001327 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001328 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001329 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001330 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001331 }
1332 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001333 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1334 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1335 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1336 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001337}
1338
1339TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1340 VideoSendStream::Config config(nullptr);
1341 config.rtp.ssrcs.push_back(kFirstSsrc);
1342 statistics_proxy_.reset(new SendStatisticsProxy(
1343 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1344
asapersson118ef002016-03-31 00:00:19 -07001345 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001346 CodecSpecificInfo codec_info;
1347 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001348
perkj803d97f2016-11-01 11:45:46 -07001349 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001350 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001351 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001352 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001353 }
1354 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001355 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1356 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001357}
1358
asapersson5265fed2016-04-18 02:58:47 -07001359TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001360 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001361 CodecSpecificInfo codec_info;
1362 codec_info.codecType = kVideoCodecVP9;
1363 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001364
perkj803d97f2016-11-01 11:45:46 -07001365 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001366 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001367 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001368 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001369 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001370 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001371 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001372 }
1373 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001374 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1375 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1376 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1377 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001378}
1379
1380TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1381 VideoSendStream::Config config(nullptr);
1382 config.rtp.ssrcs.push_back(kFirstSsrc);
1383 statistics_proxy_.reset(new SendStatisticsProxy(
1384 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1385
asapersson5265fed2016-04-18 02:58:47 -07001386 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001387 CodecSpecificInfo codec_info;
1388 codec_info.codecType = kVideoCodecVP9;
1389 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001390
perkj803d97f2016-11-01 11:45:46 -07001391 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001392 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001393 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001394 }
1395 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001396 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1397 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001398}
1399
asapersson827cab32016-11-02 09:08:47 -07001400TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1401 EncodedImage encoded_image;
1402 CodecSpecificInfo codec_info;
1403 codec_info.codecType = kVideoCodecH264;
1404
1405 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001406 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001407 encoded_image.qp_ = kQpIdx0;
1408 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001409 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001410 encoded_image.qp_ = kQpIdx1;
1411 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001412 }
1413 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001414 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1415 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1416 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1417 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001418}
1419
asapersson4ee70462016-10-31 04:05:12 -07001420TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001421 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1422 // Configure one stream.
1423 VideoEncoderConfig config;
1424 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1425 VideoStream stream1;
1426 stream1.width = kWidth;
1427 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001428 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001429
1430 const int64_t kMaxEncodedFrameWindowMs = 800;
1431 const int kFps = 20;
1432 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1433 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1434 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1435
1436 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001437 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001438 encoded_image._encodedWidth = kWidth;
1439 encoded_image._encodedHeight = kHeight;
1440 for (int i = 0; i < kMinSamples; ++i) {
1441 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001442 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1443 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001444 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001445 }
asapersson4ee70462016-10-31 04:05:12 -07001446
1447 // Histograms are updated when the statistics_proxy_ is deleted.
1448 statistics_proxy_.reset();
1449 EXPECT_EQ(0, metrics::NumSamples(
1450 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1451 EXPECT_EQ(0, metrics::NumSamples(
1452 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1453}
1454
1455TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001456 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1457 // Configure two streams.
1458 VideoEncoderConfig config;
1459 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1460 VideoStream stream1;
1461 stream1.width = kWidth / 2;
1462 stream1.height = kHeight / 2;
1463 VideoStream stream2;
1464 stream2.width = kWidth;
1465 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001466 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001467
1468 const int64_t kMaxEncodedFrameWindowMs = 800;
1469 const int kFps = 20;
1470 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1471 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1472 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1473
1474 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001475 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001476 for (int i = 0; i < kMinSamples; ++i) {
1477 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001478 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1479 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001480 encoded_image._encodedWidth = kWidth;
1481 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001482 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001483 encoded_image._encodedWidth = kWidth / 2;
1484 encoded_image._encodedHeight = kHeight / 2;
1485 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1486 }
asapersson4ee70462016-10-31 04:05:12 -07001487
1488 // Histograms are updated when the statistics_proxy_ is deleted.
1489 statistics_proxy_.reset();
1490 EXPECT_EQ(1, metrics::NumSamples(
1491 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1492 EXPECT_EQ(1, metrics::NumEvents(
1493 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1494 // No resolution disabled.
1495 EXPECT_EQ(0, metrics::NumSamples(
1496 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1497}
1498
1499TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001500 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1501 // Configure two streams.
1502 VideoEncoderConfig config;
1503 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1504 VideoStream stream1;
1505 stream1.width = kWidth / 2;
1506 stream1.height = kHeight / 2;
1507 VideoStream stream2;
1508 stream2.width = kWidth;
1509 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001510 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001511
1512 const int64_t kMaxEncodedFrameWindowMs = 800;
1513 const int kFps = 20;
1514 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1515 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1516 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1517
1518 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001519 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001520 encoded_image._encodedWidth = kWidth / 2;
1521 encoded_image._encodedHeight = kHeight / 2;
1522 for (int i = 0; i < kMinSamples; ++i) {
1523 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001524 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1525 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001526 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001527 }
asapersson4ee70462016-10-31 04:05:12 -07001528
1529 // Histograms are updated when the statistics_proxy_ is deleted.
1530 statistics_proxy_.reset();
1531 EXPECT_EQ(1, metrics::NumSamples(
1532 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1533 EXPECT_EQ(1, metrics::NumEvents(
1534 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001535 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001536 EXPECT_EQ(1, metrics::NumSamples(
1537 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001538 EXPECT_EQ(1, metrics::NumEvents(
1539 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001540}
1541
1542TEST_F(SendStatisticsProxyTest,
1543 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001544 SendStatisticsProxy::AdaptationSteps cpu_counts;
1545 SendStatisticsProxy::AdaptationSteps quality_counts;
1546 quality_counts.num_resolution_reductions = absl::nullopt;
1547 statistics_proxy_->OnAdaptationChanged(
1548 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1549 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001550 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001551 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001552 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001553 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001554
1555 // Histograms are updated when the statistics_proxy_ is deleted.
1556 statistics_proxy_.reset();
1557 EXPECT_EQ(
1558 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1559 EXPECT_EQ(0, metrics::NumSamples(
1560 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1561}
1562
1563TEST_F(SendStatisticsProxyTest,
1564 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001565 SendStatisticsProxy::AdaptationSteps cpu_counts;
1566 SendStatisticsProxy::AdaptationSteps quality_counts;
1567 quality_counts.num_resolution_reductions = 0;
1568 statistics_proxy_->OnAdaptationChanged(
1569 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1570 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001571 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001572 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001573 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001574 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001575
1576 // Histograms are updated when the statistics_proxy_ is deleted.
1577 statistics_proxy_.reset();
1578 EXPECT_EQ(
1579 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1580 EXPECT_EQ(1, metrics::NumEvents(
1581 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1582 // No resolution downscale.
1583 EXPECT_EQ(0, metrics::NumSamples(
1584 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1585}
1586
1587TEST_F(SendStatisticsProxyTest,
1588 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1589 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001590 SendStatisticsProxy::AdaptationSteps cpu_counts;
1591 SendStatisticsProxy::AdaptationSteps quality_counts;
1592 quality_counts.num_resolution_reductions = kDownscales;
1593 statistics_proxy_->OnAdaptationChanged(
1594 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1595 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001596 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001597 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001598 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001599 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001600 // Histograms are updated when the statistics_proxy_ is deleted.
1601 statistics_proxy_.reset();
1602 EXPECT_EQ(
1603 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1604 EXPECT_EQ(1, metrics::NumEvents(
1605 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1606 // Resolution downscales.
1607 EXPECT_EQ(1, metrics::NumSamples(
1608 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1609 EXPECT_EQ(
1610 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1611 kDownscales));
1612}
1613
1614TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1615 // Initially false.
1616 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001617
Åsa Perssonaa329e72017-12-15 15:54:44 +01001618 // Configure two streams.
1619 VideoEncoderConfig config;
1620 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1621 VideoStream stream1;
1622 stream1.width = kWidth / 2;
1623 stream1.height = kHeight / 2;
1624 VideoStream stream2;
1625 stream2.width = kWidth;
1626 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001627 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001628
1629 const int64_t kMaxEncodedFrameWindowMs = 800;
1630 const int kFps = 20;
1631 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1632 kFps * kMaxEncodedFrameWindowMs / 1000;
1633
1634 // One stream encoded.
1635 EncodedImage encoded_image;
1636 encoded_image._encodedWidth = kWidth / 2;
1637 encoded_image._encodedHeight = kHeight / 2;
1638 for (int i = 0; i < kMinSamples; ++i) {
1639 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001640 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1641 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001642 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1643 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1644 }
1645
1646 // First frame removed from EncodedFrameMap, stats updated.
1647 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001648 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08001649 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1650 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1651
Åsa Perssonaa329e72017-12-15 15:54:44 +01001652 // Two streams encoded.
1653 for (int i = 0; i < kMinSamples; ++i) {
1654 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001655 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1656 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001657 encoded_image._encodedWidth = kWidth;
1658 encoded_image._encodedHeight = kHeight;
1659 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1660 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1661 encoded_image._encodedWidth = kWidth / 2;
1662 encoded_image._encodedHeight = kHeight / 2;
1663 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1664 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1665 }
1666
1667 // First frame with two streams removed, expect no resolution limit.
1668 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001669 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1670 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001671 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1672 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001673
1674 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02001675 SendStatisticsProxy::AdaptationSteps cpu_counts;
1676 SendStatisticsProxy::AdaptationSteps quality_counts;
1677 quality_counts.num_resolution_reductions = 1;
1678 statistics_proxy_->OnAdaptationChanged(
1679 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1680 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001681 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1682 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1683}
1684
asapersson66d4b372016-12-19 06:50:53 -08001685TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1686 // Initially zero.
1687 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1688
1689 const int kBitrate = 100000;
1690 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1691 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1692
1693 statistics_proxy_->OnSetEncoderTargetRate(0);
1694 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1695}
1696
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001697TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001698 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07001699 std::max(*absl::c_max_element(config_.rtp.ssrcs),
1700 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001701 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001702 // From RtcpStatisticsCallback.
1703 RtcpStatistics rtcp_stats;
1704 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001705 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001706
1707 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001708 uint32_t total = 0;
1709 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001710 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001711 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001712
1713 // From FrameCountObserver.
1714 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001715 FrameCounts frame_counts;
1716 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001717 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001718
1719 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1720 EXPECT_TRUE(stats.substreams.empty());
1721}
1722
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001723TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1724 static const int kEncodedWidth = 123;
1725 static const int kEncodedHeight = 81;
1726 EncodedImage encoded_image;
1727 encoded_image._encodedWidth = kEncodedWidth;
1728 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001729 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001730
kjellander02b3d272016-04-20 05:05:54 -07001731 CodecSpecificInfo codec_info;
1732 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001733
kjellander02b3d272016-04-20 05:05:54 -07001734 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001735 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001736 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001737
1738 VideoSendStream::Stats 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);
1741 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1742 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001743
1744 // Forward almost to timeout, this should not have removed stats.
1745 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1746 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001747 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1748 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001749
1750 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1751 // resolution still times out (no global timeout for all stats).
1752 RtcpStatistics rtcp_statistics;
1753 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1754 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1755
1756 // Report stats for second SSRC to make sure it's not outdated along with the
1757 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001758 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001759
1760 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1761 // reported, but substream 1 should.
1762 fake_clock_.AdvanceTimeMilliseconds(1);
1763 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001764 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1765 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1766 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1767 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001768}
1769
Peter Boström20f3f942015-05-15 11:33:39 +02001770TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1771 static const int kEncodedWidth = 123;
1772 static const int kEncodedHeight = 81;
1773 EncodedImage encoded_image;
1774 encoded_image._encodedWidth = kEncodedWidth;
1775 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001776 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02001777
kjellander02b3d272016-04-20 05:05:54 -07001778 CodecSpecificInfo codec_info;
1779 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02001780
kjellander02b3d272016-04-20 05:05:54 -07001781 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001782 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001783 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001784
1785 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1786 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1787 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1788 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1789 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1790 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1791}
1792
1793TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001794 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001795 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1796 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1797 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1798
1799 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1800
1801 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001802 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001803 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001804 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001805 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1806 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1807 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1808}
1809
sprang07fb9be2016-02-24 07:55:00 -08001810TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1811 RtcpPacketTypeCounterObserver* proxy =
1812 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1813 RtcpPacketTypeCounter counters;
1814 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1815 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1816 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1817
1818 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1819
1820 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1821 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1822 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1823 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1824 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1825
1826 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1827 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1828
1829 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001830 VideoEncoderConfig config;
1831 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001832 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001833
asapersson01d70a32016-05-20 06:29:46 -07001834 EXPECT_EQ(1,
1835 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1836 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1837 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1838 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001839 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1840
1841 const int kRate = 60 * 2; // Packets per minute with two streams.
1842
asapersson01d70a32016-05-20 06:29:46 -07001843 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1844 1 * kRate));
1845 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1846 2 * kRate));
1847 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1848 3 * kRate));
1849 EXPECT_EQ(
1850 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1851 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001852
1853 // New start time but same counter values.
1854 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1855 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1856
1857 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1858
1859 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1860 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1861 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1862 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1863 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1864
1865 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1866 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1867
1868 SetUp(); // Reset stats proxy also causes histograms to be reported.
1869
asapersson01d70a32016-05-20 06:29:46 -07001870 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001871 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001872 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001873 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001874 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001875 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1876 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001877 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001878 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1879
asapersson01d70a32016-05-20 06:29:46 -07001880 EXPECT_EQ(1, metrics::NumEvents(
1881 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1882 1 * kRate));
1883 EXPECT_EQ(1, metrics::NumEvents(
1884 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1885 2 * kRate));
1886 EXPECT_EQ(1, metrics::NumEvents(
1887 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1888 3 * kRate));
1889 EXPECT_EQ(1,
1890 metrics::NumEvents(
1891 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1892 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001893}
1894
asaperssona6a699a2016-11-25 03:52:46 -08001895TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1896 statistics_proxy_.reset(
1897 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1898 VideoEncoderConfig::ContentType::kRealtimeVideo));
1899
1900 StreamDataCountersCallback* proxy =
1901 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1902 StreamDataCounters counters;
1903 proxy->DataCountersUpdated(counters, kFirstSsrc);
1904 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1905
1906 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1907 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1908}
1909
1910TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1911 statistics_proxy_.reset(
1912 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1913 VideoEncoderConfig::ContentType::kRealtimeVideo));
1914
1915 StreamDataCountersCallback* proxy =
1916 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001917 StreamDataCounters counters;
1918 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001919
asapersson93e1e232017-02-06 05:18:35 -08001920 const int kMinRequiredPeriodSamples = 8;
1921 const int kPeriodIntervalMs = 2000;
1922 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1923 counters.transmitted.packets += 20;
1924 counters.transmitted.header_bytes += 500;
1925 counters.transmitted.padding_bytes += 1000;
1926 counters.transmitted.payload_bytes += 2000;
1927 counters.retransmitted.packets += 2;
1928 counters.retransmitted.header_bytes += 25;
1929 counters.retransmitted.padding_bytes += 100;
1930 counters.retransmitted.payload_bytes += 250;
1931 counters.fec = counters.retransmitted;
1932 rtx_counters.transmitted = counters.transmitted;
1933 // Advance one interval and update counters.
1934 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1935 proxy->DataCountersUpdated(counters, kFirstSsrc);
1936 proxy->DataCountersUpdated(counters, kSecondSsrc);
1937 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1938 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1939 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1940 }
asaperssona6a699a2016-11-25 03:52:46 -08001941
asaperssona6a699a2016-11-25 03:52:46 -08001942 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001943 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001944 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001945 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1946 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1947 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1948 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1949 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001950 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001951 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1952 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001953 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001954 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1955 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1956 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1957 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1958 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001959 EXPECT_EQ(1,
1960 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001961 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001962 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001963}
1964
Erik Språng22c2b482016-03-01 09:40:42 +01001965TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1966 StreamDataCountersCallback* proxy =
1967 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1968 StreamDataCounters counters;
1969 StreamDataCounters rtx_counters;
1970 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001971
asapersson93e1e232017-02-06 05:18:35 -08001972 const int kMinRequiredPeriodSamples = 8;
1973 const int kPeriodIntervalMs = 2000;
1974 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1975 counters.transmitted.packets += 20;
1976 counters.transmitted.header_bytes += 500;
1977 counters.transmitted.padding_bytes += 1000;
1978 counters.transmitted.payload_bytes += 2000;
1979 counters.retransmitted.packets += 2;
1980 counters.retransmitted.header_bytes += 25;
1981 counters.retransmitted.padding_bytes += 100;
1982 counters.retransmitted.payload_bytes += 250;
1983 counters.fec = counters.retransmitted;
1984 rtx_counters.transmitted = counters.transmitted;
1985 // Advance one interval and update counters.
1986 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1987 proxy->DataCountersUpdated(counters, kFirstSsrc);
1988 proxy->DataCountersUpdated(counters, kSecondSsrc);
1989 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1990 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1991 }
Erik Språng22c2b482016-03-01 09:40:42 +01001992
1993 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001994 VideoEncoderConfig config;
1995 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001996 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01001997
asapersson93e1e232017-02-06 05:18:35 -08001998 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001999 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002000 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2001 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2002 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2003 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2004 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002005 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002006 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2007 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002008 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002009 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2010 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2011 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2012 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2013 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002014 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002015 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002016 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002017 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002018
asapersson93e1e232017-02-06 05:18:35 -08002019 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002020 // Double counter values, this should result in the same counts as before but
2021 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002022 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2023 counters.transmitted.packets += 20;
2024 counters.transmitted.header_bytes += 500;
2025 counters.transmitted.padding_bytes += 1000;
2026 counters.transmitted.payload_bytes += 2000;
2027 counters.retransmitted.packets += 2;
2028 counters.retransmitted.header_bytes += 25;
2029 counters.retransmitted.padding_bytes += 100;
2030 counters.retransmitted.payload_bytes += 250;
2031 counters.fec = counters.retransmitted;
2032 rtx_counters.transmitted = counters.transmitted;
2033 // Advance one interval and update counters.
2034 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2035 proxy->DataCountersUpdated(counters, kFirstSsrc);
2036 proxy->DataCountersUpdated(counters, kSecondSsrc);
2037 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2038 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2039 }
Erik Språng22c2b482016-03-01 09:40:42 +01002040
asapersson93e1e232017-02-06 05:18:35 -08002041 // Reset stats proxy also causes histograms to be reported.
2042 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002043
asapersson93e1e232017-02-06 05:18:35 -08002044 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002045 EXPECT_EQ(1,
2046 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002047 EXPECT_EQ(
2048 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2049 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2050 EXPECT_EQ(
2051 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2052 EXPECT_EQ(1, metrics::NumEvents(
2053 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2054 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002055 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002056 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002057 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002058 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2059 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002060 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002061 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002062 EXPECT_EQ(1, metrics::NumEvents(
2063 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2064 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2065 EXPECT_EQ(
2066 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2067 EXPECT_EQ(1, metrics::NumEvents(
2068 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2069 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002070 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002071 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002072 EXPECT_EQ(1,
2073 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002074 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2075}
Erik Språng22c2b482016-03-01 09:40:42 +01002076
asapersson93e1e232017-02-06 05:18:35 -08002077TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2078 StreamDataCountersCallback* proxy =
2079 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2080 StreamDataCounters counters;
2081 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002082
asapersson93e1e232017-02-06 05:18:35 -08002083 const int kMinRequiredPeriodSamples = 8;
2084 const int kPeriodIntervalMs = 2000;
2085 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2086 counters.transmitted.packets += 20;
2087 counters.transmitted.header_bytes += 500;
2088 counters.transmitted.payload_bytes += 2000;
2089 counters.fec = counters.retransmitted;
2090 // Advance one interval and update counters.
2091 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2092 proxy->DataCountersUpdated(counters, kFirstSsrc);
2093 }
2094
2095 // RTX enabled. No data sent over RTX.
2096 statistics_proxy_.reset();
2097 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2098 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2099}
2100
2101TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2102 VideoSendStream::Config config(nullptr);
2103 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2104 statistics_proxy_.reset(new SendStatisticsProxy(
2105 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2106
2107 StreamDataCountersCallback* proxy =
2108 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2109 StreamDataCounters counters;
2110
2111 const int kMinRequiredPeriodSamples = 8;
2112 const int kPeriodIntervalMs = 2000;
2113 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2114 counters.transmitted.packets += 20;
2115 counters.transmitted.header_bytes += 500;
2116 counters.transmitted.payload_bytes += 2000;
2117 counters.fec = counters.retransmitted;
2118 // Advance one interval and update counters.
2119 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2120 proxy->DataCountersUpdated(counters, kFirstSsrc);
2121 }
2122
2123 // RTX not enabled.
2124 statistics_proxy_.reset();
2125 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2126}
2127
2128TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2129 StreamDataCountersCallback* proxy =
2130 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2131 StreamDataCounters counters;
2132 StreamDataCounters rtx_counters;
2133
2134 const int kMinRequiredPeriodSamples = 8;
2135 const int kPeriodIntervalMs = 2000;
2136 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2137 counters.transmitted.packets += 20;
2138 counters.transmitted.header_bytes += 500;
2139 counters.transmitted.payload_bytes += 2000;
2140 // Advance one interval and update counters.
2141 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2142 proxy->DataCountersUpdated(counters, kFirstSsrc);
2143 }
2144
2145 // FEC enabled. No FEC data sent.
2146 statistics_proxy_.reset();
2147 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2148 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2149}
2150
2151TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2152 VideoSendStream::Config config(nullptr);
2153 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2154 statistics_proxy_.reset(new SendStatisticsProxy(
2155 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2156
2157 StreamDataCountersCallback* proxy =
2158 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2159 StreamDataCounters counters;
2160
2161 const int kMinRequiredPeriodSamples = 8;
2162 const int kPeriodIntervalMs = 2000;
2163 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2164 counters.transmitted.packets += 20;
2165 counters.transmitted.header_bytes += 500;
2166 counters.transmitted.payload_bytes += 2000;
2167 counters.fec = counters.retransmitted;
2168 // Advance one interval and update counters.
2169 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2170 proxy->DataCountersUpdated(counters, kFirstSsrc);
2171 }
2172
2173 // FEC not enabled.
2174 statistics_proxy_.reset();
2175 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002176}
2177
asapersson8d75ac72017-09-15 06:41:15 -07002178TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002179 const std::string kName = "encoderName";
2180 statistics_proxy_->OnEncoderImplementationChanged(kName);
2181 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002182}
2183
Sergey Silkinbb081a62018-09-04 18:34:22 +02002184TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2185 static const int kEncodedWidth = 123;
2186 static const int kEncodedHeight = 81;
2187 EncodedImage encoded_image;
2188 encoded_image._encodedWidth = kEncodedWidth;
2189 encoded_image._encodedHeight = kEncodedHeight;
2190 encoded_image.SetSpatialIndex(0);
2191
2192 CodecSpecificInfo codec_info;
2193 codec_info.codecType = kVideoCodecVP9;
2194
2195 // For first picture, it is expected that low layer updates resolution.
2196 codec_info.codecSpecific.VP9.end_of_picture = false;
2197 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2198 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2199 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2200 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2201
2202 // Top layer updates resolution.
2203 encoded_image._encodedWidth = kEncodedWidth * 2;
2204 encoded_image._encodedHeight = kEncodedHeight * 2;
2205 codec_info.codecSpecific.VP9.end_of_picture = true;
2206 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2207 stats = statistics_proxy_->GetStats();
2208 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2209 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2210
2211 // Low layer of next frame doesn't update resolution.
2212 encoded_image._encodedWidth = kEncodedWidth;
2213 encoded_image._encodedHeight = kEncodedHeight;
2214 codec_info.codecSpecific.VP9.end_of_picture = false;
2215 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2216 stats = statistics_proxy_->GetStats();
2217 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2218 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2219}
2220
asapersson8d75ac72017-09-15 06:41:15 -07002221class ForcedFallbackTest : public SendStatisticsProxyTest {
2222 public:
2223 explicit ForcedFallbackTest(const std::string& field_trials)
2224 : SendStatisticsProxyTest(field_trials) {
2225 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002226 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002227 encoded_image_._encodedWidth = kWidth;
2228 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002229 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002230 }
2231
2232 ~ForcedFallbackTest() override {}
2233
2234 protected:
2235 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002236 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2237
asapersson8d75ac72017-09-15 06:41:15 -07002238 // First frame is not updating stats, insert initial frame.
2239 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2240 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2241 }
2242 for (int i = 0; i < num_frames; ++i) {
2243 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2244 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2245 }
2246 // Add frame to include last time interval.
2247 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2248 }
2249
2250 EncodedImage encoded_image_;
2251 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002252 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002253 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2254 const int kFrameIntervalMs = 1000;
2255 const int kMinFrames = 20; // Min run time 20 sec.
2256};
2257
2258class ForcedFallbackDisabled : public ForcedFallbackTest {
2259 public:
2260 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002261 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2262 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002263};
2264
2265class ForcedFallbackEnabled : public ForcedFallbackTest {
2266 public:
2267 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002268 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2269 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002270};
2271
2272TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2273 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2274 statistics_proxy_.reset();
2275 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2276 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2277}
2278
2279TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2280 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002281 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002282 statistics_proxy_.reset();
2283 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2284 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2285 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2286 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2287}
2288
2289TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2290 codec_info_.codecType = kVideoCodecVP9;
2291 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2292 statistics_proxy_.reset();
2293 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2294 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2295}
2296
2297TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2298 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2299 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2300 statistics_proxy_.reset();
2301 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2302 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2303}
2304
2305TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002306 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002307 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2308 statistics_proxy_.reset();
2309 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2310 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2311}
2312
2313TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2314 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2315 statistics_proxy_.reset();
2316 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2317 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2318}
2319
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002320TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2321 InsertEncodedFrames(1, kFrameIntervalMs);
2322 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2323}
2324
2325TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2326 InsertEncodedFrames(1, kFrameIntervalMs);
2327 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2328}
2329
2330TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002331 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002332 InsertEncodedFrames(1, kFrameIntervalMs);
2333 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2334}
2335
2336TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2337 encoded_image_._encodedWidth = kWidth + 1;
2338 InsertEncodedFrames(1, kFrameIntervalMs);
2339 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2340}
2341
2342TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002343 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002344 InsertEncodedFrames(1, kFrameIntervalMs);
2345 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2346}
2347
2348TEST_F(ForcedFallbackDisabled,
2349 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2350 encoded_image_._encodedWidth = kWidth + 1;
2351 statistics_proxy_->OnMinPixelLimitReached();
2352 InsertEncodedFrames(1, kFrameIntervalMs);
2353 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2354}
2355
asapersson8d75ac72017-09-15 06:41:15 -07002356TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2357 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002358 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002359 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002360 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002361 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002362 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002363 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002364
2365 statistics_proxy_.reset();
2366 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2367 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2368 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2369 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2370}
2371
2372TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2373 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2374 const int kMaxFrameDiffMs = 2000;
2375
2376 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2377 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002378 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002379 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002380 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002381 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002382 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002383 InsertEncodedFrames(20, 1000);
2384 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2385 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002386 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002387 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002388 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002389 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002390 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002391 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002392 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002393
2394 statistics_proxy_.reset();
2395 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2396 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2397 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2398 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2399}
2400
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002401TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2402 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002403 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002404 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2405
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002406 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002407 statistics_proxy_.reset();
2408 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2409 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2410}
2411
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002412TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2413 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002414 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002415 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2416
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002417 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002418 statistics_proxy_.reset();
2419 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2420 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2421}
2422
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002423} // namespace webrtc