blob: 6942e36b5dddb6981eff08eae8bbe415bdf8e856 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
13#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080014#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000015#include <string>
16#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "system_wrappers/include/metrics.h"
19#include "system_wrappers/include/metrics_default.h"
asapersson8d75ac72017-09-15 06:41:15 -070020#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000022
23namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070024namespace {
25const uint32_t kFirstSsrc = 17;
26const uint32_t kSecondSsrc = 42;
27const uint32_t kFirstRtxSsrc = 18;
28const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080029const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080030const int kFpsPeriodicIntervalMs = 2000;
31const int kWidth = 640;
32const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070033const int kQpIdx0 = 21;
34const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010035const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080036const CodecSpecificInfo kDefaultCodecInfo = []() {
37 CodecSpecificInfo codec_info;
38 codec_info.codecType = kVideoCodecVP8;
39 codec_info.codecSpecific.VP8.simulcastIdx = 0;
40 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
sakal43536c32016-10-24 01:46:43 -0700321TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
322 EncodedImage encoded_image;
323 CodecSpecificInfo codec_info;
324 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
325 for (uint32_t i = 1; i <= 3; ++i) {
326 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
327 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
328 }
329}
330
sakal87da4042016-10-31 06:53:47 -0700331TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
332 EncodedImage encoded_image;
333 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200334 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700335 encoded_image.qp_ = 3;
336 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100337 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700338 encoded_image.qp_ = 127;
339 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100340 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700341}
342
343TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
344 EncodedImage encoded_image;
345 CodecSpecificInfo codec_info;
346 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200347 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700348 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200349 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700350}
351
asapersson09f05612017-05-15 23:40:18 -0700352TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200353 SendStatisticsProxy::AdaptationSteps cpu_counts;
354 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700355 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700356 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200357 cpu_counts.num_framerate_reductions = 1;
358 cpu_counts.num_resolution_reductions = 0;
359 statistics_proxy_->OnAdaptationChanged(
360 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
361 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700362 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700363 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200364 cpu_counts.num_framerate_reductions = 0;
365 cpu_counts.num_resolution_reductions = 1;
366 statistics_proxy_->OnAdaptationChanged(
367 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
368 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700369 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700370 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200371 cpu_counts.num_framerate_reductions = 1;
372 cpu_counts.num_resolution_reductions = absl::nullopt;
373 statistics_proxy_->OnAdaptationChanged(
374 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
375 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700376 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700377 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200378 cpu_counts.num_framerate_reductions = absl::nullopt;
379 cpu_counts.num_resolution_reductions = absl::nullopt;
380 statistics_proxy_->OnAdaptationChanged(
381 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
382 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700383 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
384 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
385}
386
387TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200388 SendStatisticsProxy::AdaptationSteps cpu_counts;
389 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700390 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
391 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200392 quality_counts.num_framerate_reductions = 1;
393 quality_counts.num_resolution_reductions = 0;
394 statistics_proxy_->OnAdaptationChanged(
395 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
396 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700397 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
398 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200399 quality_counts.num_framerate_reductions = 0;
400 quality_counts.num_resolution_reductions = 1;
401 statistics_proxy_->OnAdaptationChanged(
402 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
403 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700404 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
405 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200406 quality_counts.num_framerate_reductions = 1;
407 quality_counts.num_resolution_reductions = absl::nullopt;
408 statistics_proxy_->OnAdaptationChanged(
409 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
410 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700411 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
412 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200413 quality_counts.num_framerate_reductions = absl::nullopt;
414 quality_counts.num_resolution_reductions = absl::nullopt;
415 statistics_proxy_->OnAdaptationChanged(
416 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
417 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700418 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
419 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
420}
421
422TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200423 SendStatisticsProxy::AdaptationSteps cpu_counts;
424 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700425 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
426
Niels Möller213618e2018-07-24 09:29:58 +0200427 cpu_counts.num_resolution_reductions = 1;
428 statistics_proxy_->OnAdaptationChanged(
429 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
430 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700431 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700432 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
433 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
434
Niels Möller213618e2018-07-24 09:29:58 +0200435 cpu_counts.num_resolution_reductions = 2;
436 statistics_proxy_->OnAdaptationChanged(
437 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
438 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700439 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
440 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700441 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700442 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700443}
444
asapersson09f05612017-05-15 23:40:18 -0700445TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200446 SendStatisticsProxy::AdaptationSteps cpu_counts;
447 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700448 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
449
Niels Möller213618e2018-07-24 09:29:58 +0200450 quality_counts.num_framerate_reductions = 1;
451 statistics_proxy_->OnAdaptationChanged(
452 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
453 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700454 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
455 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700456 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
457
Niels Möller213618e2018-07-24 09:29:58 +0200458 quality_counts.num_framerate_reductions = 0;
459 statistics_proxy_->OnAdaptationChanged(
460 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
461 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700462 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700463 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700464 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
465 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700466}
467
asapersson09f05612017-05-15 23:40:18 -0700468TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700469 // First RTP packet sent.
470 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700471 // Min runtime has passed.
472 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
473 statistics_proxy_.reset();
474 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
475 EXPECT_EQ(0,
476 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
477}
478
479TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700480 // First RTP packet sent.
481 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700482 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200483 SendStatisticsProxy::AdaptationSteps cpu_counts;
484 SendStatisticsProxy::AdaptationSteps quality_counts;
485 statistics_proxy_->OnAdaptationChanged(
486 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
487 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700488 // Min runtime has not passed.
489 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
490 statistics_proxy_.reset();
491 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
492 EXPECT_EQ(0,
493 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
494}
495
asapersson09f05612017-05-15 23:40:18 -0700496TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700497 // First RTP packet sent.
498 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700499 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200500 SendStatisticsProxy::AdaptationSteps cpu_counts;
501 SendStatisticsProxy::AdaptationSteps quality_counts;
502 statistics_proxy_->OnAdaptationChanged(
503 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
504 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700505 // Min runtime has passed.
506 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
507 statistics_proxy_.reset();
508 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
509 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700510 EXPECT_EQ(1,
511 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
512 EXPECT_EQ(
513 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
514}
515
516TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700517 // First RTP packet sent.
518 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700519 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200520 SendStatisticsProxy::AdaptationSteps cpu_counts;
521 SendStatisticsProxy::AdaptationSteps quality_counts;
522 statistics_proxy_->OnAdaptationChanged(
523 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
524 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700525 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200526 statistics_proxy_->OnAdaptationChanged(
527 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
528 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700529 fake_clock_.AdvanceTimeMilliseconds(10000);
530 statistics_proxy_.reset();
531 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
532 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
533}
534
Åsa Persson875841d2018-01-08 08:49:53 +0100535TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
536 // First RTP packet sent.
537 UpdateDataCounters(kFirstSsrc);
538 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200539 SendStatisticsProxy::AdaptationSteps cpu_counts;
540 SendStatisticsProxy::AdaptationSteps quality_counts;
541 statistics_proxy_->OnAdaptationChanged(
542 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
543 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100544 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200545 statistics_proxy_->OnAdaptationChanged(
546 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
547 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100548 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
549 fake_clock_.AdvanceTimeMilliseconds(10000);
550 statistics_proxy_.reset();
551 EXPECT_EQ(1,
552 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
553 EXPECT_EQ(
554 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
555}
556
557TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
558 // First RTP packet sent.
559 UpdateDataCounters(kFirstSsrc);
560 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200561 SendStatisticsProxy::AdaptationSteps cpu_counts;
562 SendStatisticsProxy::AdaptationSteps quality_counts;
563 statistics_proxy_->OnAdaptationChanged(
564 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
565 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100566 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200567 quality_counts.num_resolution_reductions = 1;
568 statistics_proxy_->OnAdaptationChanged(
569 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
570 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100571 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200572 quality_counts.num_resolution_reductions = 2;
573 statistics_proxy_->OnAdaptationChanged(
574 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
575 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100576 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200577 quality_counts.num_resolution_reductions = 3;
578 statistics_proxy_->OnAdaptationChanged(
579 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
580 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100581 fake_clock_.AdvanceTimeMilliseconds(10000);
582 statistics_proxy_.reset();
583 EXPECT_EQ(1,
584 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
585 EXPECT_EQ(
586 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
587}
588
589TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
590 // First RTP packet sent.
591 UpdateDataCounters(kFirstSsrc);
592 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200593 SendStatisticsProxy::AdaptationSteps cpu_counts;
594 SendStatisticsProxy::AdaptationSteps quality_counts;
595 statistics_proxy_->OnAdaptationChanged(
596 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
597 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100598 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200599 statistics_proxy_->OnAdaptationChanged(
600 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
601 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100602 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
603 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
604 fake_clock_.AdvanceTimeMilliseconds(10000);
605 statistics_proxy_.reset();
606 EXPECT_EQ(1,
607 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
608 EXPECT_EQ(
609 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
610}
611
612TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
613 // First RTP packet sent.
614 UpdateDataCounters(kFirstSsrc);
615 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200616 SendStatisticsProxy::AdaptationSteps cpu_counts;
617 SendStatisticsProxy::AdaptationSteps quality_counts;
618 statistics_proxy_->OnAdaptationChanged(
619 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
620 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100621 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200622 quality_counts.num_resolution_reductions = 1;
623 statistics_proxy_->OnAdaptationChanged(
624 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
625 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100626 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200627 quality_counts.num_resolution_reductions = 2;
628 statistics_proxy_->OnAdaptationChanged(
629 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
630 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100631 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200632 quality_counts.num_resolution_reductions = 3;
633 statistics_proxy_->OnAdaptationChanged(
634 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
635 quality_counts);
636 quality_counts.num_framerate_reductions = 1;
637 statistics_proxy_->OnAdaptationChanged(
638 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
639 quality_counts);
640 quality_counts.num_framerate_reductions = 0;
641 statistics_proxy_->OnAdaptationChanged(
642 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
643 quality_counts);
644 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
645 statistics_proxy_->OnAdaptationChanged(
646 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
647 quality_counts);
648 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
649 statistics_proxy_->OnAdaptationChanged(
650 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
651 quality_counts);
652 quality_counts.num_resolution_reductions = 0;
653 statistics_proxy_->OnAdaptationChanged(
654 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
655 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100656
657 fake_clock_.AdvanceTimeMilliseconds(10000);
658 statistics_proxy_.reset();
659 EXPECT_EQ(1,
660 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
661 EXPECT_EQ(
662 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
663}
664
asapersson6eca98b2017-04-04 23:40:50 -0700665TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700666 // First RTP packet sent.
667 UpdateDataCounters(kFirstSsrc);
668
asapersson09f05612017-05-15 23:40:18 -0700669 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200670 SendStatisticsProxy::AdaptationSteps cpu_counts;
671 SendStatisticsProxy::AdaptationSteps quality_counts;
672 quality_counts.num_framerate_reductions = absl::nullopt;
673 quality_counts.num_resolution_reductions = absl::nullopt;
674 statistics_proxy_->OnAdaptationChanged(
675 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
676 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700677 fake_clock_.AdvanceTimeMilliseconds(10000);
678
asapersson09f05612017-05-15 23:40:18 -0700679 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700680 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200681 quality_counts.num_framerate_reductions = 0;
682 statistics_proxy_->OnAdaptationChanged(
683 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
684 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700685 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200686 statistics_proxy_->OnAdaptationChanged(
687 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
688 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700689 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200690 statistics_proxy_->OnAdaptationChanged(
691 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
692 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700693 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200694 statistics_proxy_->OnAdaptationChanged(
695 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
696 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700697
asapersson09f05612017-05-15 23:40:18 -0700698 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200699 quality_counts.num_framerate_reductions = absl::nullopt;
700 statistics_proxy_->OnAdaptationChanged(
701 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
702 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700703 fake_clock_.AdvanceTimeMilliseconds(30000);
704
asapersson09f05612017-05-15 23:40:18 -0700705 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700706 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200707 quality_counts.num_resolution_reductions = 0;
708 statistics_proxy_->OnAdaptationChanged(
709 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
710 quality_counts);
711 statistics_proxy_->OnAdaptationChanged(
712 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
713 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700714 fake_clock_.AdvanceTimeMilliseconds(10000);
715
asapersson09f05612017-05-15 23:40:18 -0700716 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200717 quality_counts.num_resolution_reductions = absl::nullopt;
718 statistics_proxy_->OnAdaptationChanged(
719 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
720 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700721 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200722 statistics_proxy_->OnAdaptationChanged(
723 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
724 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700725 fake_clock_.AdvanceTimeMilliseconds(20000);
726
asapersson0944a802017-04-07 00:57:58 -0700727 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700728 statistics_proxy_.reset();
729 EXPECT_EQ(1,
730 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
731 EXPECT_EQ(
732 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
733}
734
asapersson0944a802017-04-07 00:57:58 -0700735TEST_F(SendStatisticsProxyTest,
736 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
737 // First RTP packet sent.
738 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700739
asapersson0944a802017-04-07 00:57:58 -0700740 // Suspend and resume video.
741 statistics_proxy_->OnSuspendChange(true);
742 fake_clock_.AdvanceTimeMilliseconds(5000);
743 statistics_proxy_->OnSuspendChange(false);
744
745 // Min runtime has passed but scaling not enabled.
746 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
747 statistics_proxy_.reset();
748 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
749 EXPECT_EQ(0,
750 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
751}
752
753TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
754 // First RTP packet sent.
755 UpdateDataCounters(kFirstSsrc);
756
asapersson09f05612017-05-15 23:40:18 -0700757 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200758 SendStatisticsProxy::AdaptationSteps cpu_counts;
759 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700760 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200761 statistics_proxy_->OnAdaptationChanged(
762 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
763 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700764 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200765 statistics_proxy_->OnAdaptationChanged(
766 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
767 quality_counts);
768 statistics_proxy_->OnAdaptationChanged(
769 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
770 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700771
772 // Suspend and resume video.
773 statistics_proxy_->OnSuspendChange(true);
774 fake_clock_.AdvanceTimeMilliseconds(30000);
775 statistics_proxy_->OnSuspendChange(false);
776
777 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200778 statistics_proxy_->OnAdaptationChanged(
779 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
780 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700781 fake_clock_.AdvanceTimeMilliseconds(10000);
782
783 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
784 statistics_proxy_.reset();
785 EXPECT_EQ(1,
786 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
787 EXPECT_EQ(
788 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
789}
790
791TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
792 // First RTP packet sent.
793 UpdateDataCounters(kFirstSsrc);
794
795 // Video not suspended.
796 statistics_proxy_->OnSuspendChange(false);
797 fake_clock_.AdvanceTimeMilliseconds(30000);
798
asapersson09f05612017-05-15 23:40:18 -0700799 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200800 SendStatisticsProxy::AdaptationSteps cpu_counts;
801 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700802 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200803 statistics_proxy_->OnAdaptationChanged(
804 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
805 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700806 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200807 statistics_proxy_->OnAdaptationChanged(
808 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
809 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700810
811 // Video not suspended, stats time already started.
812 statistics_proxy_->OnSuspendChange(false);
813 fake_clock_.AdvanceTimeMilliseconds(10000);
814
asapersson09f05612017-05-15 23:40:18 -0700815 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200816 cpu_counts.num_framerate_reductions = absl::nullopt;
817 cpu_counts.num_resolution_reductions = absl::nullopt;
818 statistics_proxy_->OnAdaptationChanged(
819 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
820 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700821 fake_clock_.AdvanceTimeMilliseconds(30000);
822
823 // Suspend and resume video, stats time not started when scaling not enabled.
824 statistics_proxy_->OnSuspendChange(true);
825 fake_clock_.AdvanceTimeMilliseconds(30000);
826 statistics_proxy_->OnSuspendChange(false);
827 fake_clock_.AdvanceTimeMilliseconds(30000);
828
asapersson09f05612017-05-15 23:40:18 -0700829 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700830 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200831 cpu_counts.num_framerate_reductions = 0;
832 cpu_counts.num_resolution_reductions = 0;
833 statistics_proxy_->OnAdaptationChanged(
834 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
835 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700836 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200837 statistics_proxy_->OnAdaptationChanged(
838 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
839 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700840
841 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
842 statistics_proxy_.reset();
843 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
844 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
845}
846
847TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
848 // First RTP packet sent.
849 UpdateDataCounters(kFirstSsrc);
850
851 // Video suspended.
852 statistics_proxy_->OnSuspendChange(true);
853
asapersson09f05612017-05-15 23:40:18 -0700854 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200855 SendStatisticsProxy::AdaptationSteps cpu_counts;
856 SendStatisticsProxy::AdaptationSteps quality_counts;
857 statistics_proxy_->OnAdaptationChanged(
858 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
859 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700860 fake_clock_.AdvanceTimeMilliseconds(10000);
861
862 // Resume video, stats time started.
863 // Adapt changes: 1, elapsed time: 10 sec.
864 statistics_proxy_->OnSuspendChange(false);
865 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200866 statistics_proxy_->OnAdaptationChanged(
867 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
868 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700869
870 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
871 statistics_proxy_.reset();
872 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
873 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
874}
875
876TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700877 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700878 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200879 SendStatisticsProxy::AdaptationSteps cpu_counts;
880 SendStatisticsProxy::AdaptationSteps quality_counts;
881 statistics_proxy_->OnAdaptationChanged(
882 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
883 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700884 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700885 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700886
asapersson0944a802017-04-07 00:57:58 -0700887 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700888 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200889 statistics_proxy_->OnAdaptationChanged(
890 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
891 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700892 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700893
asapersson0944a802017-04-07 00:57:58 -0700894 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700895 statistics_proxy_.reset();
896 EXPECT_EQ(1,
897 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
898 EXPECT_EQ(
899 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
900}
901
902TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700903 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200904 SendStatisticsProxy::AdaptationSteps cpu_counts;
905 SendStatisticsProxy::AdaptationSteps quality_counts;
906 statistics_proxy_->OnAdaptationChanged(
907 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
908 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700909 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200910 cpu_counts.num_framerate_reductions = absl::nullopt;
911 cpu_counts.num_resolution_reductions = absl::nullopt;
912 statistics_proxy_->OnAdaptationChanged(
913 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
914 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700915
916 // Send first packet, scaling disabled.
917 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700918 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700919 fake_clock_.AdvanceTimeMilliseconds(60000);
920
asapersson09f05612017-05-15 23:40:18 -0700921 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200922 cpu_counts.num_resolution_reductions = 0;
923 statistics_proxy_->OnAdaptationChanged(
924 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
925 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700926 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700927 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700928
asapersson0944a802017-04-07 00:57:58 -0700929 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700930 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200931 statistics_proxy_->OnAdaptationChanged(
932 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
933 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700934
asapersson0944a802017-04-07 00:57:58 -0700935 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700936 statistics_proxy_.reset();
937 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
938 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
939}
940
941TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700942 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700943 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200944 SendStatisticsProxy::AdaptationSteps cpu_counts;
945 SendStatisticsProxy::AdaptationSteps quality_counts;
946 quality_counts.num_framerate_reductions = absl::nullopt;
947 quality_counts.num_resolution_reductions = absl::nullopt;
948 statistics_proxy_->OnAdaptationChanged(
949 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
950 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700951
asapersson0944a802017-04-07 00:57:58 -0700952 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200953 statistics_proxy_->OnAdaptationChanged(
954 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
955 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700956 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200957 statistics_proxy_->OnAdaptationChanged(
958 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
959 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700960 fake_clock_.AdvanceTimeMilliseconds(9000);
961
962 // Switch content type, real-time stats should be updated.
963 VideoEncoderConfig config;
964 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +0200965 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -0700966 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
967 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
968 EXPECT_EQ(0,
969 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
970
asapersson0944a802017-04-07 00:57:58 -0700971 // First RTP packet sent, scaling enabled.
972 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200973 statistics_proxy_->OnAdaptationChanged(
974 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
975 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700976
asapersson0944a802017-04-07 00:57:58 -0700977 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200978 statistics_proxy_->OnAdaptationChanged(
979 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
980 quality_counts);
981 statistics_proxy_->OnAdaptationChanged(
982 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
983 quality_counts);
984 statistics_proxy_->OnAdaptationChanged(
985 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
986 quality_counts);
987 statistics_proxy_->OnAdaptationChanged(
988 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
989 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700990 fake_clock_.AdvanceTimeMilliseconds(120000);
991
992 statistics_proxy_.reset();
993 EXPECT_EQ(1, metrics::NumSamples(
994 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
995 EXPECT_EQ(1, metrics::NumEvents(
996 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
997 EXPECT_EQ(0, metrics::NumSamples(
998 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
999}
1000
asapersson59bac1a2016-01-07 23:36:00 -08001001TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001002 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001003 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1004
Pera48ddb72016-09-29 11:48:50 +02001005 // No switch, stats should not be updated.
1006 VideoEncoderConfig config;
1007 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001008 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001009 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001010
1011 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001012 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001013 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001014 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001015}
1016
asapersson320e45a2016-11-29 01:40:35 -08001017TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1018 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1019 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001020
asapersson320e45a2016-11-29 01:40:35 -08001021 statistics_proxy_.reset();
1022 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1023 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1024 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1025 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1026}
1027
1028TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001029 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001030 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001031 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1032 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1033 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001034 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001035
1036 // Not enough samples, stats should not be updated.
1037 for (int i = 0; i < kMinSamples - 1; ++i) {
1038 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Åsa Persson20317f92018-08-15 08:57:54 +02001039 encoded_image._timeStamp += 90 * 1000 / kFps;
asapersson320e45a2016-11-29 01:40:35 -08001040 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1041 }
Åsa Persson0122e842017-10-16 12:19:23 +02001042 SetUp(); // Reset stats proxy also causes histograms to be reported.
1043 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1044 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1045
1046 // Enough samples, max resolution per frame should be reported.
Åsa Persson20317f92018-08-15 08:57:54 +02001047 encoded_image._timeStamp = 0xffff0000; // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001048 for (int i = 0; i < kMinSamples; ++i) {
1049 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Åsa Persson20317f92018-08-15 08:57:54 +02001050 encoded_image._timeStamp += 90 * 1000 / kFps;
Åsa Persson0122e842017-10-16 12:19:23 +02001051 encoded_image._encodedWidth = kWidth;
1052 encoded_image._encodedHeight = kHeight;
1053 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1054 encoded_image._encodedWidth = kWidth / 2;
1055 encoded_image._encodedHeight = kHeight / 2;
1056 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1057 }
1058
asapersson320e45a2016-11-29 01:40:35 -08001059 statistics_proxy_.reset();
1060 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1061 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1062 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1063 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1064}
1065
1066TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1067 const int kFps = 20;
1068 const int kMinPeriodicSamples = 6;
1069 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1070 for (int i = 0; i <= frames; ++i) {
1071 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1072 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1073 }
1074 statistics_proxy_.reset();
1075 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1076 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1077}
1078
1079TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1080 EncodedImage encoded_image;
1081 const int kFps = 20;
1082 const int kMinPeriodicSamples = 6;
1083 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001084 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001085 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001086 ++encoded_image._timeStamp;
1087 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1088 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001089 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1090 }
1091 statistics_proxy_.reset();
1092 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1093 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1094}
1095
1096TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1097 const int kFps = 20;
1098 const int kSuspendTimeMs = 10000;
1099 const int kMinPeriodicSamples = 6;
1100 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1101 for (int i = 0; i < frames; ++i) {
1102 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1103 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1104 }
1105 // Suspend.
1106 statistics_proxy_->OnSuspendChange(true);
1107 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1108
1109 for (int i = 0; i < frames; ++i) {
1110 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1111 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1112 }
1113 // Suspended time interval should not affect the framerate.
1114 statistics_proxy_.reset();
1115 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1116 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1117}
1118
1119TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1120 EncodedImage encoded_image;
1121 const int kFps = 20;
1122 const int kSuspendTimeMs = 10000;
1123 const int kMinPeriodicSamples = 6;
1124 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001125 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001126 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1127 encoded_image._timeStamp = i + 1;
1128 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1129 }
1130 // Suspend.
1131 statistics_proxy_->OnSuspendChange(true);
1132 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1133
Å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);
1136 encoded_image._timeStamp = i + 1;
1137 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1138 }
1139 // Suspended time interval should not affect the framerate.
1140 statistics_proxy_.reset();
1141 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1142 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1143}
1144
asaperssonf4e44af2017-04-19 02:01:06 -07001145TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001146 SendStatisticsProxy::AdaptationSteps cpu_counts;
1147 SendStatisticsProxy::AdaptationSteps quality_counts;
1148 cpu_counts.num_resolution_reductions = absl::nullopt;
1149 statistics_proxy_->OnAdaptationChanged(
1150 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1151 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001152
1153 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1154 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1155
1156 statistics_proxy_.reset();
1157 EXPECT_EQ(0,
1158 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1159}
1160
1161TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001162 SendStatisticsProxy::AdaptationSteps cpu_counts;
1163 SendStatisticsProxy::AdaptationSteps quality_counts;
1164 cpu_counts.num_resolution_reductions = 0;
1165 statistics_proxy_->OnAdaptationChanged(
1166 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1167 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001168
perkj803d97f2016-11-01 11:45:46 -07001169 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1170 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1171
Niels Möller213618e2018-07-24 09:29:58 +02001172 cpu_counts.num_resolution_reductions = 1;
1173 statistics_proxy_->OnAdaptationChanged(
1174 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1175 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001176
1177 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1178 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1179
1180 statistics_proxy_.reset();
1181 EXPECT_EQ(1,
1182 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1183 EXPECT_EQ(
1184 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1185}
1186
asapersson4374a092016-07-27 00:39:09 -07001187TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1188 const int64_t kTimeSec = 3;
1189 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1190 statistics_proxy_.reset();
1191 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1192 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1193 kTimeSec));
1194}
1195
1196TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1197 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1198 statistics_proxy_.reset();
1199 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1200}
1201
asapersson66d4b372016-12-19 06:50:53 -08001202TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1203 // First RTP packet sent.
1204 UpdateDataCounters(kFirstSsrc);
1205
1206 // Min runtime has passed.
1207 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1208 statistics_proxy_.reset();
1209 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1210 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1211}
1212
1213TEST_F(SendStatisticsProxyTest,
1214 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1215 // First RTP packet sent.
1216 UpdateDataCounters(kFirstSsrc);
1217
1218 // Min runtime has not passed.
1219 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1220 statistics_proxy_.reset();
1221 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1222 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1223}
1224
1225TEST_F(SendStatisticsProxyTest,
1226 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1227 // First RTP packet not sent.
1228 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1229 statistics_proxy_.reset();
1230 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1231}
1232
1233TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1234 // First RTP packet sent and min runtime passed.
1235 UpdateDataCounters(kFirstSsrc);
1236
1237 // No change. Video: 10000 ms, paused: 0 ms (0%).
1238 statistics_proxy_->OnSetEncoderTargetRate(50000);
1239 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1240 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1241
1242 statistics_proxy_.reset();
1243 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1244 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1245 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1246 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1247}
1248
1249TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1250 // First RTP packet sent and min runtime passed.
1251 UpdateDataCounters(kFirstSsrc);
1252
1253 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1254 statistics_proxy_->OnSetEncoderTargetRate(50000);
1255 fake_clock_.AdvanceTimeMilliseconds(7000);
1256 statistics_proxy_->OnSetEncoderTargetRate(0);
1257 fake_clock_.AdvanceTimeMilliseconds(3000);
1258 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1259
1260 statistics_proxy_.reset();
1261 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1262 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1263 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1264 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1265}
1266
1267TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1268 // First RTP packet sent.
1269 UpdateDataCounters(kFirstSsrc);
1270
1271 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1272 statistics_proxy_->OnSetEncoderTargetRate(0);
1273 fake_clock_.AdvanceTimeMilliseconds(1000);
1274 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1275 fake_clock_.AdvanceTimeMilliseconds(7000);
1276 statistics_proxy_->OnSetEncoderTargetRate(60000);
1277 fake_clock_.AdvanceTimeMilliseconds(3000);
1278 statistics_proxy_->OnSetEncoderTargetRate(0);
1279 fake_clock_.AdvanceTimeMilliseconds(250);
1280 statistics_proxy_->OnSetEncoderTargetRate(0);
1281 fake_clock_.AdvanceTimeMilliseconds(750);
1282 statistics_proxy_->OnSetEncoderTargetRate(60000);
1283 fake_clock_.AdvanceTimeMilliseconds(5000);
1284 statistics_proxy_->OnSetEncoderTargetRate(50000);
1285 fake_clock_.AdvanceTimeMilliseconds(4000);
1286 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1287
1288 statistics_proxy_.reset();
1289 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1290 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1291 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1292 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1293}
1294
1295TEST_F(SendStatisticsProxyTest,
1296 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1297 // First RTP packet sent.
1298 UpdateDataCounters(kFirstSsrc);
1299 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1300
1301 // Min runtime has not passed.
1302 statistics_proxy_->OnSetEncoderTargetRate(50000);
1303 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1304 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1305
1306 statistics_proxy_.reset();
1307 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1308}
1309
asapersson118ef002016-03-31 00:00:19 -07001310TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001311 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001312 CodecSpecificInfo codec_info;
1313 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001314
perkj803d97f2016-11-01 11:45:46 -07001315 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001316 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001317 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001318 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1319 codec_info.codecSpecific.VP8.simulcastIdx = 1;
asapersson118ef002016-03-31 00:00:19 -07001320 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001321 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001322 }
1323 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001324 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1325 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1326 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1327 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001328}
1329
1330TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1331 VideoSendStream::Config config(nullptr);
1332 config.rtp.ssrcs.push_back(kFirstSsrc);
1333 statistics_proxy_.reset(new SendStatisticsProxy(
1334 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1335
asapersson118ef002016-03-31 00:00:19 -07001336 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001337 CodecSpecificInfo codec_info;
1338 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001339
perkj803d97f2016-11-01 11:45:46 -07001340 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001341 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001342 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001343 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001344 }
1345 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001346 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1347 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001348}
1349
asapersson5265fed2016-04-18 02:58:47 -07001350TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001351 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001352 CodecSpecificInfo codec_info;
1353 codec_info.codecType = kVideoCodecVP9;
1354 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001355
perkj803d97f2016-11-01 11:45:46 -07001356 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001357 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001358 codec_info.codecSpecific.VP9.spatial_idx = 0;
1359 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001360 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001361 codec_info.codecSpecific.VP9.spatial_idx = 1;
1362 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001363 }
1364 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001365 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1366 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1367 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1368 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001369}
1370
1371TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1372 VideoSendStream::Config config(nullptr);
1373 config.rtp.ssrcs.push_back(kFirstSsrc);
1374 statistics_proxy_.reset(new SendStatisticsProxy(
1375 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1376
asapersson5265fed2016-04-18 02:58:47 -07001377 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001378 CodecSpecificInfo codec_info;
1379 codec_info.codecType = kVideoCodecVP9;
1380 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001381
perkj803d97f2016-11-01 11:45:46 -07001382 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001383 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001384 codec_info.codecSpecific.VP9.spatial_idx = 0;
1385 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001386 }
1387 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001388 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1389 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001390}
1391
asapersson827cab32016-11-02 09:08:47 -07001392TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1393 EncodedImage encoded_image;
1394 CodecSpecificInfo codec_info;
1395 codec_info.codecType = kVideoCodecH264;
1396
1397 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001398 codec_info.codecSpecific.H264.simulcast_idx = 0;
asapersson827cab32016-11-02 09:08:47 -07001399 encoded_image.qp_ = kQpIdx0;
1400 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001401 codec_info.codecSpecific.H264.simulcast_idx = 1;
1402 encoded_image.qp_ = kQpIdx1;
1403 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001404 }
1405 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001406 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1407 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1408 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1409 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001410}
1411
asapersson4ee70462016-10-31 04:05:12 -07001412TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001413 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1414 // Configure one stream.
1415 VideoEncoderConfig config;
1416 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1417 VideoStream stream1;
1418 stream1.width = kWidth;
1419 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001420 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001421
1422 const int64_t kMaxEncodedFrameWindowMs = 800;
1423 const int kFps = 20;
1424 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1425 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1426 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1427
1428 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001429 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001430 encoded_image._encodedWidth = kWidth;
1431 encoded_image._encodedHeight = kHeight;
1432 for (int i = 0; i < kMinSamples; ++i) {
1433 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1434 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001435 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001436 }
asapersson4ee70462016-10-31 04:05:12 -07001437
1438 // Histograms are updated when the statistics_proxy_ is deleted.
1439 statistics_proxy_.reset();
1440 EXPECT_EQ(0, metrics::NumSamples(
1441 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1442 EXPECT_EQ(0, metrics::NumSamples(
1443 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1444}
1445
1446TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001447 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1448 // Configure two streams.
1449 VideoEncoderConfig config;
1450 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1451 VideoStream stream1;
1452 stream1.width = kWidth / 2;
1453 stream1.height = kHeight / 2;
1454 VideoStream stream2;
1455 stream2.width = kWidth;
1456 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001457 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001458
1459 const int64_t kMaxEncodedFrameWindowMs = 800;
1460 const int kFps = 20;
1461 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1462 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1463 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1464
1465 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001466 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001467 for (int i = 0; i < kMinSamples; ++i) {
1468 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1469 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1470 encoded_image._encodedWidth = kWidth;
1471 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001472 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001473 encoded_image._encodedWidth = kWidth / 2;
1474 encoded_image._encodedHeight = kHeight / 2;
1475 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1476 }
asapersson4ee70462016-10-31 04:05:12 -07001477
1478 // Histograms are updated when the statistics_proxy_ is deleted.
1479 statistics_proxy_.reset();
1480 EXPECT_EQ(1, metrics::NumSamples(
1481 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1482 EXPECT_EQ(1, metrics::NumEvents(
1483 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1484 // No resolution disabled.
1485 EXPECT_EQ(0, metrics::NumSamples(
1486 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1487}
1488
1489TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001490 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1491 // Configure two streams.
1492 VideoEncoderConfig config;
1493 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1494 VideoStream stream1;
1495 stream1.width = kWidth / 2;
1496 stream1.height = kHeight / 2;
1497 VideoStream stream2;
1498 stream2.width = kWidth;
1499 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001500 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001501
1502 const int64_t kMaxEncodedFrameWindowMs = 800;
1503 const int kFps = 20;
1504 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1505 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1506 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1507
1508 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001509 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001510 encoded_image._encodedWidth = kWidth / 2;
1511 encoded_image._encodedHeight = kHeight / 2;
1512 for (int i = 0; i < kMinSamples; ++i) {
1513 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1514 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001515 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001516 }
asapersson4ee70462016-10-31 04:05:12 -07001517
1518 // Histograms are updated when the statistics_proxy_ is deleted.
1519 statistics_proxy_.reset();
1520 EXPECT_EQ(1, metrics::NumSamples(
1521 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1522 EXPECT_EQ(1, metrics::NumEvents(
1523 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001524 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001525 EXPECT_EQ(1, metrics::NumSamples(
1526 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001527 EXPECT_EQ(1, metrics::NumEvents(
1528 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001529}
1530
1531TEST_F(SendStatisticsProxyTest,
1532 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001533 SendStatisticsProxy::AdaptationSteps cpu_counts;
1534 SendStatisticsProxy::AdaptationSteps quality_counts;
1535 quality_counts.num_resolution_reductions = absl::nullopt;
1536 statistics_proxy_->OnAdaptationChanged(
1537 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1538 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001539 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001540 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001541 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001542
1543 // Histograms are updated when the statistics_proxy_ is deleted.
1544 statistics_proxy_.reset();
1545 EXPECT_EQ(
1546 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1547 EXPECT_EQ(0, metrics::NumSamples(
1548 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1549}
1550
1551TEST_F(SendStatisticsProxyTest,
1552 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001553 SendStatisticsProxy::AdaptationSteps cpu_counts;
1554 SendStatisticsProxy::AdaptationSteps quality_counts;
1555 quality_counts.num_resolution_reductions = 0;
1556 statistics_proxy_->OnAdaptationChanged(
1557 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1558 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001559 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001560 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001561 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001562
1563 // Histograms are updated when the statistics_proxy_ is deleted.
1564 statistics_proxy_.reset();
1565 EXPECT_EQ(
1566 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1567 EXPECT_EQ(1, metrics::NumEvents(
1568 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1569 // No resolution downscale.
1570 EXPECT_EQ(0, metrics::NumSamples(
1571 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1572}
1573
1574TEST_F(SendStatisticsProxyTest,
1575 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1576 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001577 SendStatisticsProxy::AdaptationSteps cpu_counts;
1578 SendStatisticsProxy::AdaptationSteps quality_counts;
1579 quality_counts.num_resolution_reductions = kDownscales;
1580 statistics_proxy_->OnAdaptationChanged(
1581 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1582 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001583 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001584 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001585 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001586 // Histograms are updated when the statistics_proxy_ is deleted.
1587 statistics_proxy_.reset();
1588 EXPECT_EQ(
1589 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1590 EXPECT_EQ(1, metrics::NumEvents(
1591 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1592 // Resolution downscales.
1593 EXPECT_EQ(1, metrics::NumSamples(
1594 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1595 EXPECT_EQ(
1596 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1597 kDownscales));
1598}
1599
1600TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1601 // Initially false.
1602 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001603
Åsa Perssonaa329e72017-12-15 15:54:44 +01001604 // Configure two streams.
1605 VideoEncoderConfig config;
1606 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1607 VideoStream stream1;
1608 stream1.width = kWidth / 2;
1609 stream1.height = kHeight / 2;
1610 VideoStream stream2;
1611 stream2.width = kWidth;
1612 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001613 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001614
1615 const int64_t kMaxEncodedFrameWindowMs = 800;
1616 const int kFps = 20;
1617 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1618 kFps * kMaxEncodedFrameWindowMs / 1000;
1619
1620 // One stream encoded.
1621 EncodedImage encoded_image;
1622 encoded_image._encodedWidth = kWidth / 2;
1623 encoded_image._encodedHeight = kHeight / 2;
1624 for (int i = 0; i < kMinSamples; ++i) {
1625 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1626 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1627 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1628 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1629 }
1630
1631 // First frame removed from EncodedFrameMap, stats updated.
1632 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1633 ++encoded_image._timeStamp;
kthelgason0cd27ba2016-12-19 06:32:16 -08001634 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1635 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1636
Åsa Perssonaa329e72017-12-15 15:54:44 +01001637 // Two streams encoded.
1638 for (int i = 0; i < kMinSamples; ++i) {
1639 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1640 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1641 encoded_image._encodedWidth = kWidth;
1642 encoded_image._encodedHeight = kHeight;
1643 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1644 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1645 encoded_image._encodedWidth = kWidth / 2;
1646 encoded_image._encodedHeight = kHeight / 2;
1647 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1648 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1649 }
1650
1651 // First frame with two streams removed, expect no resolution limit.
1652 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1653 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001654 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1655 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001656
1657 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02001658 SendStatisticsProxy::AdaptationSteps cpu_counts;
1659 SendStatisticsProxy::AdaptationSteps quality_counts;
1660 quality_counts.num_resolution_reductions = 1;
1661 statistics_proxy_->OnAdaptationChanged(
1662 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1663 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001664 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1665 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1666}
1667
asapersson66d4b372016-12-19 06:50:53 -08001668TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1669 // Initially zero.
1670 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1671
1672 const int kBitrate = 100000;
1673 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1674 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1675
1676 statistics_proxy_->OnSetEncoderTargetRate(0);
1677 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1678}
1679
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001680TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001681 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001682 std::max(
1683 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1684 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1685 config_.rtp.rtx.ssrcs.end())) +
1686 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001687 // From RtcpStatisticsCallback.
1688 RtcpStatistics rtcp_stats;
1689 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001690 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001691
1692 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001693 uint32_t total = 0;
1694 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001695 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001696 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001697
1698 // From FrameCountObserver.
1699 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001700 FrameCounts frame_counts;
1701 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001702 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001703
1704 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1705 EXPECT_TRUE(stats.substreams.empty());
1706}
1707
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001708TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1709 static const int kEncodedWidth = 123;
1710 static const int kEncodedHeight = 81;
1711 EncodedImage encoded_image;
1712 encoded_image._encodedWidth = kEncodedWidth;
1713 encoded_image._encodedHeight = kEncodedHeight;
1714
kjellander02b3d272016-04-20 05:05:54 -07001715 CodecSpecificInfo codec_info;
1716 codec_info.codecType = kVideoCodecVP8;
1717 codec_info.codecSpecific.VP8.simulcastIdx = 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001718
kjellander02b3d272016-04-20 05:05:54 -07001719 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1720 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1721 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001722
1723 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001724 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1725 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1726 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1727 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001728
1729 // Forward almost to timeout, this should not have removed stats.
1730 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1731 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001732 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1733 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001734
1735 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1736 // resolution still times out (no global timeout for all stats).
1737 RtcpStatistics rtcp_statistics;
1738 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1739 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1740
1741 // Report stats for second SSRC to make sure it's not outdated along with the
1742 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001743 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1744 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001745
1746 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1747 // reported, but substream 1 should.
1748 fake_clock_.AdvanceTimeMilliseconds(1);
1749 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001750 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1751 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1752 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1753 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001754}
1755
Peter Boström20f3f942015-05-15 11:33:39 +02001756TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1757 static const int kEncodedWidth = 123;
1758 static const int kEncodedHeight = 81;
1759 EncodedImage encoded_image;
1760 encoded_image._encodedWidth = kEncodedWidth;
1761 encoded_image._encodedHeight = kEncodedHeight;
1762
kjellander02b3d272016-04-20 05:05:54 -07001763 CodecSpecificInfo codec_info;
1764 codec_info.codecType = kVideoCodecVP8;
1765 codec_info.codecSpecific.VP8.simulcastIdx = 0;
Peter Boström20f3f942015-05-15 11:33:39 +02001766
kjellander02b3d272016-04-20 05:05:54 -07001767 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1768 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1769 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001770
1771 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1772 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1773 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1774 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1775 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1776 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1777}
1778
1779TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001780 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001781 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1782 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1783 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1784
1785 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1786
1787 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001788 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001789 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001790 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001791 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1792 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1793 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1794}
1795
sprang07fb9be2016-02-24 07:55:00 -08001796TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1797 RtcpPacketTypeCounterObserver* proxy =
1798 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1799 RtcpPacketTypeCounter counters;
1800 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1801 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1802 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1803
1804 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1805
1806 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1807 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1808 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1809 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1810 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1811
1812 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1813 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1814
1815 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001816 VideoEncoderConfig config;
1817 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001818 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001819
asapersson01d70a32016-05-20 06:29:46 -07001820 EXPECT_EQ(1,
1821 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1822 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1823 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1824 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001825 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1826
1827 const int kRate = 60 * 2; // Packets per minute with two streams.
1828
asapersson01d70a32016-05-20 06:29:46 -07001829 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1830 1 * kRate));
1831 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1832 2 * kRate));
1833 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1834 3 * kRate));
1835 EXPECT_EQ(
1836 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1837 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001838
1839 // New start time but same counter values.
1840 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1841 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1842
1843 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1844
1845 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1846 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1847 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1848 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1849 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1850
1851 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1852 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1853
1854 SetUp(); // Reset stats proxy also causes histograms to be reported.
1855
asapersson01d70a32016-05-20 06:29:46 -07001856 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001857 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001858 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001859 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001860 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001861 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1862 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001863 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001864 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1865
asapersson01d70a32016-05-20 06:29:46 -07001866 EXPECT_EQ(1, metrics::NumEvents(
1867 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1868 1 * kRate));
1869 EXPECT_EQ(1, metrics::NumEvents(
1870 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1871 2 * kRate));
1872 EXPECT_EQ(1, metrics::NumEvents(
1873 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1874 3 * kRate));
1875 EXPECT_EQ(1,
1876 metrics::NumEvents(
1877 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1878 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001879}
1880
asaperssona6a699a2016-11-25 03:52:46 -08001881TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1882 statistics_proxy_.reset(
1883 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1884 VideoEncoderConfig::ContentType::kRealtimeVideo));
1885
1886 StreamDataCountersCallback* proxy =
1887 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1888 StreamDataCounters counters;
1889 proxy->DataCountersUpdated(counters, kFirstSsrc);
1890 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1891
1892 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1893 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1894}
1895
1896TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1897 statistics_proxy_.reset(
1898 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1899 VideoEncoderConfig::ContentType::kRealtimeVideo));
1900
1901 StreamDataCountersCallback* proxy =
1902 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001903 StreamDataCounters counters;
1904 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001905
asapersson93e1e232017-02-06 05:18:35 -08001906 const int kMinRequiredPeriodSamples = 8;
1907 const int kPeriodIntervalMs = 2000;
1908 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1909 counters.transmitted.packets += 20;
1910 counters.transmitted.header_bytes += 500;
1911 counters.transmitted.padding_bytes += 1000;
1912 counters.transmitted.payload_bytes += 2000;
1913 counters.retransmitted.packets += 2;
1914 counters.retransmitted.header_bytes += 25;
1915 counters.retransmitted.padding_bytes += 100;
1916 counters.retransmitted.payload_bytes += 250;
1917 counters.fec = counters.retransmitted;
1918 rtx_counters.transmitted = counters.transmitted;
1919 // Advance one interval and update counters.
1920 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1921 proxy->DataCountersUpdated(counters, kFirstSsrc);
1922 proxy->DataCountersUpdated(counters, kSecondSsrc);
1923 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1924 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1925 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1926 }
asaperssona6a699a2016-11-25 03:52:46 -08001927
asaperssona6a699a2016-11-25 03:52:46 -08001928 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001929 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001930 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001931 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1932 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1933 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1934 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1935 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001936 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001937 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1938 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001939 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001940 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1941 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1942 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1943 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1944 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001945 EXPECT_EQ(1,
1946 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001947 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001948 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001949}
1950
Erik Språng22c2b482016-03-01 09:40:42 +01001951TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1952 StreamDataCountersCallback* proxy =
1953 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1954 StreamDataCounters counters;
1955 StreamDataCounters rtx_counters;
1956 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001957
asapersson93e1e232017-02-06 05:18:35 -08001958 const int kMinRequiredPeriodSamples = 8;
1959 const int kPeriodIntervalMs = 2000;
1960 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1961 counters.transmitted.packets += 20;
1962 counters.transmitted.header_bytes += 500;
1963 counters.transmitted.padding_bytes += 1000;
1964 counters.transmitted.payload_bytes += 2000;
1965 counters.retransmitted.packets += 2;
1966 counters.retransmitted.header_bytes += 25;
1967 counters.retransmitted.padding_bytes += 100;
1968 counters.retransmitted.payload_bytes += 250;
1969 counters.fec = counters.retransmitted;
1970 rtx_counters.transmitted = counters.transmitted;
1971 // Advance one interval and update counters.
1972 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1973 proxy->DataCountersUpdated(counters, kFirstSsrc);
1974 proxy->DataCountersUpdated(counters, kSecondSsrc);
1975 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1976 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1977 }
Erik Språng22c2b482016-03-01 09:40:42 +01001978
1979 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001980 VideoEncoderConfig config;
1981 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001982 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01001983
asapersson93e1e232017-02-06 05:18:35 -08001984 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001985 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001986 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1987 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1988 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1989 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1990 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001991 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001992 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1993 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001994 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001995 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1996 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1997 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1998 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1999 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002000 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002001 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002002 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002003 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002004
asapersson93e1e232017-02-06 05:18:35 -08002005 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002006 // Double counter values, this should result in the same counts as before but
2007 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002008 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2009 counters.transmitted.packets += 20;
2010 counters.transmitted.header_bytes += 500;
2011 counters.transmitted.padding_bytes += 1000;
2012 counters.transmitted.payload_bytes += 2000;
2013 counters.retransmitted.packets += 2;
2014 counters.retransmitted.header_bytes += 25;
2015 counters.retransmitted.padding_bytes += 100;
2016 counters.retransmitted.payload_bytes += 250;
2017 counters.fec = counters.retransmitted;
2018 rtx_counters.transmitted = counters.transmitted;
2019 // Advance one interval and update counters.
2020 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2021 proxy->DataCountersUpdated(counters, kFirstSsrc);
2022 proxy->DataCountersUpdated(counters, kSecondSsrc);
2023 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2024 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2025 }
Erik Språng22c2b482016-03-01 09:40:42 +01002026
asapersson93e1e232017-02-06 05:18:35 -08002027 // Reset stats proxy also causes histograms to be reported.
2028 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002029
asapersson93e1e232017-02-06 05:18:35 -08002030 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002031 EXPECT_EQ(1,
2032 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002033 EXPECT_EQ(
2034 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2035 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2036 EXPECT_EQ(
2037 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2038 EXPECT_EQ(1, metrics::NumEvents(
2039 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2040 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002041 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002042 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002043 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002044 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2045 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002046 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002047 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002048 EXPECT_EQ(1, metrics::NumEvents(
2049 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2050 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2051 EXPECT_EQ(
2052 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2053 EXPECT_EQ(1, metrics::NumEvents(
2054 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2055 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002056 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002057 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002058 EXPECT_EQ(1,
2059 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002060 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2061}
Erik Språng22c2b482016-03-01 09:40:42 +01002062
asapersson93e1e232017-02-06 05:18:35 -08002063TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2064 StreamDataCountersCallback* proxy =
2065 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2066 StreamDataCounters counters;
2067 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002068
asapersson93e1e232017-02-06 05:18:35 -08002069 const int kMinRequiredPeriodSamples = 8;
2070 const int kPeriodIntervalMs = 2000;
2071 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2072 counters.transmitted.packets += 20;
2073 counters.transmitted.header_bytes += 500;
2074 counters.transmitted.payload_bytes += 2000;
2075 counters.fec = counters.retransmitted;
2076 // Advance one interval and update counters.
2077 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2078 proxy->DataCountersUpdated(counters, kFirstSsrc);
2079 }
2080
2081 // RTX enabled. No data sent over RTX.
2082 statistics_proxy_.reset();
2083 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2084 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2085}
2086
2087TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2088 VideoSendStream::Config config(nullptr);
2089 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2090 statistics_proxy_.reset(new SendStatisticsProxy(
2091 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2092
2093 StreamDataCountersCallback* proxy =
2094 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2095 StreamDataCounters counters;
2096
2097 const int kMinRequiredPeriodSamples = 8;
2098 const int kPeriodIntervalMs = 2000;
2099 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2100 counters.transmitted.packets += 20;
2101 counters.transmitted.header_bytes += 500;
2102 counters.transmitted.payload_bytes += 2000;
2103 counters.fec = counters.retransmitted;
2104 // Advance one interval and update counters.
2105 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2106 proxy->DataCountersUpdated(counters, kFirstSsrc);
2107 }
2108
2109 // RTX not enabled.
2110 statistics_proxy_.reset();
2111 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2112}
2113
2114TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2115 StreamDataCountersCallback* proxy =
2116 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2117 StreamDataCounters counters;
2118 StreamDataCounters rtx_counters;
2119
2120 const int kMinRequiredPeriodSamples = 8;
2121 const int kPeriodIntervalMs = 2000;
2122 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2123 counters.transmitted.packets += 20;
2124 counters.transmitted.header_bytes += 500;
2125 counters.transmitted.payload_bytes += 2000;
2126 // Advance one interval and update counters.
2127 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2128 proxy->DataCountersUpdated(counters, kFirstSsrc);
2129 }
2130
2131 // FEC enabled. No FEC data sent.
2132 statistics_proxy_.reset();
2133 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2134 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2135}
2136
2137TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2138 VideoSendStream::Config config(nullptr);
2139 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2140 statistics_proxy_.reset(new SendStatisticsProxy(
2141 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2142
2143 StreamDataCountersCallback* proxy =
2144 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2145 StreamDataCounters counters;
2146
2147 const int kMinRequiredPeriodSamples = 8;
2148 const int kPeriodIntervalMs = 2000;
2149 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2150 counters.transmitted.packets += 20;
2151 counters.transmitted.header_bytes += 500;
2152 counters.transmitted.payload_bytes += 2000;
2153 counters.fec = counters.retransmitted;
2154 // Advance one interval and update counters.
2155 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2156 proxy->DataCountersUpdated(counters, kFirstSsrc);
2157 }
2158
2159 // FEC not enabled.
2160 statistics_proxy_.reset();
2161 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002162}
2163
asapersson8d75ac72017-09-15 06:41:15 -07002164TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
2165 const char* kName = "encoderName";
2166 EncodedImage encoded_image;
2167 CodecSpecificInfo codec_info;
2168 codec_info.codec_name = kName;
2169 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2170 EXPECT_STREQ(
2171 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str());
2172}
2173
2174class ForcedFallbackTest : public SendStatisticsProxyTest {
2175 public:
2176 explicit ForcedFallbackTest(const std::string& field_trials)
2177 : SendStatisticsProxyTest(field_trials) {
2178 codec_info_.codecType = kVideoCodecVP8;
2179 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
2180 codec_info_.codecSpecific.VP8.temporalIdx = 0;
2181 codec_info_.codec_name = "fake_codec";
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002182 encoded_image_._encodedWidth = kWidth;
2183 encoded_image_._encodedHeight = kHeight;
asapersson8d75ac72017-09-15 06:41:15 -07002184 }
2185
2186 ~ForcedFallbackTest() override {}
2187
2188 protected:
2189 void InsertEncodedFrames(int num_frames, int interval_ms) {
2190 // First frame is not updating stats, insert initial frame.
2191 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2192 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2193 }
2194 for (int i = 0; i < num_frames; ++i) {
2195 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2196 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2197 }
2198 // Add frame to include last time interval.
2199 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2200 }
2201
2202 EncodedImage encoded_image_;
2203 CodecSpecificInfo codec_info_;
2204 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2205 const int kFrameIntervalMs = 1000;
2206 const int kMinFrames = 20; // Min run time 20 sec.
2207};
2208
2209class ForcedFallbackDisabled : public ForcedFallbackTest {
2210 public:
2211 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002212 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2213 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002214};
2215
2216class ForcedFallbackEnabled : public ForcedFallbackTest {
2217 public:
2218 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002219 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2220 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002221};
2222
2223TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2224 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2225 statistics_proxy_.reset();
2226 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2227 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2228}
2229
2230TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2231 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002232 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002233 statistics_proxy_.reset();
2234 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2235 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2236 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2237 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2238}
2239
2240TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2241 codec_info_.codecType = kVideoCodecVP9;
2242 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2243 statistics_proxy_.reset();
2244 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2245 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2246}
2247
2248TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2249 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2250 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2251 statistics_proxy_.reset();
2252 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2253 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2254}
2255
2256TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
2257 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
2258 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2259 statistics_proxy_.reset();
2260 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2261 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2262}
2263
2264TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2265 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2266 statistics_proxy_.reset();
2267 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2268 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2269}
2270
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002271TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2272 InsertEncodedFrames(1, kFrameIntervalMs);
2273 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2274}
2275
2276TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2277 InsertEncodedFrames(1, kFrameIntervalMs);
2278 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2279}
2280
2281TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
2282 codec_info_.codec_name = "libvpx";
2283 InsertEncodedFrames(1, kFrameIntervalMs);
2284 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2285}
2286
2287TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2288 encoded_image_._encodedWidth = kWidth + 1;
2289 InsertEncodedFrames(1, kFrameIntervalMs);
2290 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2291}
2292
2293TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
2294 codec_info_.codec_name = "libvpx";
2295 InsertEncodedFrames(1, kFrameIntervalMs);
2296 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2297}
2298
2299TEST_F(ForcedFallbackDisabled,
2300 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2301 encoded_image_._encodedWidth = kWidth + 1;
2302 statistics_proxy_->OnMinPixelLimitReached();
2303 InsertEncodedFrames(1, kFrameIntervalMs);
2304 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2305}
2306
asapersson8d75ac72017-09-15 06:41:15 -07002307TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2308 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002309 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002310 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002311 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002312 codec_info_.codec_name = "libvpx";
2313 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002314 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002315
2316 statistics_proxy_.reset();
2317 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2318 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2319 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2320 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2321}
2322
2323TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2324 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2325 const int kMaxFrameDiffMs = 2000;
2326
2327 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2328 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002329 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002330 codec_info_.codec_name = "libvpx";
2331 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002332 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002333 codec_info_.codec_name = "notlibvpx";
2334 InsertEncodedFrames(20, 1000);
2335 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2336 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002337 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002338 codec_info_.codec_name = "notlibvpx2";
2339 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002340 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002341 codec_info_.codec_name = "libvpx";
2342 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002343 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002344
2345 statistics_proxy_.reset();
2346 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2347 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2348 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2349 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2350}
2351
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002352TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2353 encoded_image_._encodedWidth = kWidth + 1;
asapersson8d75ac72017-09-15 06:41:15 -07002354 codec_info_.codec_name = "libvpx";
2355 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2356
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002357 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002358 statistics_proxy_.reset();
2359 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2360 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2361}
2362
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002363TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2364 encoded_image_._encodedWidth = kWidth;
asapersson8d75ac72017-09-15 06:41:15 -07002365 codec_info_.codec_name = "libvpx";
2366 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2367
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002368 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002369 statistics_proxy_.reset();
2370 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2371 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2372}
2373
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002374} // namespace webrtc