blob: 1e367957be770f260dc081352fc37519319f36af [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
Steve Antonbd631a02019-03-28 10:51:27 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 10:51:27 -070019#include "absl/algorithm/container.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070021#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000023
24namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070025namespace {
26const uint32_t kFirstSsrc = 17;
27const uint32_t kSecondSsrc = 42;
28const uint32_t kFirstRtxSsrc = 18;
29const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080030const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080031const int kFpsPeriodicIntervalMs = 2000;
32const int kWidth = 640;
33const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070034const int kQpIdx0 = 21;
35const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010036const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080037const CodecSpecificInfo kDefaultCodecInfo = []() {
38 CodecSpecificInfo codec_info;
39 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080040 return codec_info;
41}();
asapersson5265fed2016-04-18 02:58:47 -070042} // namespace
sprang07fb9be2016-02-24 07:55:00 -080043
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000044class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000045 public:
asapersson8d75ac72017-09-15 06:41:15 -070046 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
47 explicit SendStatisticsProxyTest(const std::string& field_trials)
48 : override_field_trials_(field_trials),
49 fake_clock_(1234),
50 config_(GetTestConfig()),
51 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070052 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000053 virtual ~SendStatisticsProxyTest() {}
54
55 protected:
56 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070057 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080058 statistics_proxy_.reset(new SendStatisticsProxy(
59 &fake_clock_, GetTestConfig(),
60 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000061 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070062 for (const auto& ssrc : config_.rtp.ssrcs)
63 expected_.substreams[ssrc].is_rtx = false;
64 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
65 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000066 }
67
68 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070069 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080070 config.rtp.ssrcs.push_back(kFirstSsrc);
71 config.rtp.ssrcs.push_back(kSecondSsrc);
72 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
73 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070074 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000075 return config;
76 }
77
asaperssona6a699a2016-11-25 03:52:46 -080078 VideoSendStream::Config GetTestConfigWithFlexFec() {
79 VideoSendStream::Config config(nullptr);
80 config.rtp.ssrcs.push_back(kFirstSsrc);
81 config.rtp.ssrcs.push_back(kSecondSsrc);
82 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
83 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080084 config.rtp.flexfec.payload_type = 50;
85 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080086 return config;
87 }
88
89 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
90 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
91 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
92 stats.substreams.find(ssrc);
93 EXPECT_NE(it, stats.substreams.end());
94 return it->second;
95 }
96
asapersson66d4b372016-12-19 06:50:53 -080097 void UpdateDataCounters(uint32_t ssrc) {
98 StreamDataCountersCallback* proxy =
99 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
100 StreamDataCounters counters;
101 proxy->DataCountersUpdated(counters, ssrc);
102 }
103
sprang@webrtc.org09315702014-02-07 12:06:29 +0000104 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000105 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
106 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000107 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000108 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000109
110 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000111 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000112 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000113 it != one.substreams.end(); ++it) {
114 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
115 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000116 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000117 const VideoSendStream::StreamStats& a = it->second;
118 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000119
asapersson2e5cfcd2016-08-11 08:41:18 -0700120 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000121 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
122 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000123 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000124 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
125 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000126
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000127 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
128 b.rtp_stats.transmitted.payload_bytes);
129 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
130 b.rtp_stats.transmitted.header_bytes);
131 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
132 b.rtp_stats.transmitted.padding_bytes);
133 EXPECT_EQ(a.rtp_stats.transmitted.packets,
134 b.rtp_stats.transmitted.packets);
135 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
136 b.rtp_stats.retransmitted.packets);
137 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000138
139 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700140 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
141 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
142 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000143 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
144 }
145 }
146
asapersson8d75ac72017-09-15 06:41:15 -0700147 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000148 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800149 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000150 VideoSendStream::Config config_;
151 int avg_delay_ms_;
152 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000153 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000154 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
155 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156};
157
158TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
159 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700160 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000161 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000162
163 // Add statistics with some arbitrary, but unique, numbers.
164 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700165 ssrc_stats.rtcp_stats.packets_lost = offset;
166 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000167 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
168 ssrc_stats.rtcp_stats.jitter = offset + 3;
169 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
170 }
asapersson35151f32016-05-02 23:44:01 -0700171 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000172 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000174 // Add statistics with some arbitrary, but unique, numbers.
175 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700176 ssrc_stats.rtcp_stats.packets_lost = offset;
177 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000178 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
179 ssrc_stats.rtcp_stats.jitter = offset + 3;
180 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
181 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000183 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184}
185
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000186TEST_F(SendStatisticsProxyTest, Suspended) {
187 // Verify that the value is false by default.
188 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
189
190 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200191 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000192 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
193
194 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200195 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000196 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
197}
198
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000199TEST_F(SendStatisticsProxyTest, FrameCounts) {
200 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700201 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000202 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000203 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
204 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000205 FrameCounts frame_counts;
206 frame_counts.key_frames = offset;
207 frame_counts.delta_frames = offset + 1;
208 stats.frame_counts = frame_counts;
209 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000210 }
asapersson35151f32016-05-02 23:44:01 -0700211 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000212 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000213 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
214 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000215 FrameCounts frame_counts;
216 frame_counts.key_frames = offset;
217 frame_counts.delta_frames = offset + 1;
218 stats.frame_counts = frame_counts;
219 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000220 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000221
222 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000223 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224}
225
226TEST_F(SendStatisticsProxyTest, DataCounters) {
227 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700228 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000229 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
230 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000231 size_t offset = ssrc * sizeof(StreamDataCounters);
232 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000233 counters.transmitted.payload_bytes = offset;
234 counters.transmitted.header_bytes = offset + 1;
235 counters.fec.packets = offset_uint32 + 2;
236 counters.transmitted.padding_bytes = offset + 3;
237 counters.retransmitted.packets = offset_uint32 + 4;
238 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000239 callback->DataCountersUpdated(counters, ssrc);
240 }
asapersson35151f32016-05-02 23:44:01 -0700241 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000242 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
243 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000244 size_t offset = ssrc * sizeof(StreamDataCounters);
245 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000246 counters.transmitted.payload_bytes = offset;
247 counters.transmitted.header_bytes = offset + 1;
248 counters.fec.packets = offset_uint32 + 2;
249 counters.transmitted.padding_bytes = offset + 3;
250 counters.retransmitted.packets = offset_uint32 + 4;
251 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000252 callback->DataCountersUpdated(counters, ssrc);
253 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000254
255 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000256 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000257}
258
259TEST_F(SendStatisticsProxyTest, Bitrate) {
260 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700261 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700262 uint32_t total;
263 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000264 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700265 total = ssrc;
266 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000267 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700268 expected_.substreams[ssrc].total_bitrate_bps = total;
269 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000270 }
asapersson35151f32016-05-02 23:44:01 -0700271 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700272 uint32_t total;
273 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000274 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700275 total = ssrc;
276 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000277 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700278 expected_.substreams[ssrc].total_bitrate_bps = total;
279 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000281
282 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000283 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000284}
285
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000286TEST_F(SendStatisticsProxyTest, SendSideDelay) {
287 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700288 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000289 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
290 // stream.
291 int avg_delay_ms = ssrc;
292 int max_delay_ms = ssrc + 1;
293 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
294 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
295 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
296 }
asapersson35151f32016-05-02 23:44:01 -0700297 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000298 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
299 // stream.
300 int avg_delay_ms = ssrc;
301 int max_delay_ms = ssrc + 1;
302 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
303 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
304 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
305 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000306 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000307 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000308}
309
Peter Boströme4499152016-02-05 11:13:28 +0100310TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800311 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200312 int encode_usage_percent = 80;
313 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
314 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800315
316 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
317 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200318 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800319}
320
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);
Niels Möller23775882018-08-16 10:24:12 +02001039 encoded_image.SetTimestamp(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.
Niels Möller23775882018-08-16 10:24:12 +02001047 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001048 for (int i = 0; i < kMinSamples; ++i) {
1049 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001050 encoded_image.SetTimestamp(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);
Niels Möller23775882018-08-16 10:24:12 +02001086 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001087 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);
Niels Möller23775882018-08-16 10:24:12 +02001127 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001128 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);
Niels Möller23775882018-08-16 10:24:12 +02001136 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001137 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1138 }
1139 // 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) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001316 encoded_image.SetSpatialIndex(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);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001319 encoded_image.SetSpatialIndex(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) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001341 encoded_image.SetSpatialIndex(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;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001358 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001359 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001360 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001361 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001362 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 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001385 }
1386 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001387 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1388 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001389}
1390
asapersson827cab32016-11-02 09:08:47 -07001391TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1392 EncodedImage encoded_image;
1393 CodecSpecificInfo codec_info;
1394 codec_info.codecType = kVideoCodecH264;
1395
1396 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001397 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001398 encoded_image.qp_ = kQpIdx0;
1399 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001400 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001401 encoded_image.qp_ = kQpIdx1;
1402 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001403 }
1404 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001405 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1406 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1407 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1408 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001409}
1410
asapersson4ee70462016-10-31 04:05:12 -07001411TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001412 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1413 // Configure one stream.
1414 VideoEncoderConfig config;
1415 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1416 VideoStream stream1;
1417 stream1.width = kWidth;
1418 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001419 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001420
1421 const int64_t kMaxEncodedFrameWindowMs = 800;
1422 const int kFps = 20;
1423 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1424 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1425 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1426
1427 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001428 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001429 encoded_image._encodedWidth = kWidth;
1430 encoded_image._encodedHeight = kHeight;
1431 for (int i = 0; i < kMinSamples; ++i) {
1432 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001433 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1434 (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);
Niels Möller23775882018-08-16 10:24:12 +02001469 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1470 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001471 encoded_image._encodedWidth = kWidth;
1472 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001473 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001474 encoded_image._encodedWidth = kWidth / 2;
1475 encoded_image._encodedHeight = kHeight / 2;
1476 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1477 }
asapersson4ee70462016-10-31 04:05:12 -07001478
1479 // Histograms are updated when the statistics_proxy_ is deleted.
1480 statistics_proxy_.reset();
1481 EXPECT_EQ(1, metrics::NumSamples(
1482 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1483 EXPECT_EQ(1, metrics::NumEvents(
1484 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1485 // No resolution disabled.
1486 EXPECT_EQ(0, metrics::NumSamples(
1487 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1488}
1489
1490TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001491 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1492 // Configure two streams.
1493 VideoEncoderConfig config;
1494 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1495 VideoStream stream1;
1496 stream1.width = kWidth / 2;
1497 stream1.height = kHeight / 2;
1498 VideoStream stream2;
1499 stream2.width = kWidth;
1500 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001501 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001502
1503 const int64_t kMaxEncodedFrameWindowMs = 800;
1504 const int kFps = 20;
1505 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1506 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1507 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1508
1509 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001510 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001511 encoded_image._encodedWidth = kWidth / 2;
1512 encoded_image._encodedHeight = kHeight / 2;
1513 for (int i = 0; i < kMinSamples; ++i) {
1514 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001515 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1516 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001517 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001518 }
asapersson4ee70462016-10-31 04:05:12 -07001519
1520 // Histograms are updated when the statistics_proxy_ is deleted.
1521 statistics_proxy_.reset();
1522 EXPECT_EQ(1, metrics::NumSamples(
1523 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1524 EXPECT_EQ(1, metrics::NumEvents(
1525 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001526 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001527 EXPECT_EQ(1, metrics::NumSamples(
1528 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001529 EXPECT_EQ(1, metrics::NumEvents(
1530 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001531}
1532
1533TEST_F(SendStatisticsProxyTest,
1534 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001535 SendStatisticsProxy::AdaptationSteps cpu_counts;
1536 SendStatisticsProxy::AdaptationSteps quality_counts;
1537 quality_counts.num_resolution_reductions = absl::nullopt;
1538 statistics_proxy_->OnAdaptationChanged(
1539 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1540 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001541 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001542 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001543 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001544 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001545
1546 // Histograms are updated when the statistics_proxy_ is deleted.
1547 statistics_proxy_.reset();
1548 EXPECT_EQ(
1549 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1550 EXPECT_EQ(0, metrics::NumSamples(
1551 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1552}
1553
1554TEST_F(SendStatisticsProxyTest,
1555 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001556 SendStatisticsProxy::AdaptationSteps cpu_counts;
1557 SendStatisticsProxy::AdaptationSteps quality_counts;
1558 quality_counts.num_resolution_reductions = 0;
1559 statistics_proxy_->OnAdaptationChanged(
1560 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1561 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001562 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001563 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001564 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001565 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001566
1567 // Histograms are updated when the statistics_proxy_ is deleted.
1568 statistics_proxy_.reset();
1569 EXPECT_EQ(
1570 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1571 EXPECT_EQ(1, metrics::NumEvents(
1572 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1573 // No resolution downscale.
1574 EXPECT_EQ(0, metrics::NumSamples(
1575 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1576}
1577
1578TEST_F(SendStatisticsProxyTest,
1579 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1580 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001581 SendStatisticsProxy::AdaptationSteps cpu_counts;
1582 SendStatisticsProxy::AdaptationSteps quality_counts;
1583 quality_counts.num_resolution_reductions = kDownscales;
1584 statistics_proxy_->OnAdaptationChanged(
1585 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1586 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001587 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001588 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001589 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001590 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001591 // Histograms are updated when the statistics_proxy_ is deleted.
1592 statistics_proxy_.reset();
1593 EXPECT_EQ(
1594 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1595 EXPECT_EQ(1, metrics::NumEvents(
1596 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1597 // Resolution downscales.
1598 EXPECT_EQ(1, metrics::NumSamples(
1599 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1600 EXPECT_EQ(
1601 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1602 kDownscales));
1603}
1604
1605TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1606 // Initially false.
1607 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001608
Åsa Perssonaa329e72017-12-15 15:54:44 +01001609 // Configure two streams.
1610 VideoEncoderConfig config;
1611 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1612 VideoStream stream1;
1613 stream1.width = kWidth / 2;
1614 stream1.height = kHeight / 2;
1615 VideoStream stream2;
1616 stream2.width = kWidth;
1617 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001618 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001619
1620 const int64_t kMaxEncodedFrameWindowMs = 800;
1621 const int kFps = 20;
1622 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1623 kFps * kMaxEncodedFrameWindowMs / 1000;
1624
1625 // One stream encoded.
1626 EncodedImage encoded_image;
1627 encoded_image._encodedWidth = kWidth / 2;
1628 encoded_image._encodedHeight = kHeight / 2;
1629 for (int i = 0; i < kMinSamples; ++i) {
1630 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001631 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1632 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001633 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1634 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1635 }
1636
1637 // First frame removed from EncodedFrameMap, stats updated.
1638 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001639 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08001640 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1641 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1642
Åsa Perssonaa329e72017-12-15 15:54:44 +01001643 // Two streams encoded.
1644 for (int i = 0; i < kMinSamples; ++i) {
1645 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001646 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1647 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001648 encoded_image._encodedWidth = kWidth;
1649 encoded_image._encodedHeight = kHeight;
1650 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1651 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1652 encoded_image._encodedWidth = kWidth / 2;
1653 encoded_image._encodedHeight = kHeight / 2;
1654 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1655 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1656 }
1657
1658 // First frame with two streams removed, expect no resolution limit.
1659 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001660 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1661 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001662 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1663 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001664
1665 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02001666 SendStatisticsProxy::AdaptationSteps cpu_counts;
1667 SendStatisticsProxy::AdaptationSteps quality_counts;
1668 quality_counts.num_resolution_reductions = 1;
1669 statistics_proxy_->OnAdaptationChanged(
1670 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1671 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001672 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1673 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1674}
1675
asapersson66d4b372016-12-19 06:50:53 -08001676TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1677 // Initially zero.
1678 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1679
1680 const int kBitrate = 100000;
1681 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1682 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1683
1684 statistics_proxy_->OnSetEncoderTargetRate(0);
1685 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1686}
1687
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001688TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001689 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07001690 std::max(*absl::c_max_element(config_.rtp.ssrcs),
1691 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001692 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001693 // From RtcpStatisticsCallback.
1694 RtcpStatistics rtcp_stats;
1695 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001696 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001697
1698 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001699 uint32_t total = 0;
1700 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001701 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001702 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001703
1704 // From FrameCountObserver.
1705 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001706 FrameCounts frame_counts;
1707 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001708 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001709
1710 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1711 EXPECT_TRUE(stats.substreams.empty());
1712}
1713
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001714TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1715 static const int kEncodedWidth = 123;
1716 static const int kEncodedHeight = 81;
1717 EncodedImage encoded_image;
1718 encoded_image._encodedWidth = kEncodedWidth;
1719 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001720 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001721
kjellander02b3d272016-04-20 05:05:54 -07001722 CodecSpecificInfo codec_info;
1723 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001724
kjellander02b3d272016-04-20 05:05:54 -07001725 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001726 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001727 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001728
1729 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001730 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1731 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1732 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1733 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001734
1735 // Forward almost to timeout, this should not have removed stats.
1736 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1737 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001738 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1739 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001740
1741 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1742 // resolution still times out (no global timeout for all stats).
1743 RtcpStatistics rtcp_statistics;
1744 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1745 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1746
1747 // Report stats for second SSRC to make sure it's not outdated along with the
1748 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001749 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001750
1751 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1752 // reported, but substream 1 should.
1753 fake_clock_.AdvanceTimeMilliseconds(1);
1754 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001755 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1756 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1757 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1758 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001759}
1760
Peter Boström20f3f942015-05-15 11:33:39 +02001761TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1762 static const int kEncodedWidth = 123;
1763 static const int kEncodedHeight = 81;
1764 EncodedImage encoded_image;
1765 encoded_image._encodedWidth = kEncodedWidth;
1766 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001767 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02001768
kjellander02b3d272016-04-20 05:05:54 -07001769 CodecSpecificInfo codec_info;
1770 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02001771
kjellander02b3d272016-04-20 05:05:54 -07001772 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001773 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001774 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001775
1776 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1777 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1778 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1779 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1780 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1781 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1782}
1783
1784TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001785 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001786 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1787 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1788 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1789
1790 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1791
1792 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001793 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001794 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001795 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001796 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1797 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1798 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1799}
1800
sprang07fb9be2016-02-24 07:55:00 -08001801TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1802 RtcpPacketTypeCounterObserver* proxy =
1803 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1804 RtcpPacketTypeCounter counters;
1805 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1806 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1807 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1808
1809 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1810
1811 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1812 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1813 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1814 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1815 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1816
1817 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1818 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1819
1820 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001821 VideoEncoderConfig config;
1822 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001823 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001824
asapersson01d70a32016-05-20 06:29:46 -07001825 EXPECT_EQ(1,
1826 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1827 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1828 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1829 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001830 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1831
1832 const int kRate = 60 * 2; // Packets per minute with two streams.
1833
asapersson01d70a32016-05-20 06:29:46 -07001834 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1835 1 * kRate));
1836 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1837 2 * kRate));
1838 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1839 3 * kRate));
1840 EXPECT_EQ(
1841 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1842 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001843
1844 // New start time but same counter values.
1845 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1846 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1847
1848 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1849
1850 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1851 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1852 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1853 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1854 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1855
1856 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1857 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1858
1859 SetUp(); // Reset stats proxy also causes histograms to be reported.
1860
asapersson01d70a32016-05-20 06:29:46 -07001861 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001862 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001863 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001864 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001865 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001866 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1867 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001868 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001869 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1870
asapersson01d70a32016-05-20 06:29:46 -07001871 EXPECT_EQ(1, metrics::NumEvents(
1872 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1873 1 * kRate));
1874 EXPECT_EQ(1, metrics::NumEvents(
1875 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1876 2 * kRate));
1877 EXPECT_EQ(1, metrics::NumEvents(
1878 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1879 3 * kRate));
1880 EXPECT_EQ(1,
1881 metrics::NumEvents(
1882 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1883 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001884}
1885
asaperssona6a699a2016-11-25 03:52:46 -08001886TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1887 statistics_proxy_.reset(
1888 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1889 VideoEncoderConfig::ContentType::kRealtimeVideo));
1890
1891 StreamDataCountersCallback* proxy =
1892 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1893 StreamDataCounters counters;
1894 proxy->DataCountersUpdated(counters, kFirstSsrc);
1895 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1896
1897 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1898 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1899}
1900
1901TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1902 statistics_proxy_.reset(
1903 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1904 VideoEncoderConfig::ContentType::kRealtimeVideo));
1905
1906 StreamDataCountersCallback* proxy =
1907 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001908 StreamDataCounters counters;
1909 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001910
asapersson93e1e232017-02-06 05:18:35 -08001911 const int kMinRequiredPeriodSamples = 8;
1912 const int kPeriodIntervalMs = 2000;
1913 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1914 counters.transmitted.packets += 20;
1915 counters.transmitted.header_bytes += 500;
1916 counters.transmitted.padding_bytes += 1000;
1917 counters.transmitted.payload_bytes += 2000;
1918 counters.retransmitted.packets += 2;
1919 counters.retransmitted.header_bytes += 25;
1920 counters.retransmitted.padding_bytes += 100;
1921 counters.retransmitted.payload_bytes += 250;
1922 counters.fec = counters.retransmitted;
1923 rtx_counters.transmitted = counters.transmitted;
1924 // Advance one interval and update counters.
1925 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1926 proxy->DataCountersUpdated(counters, kFirstSsrc);
1927 proxy->DataCountersUpdated(counters, kSecondSsrc);
1928 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1929 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1930 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1931 }
asaperssona6a699a2016-11-25 03:52:46 -08001932
asaperssona6a699a2016-11-25 03:52:46 -08001933 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001934 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001935 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001936 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1937 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1938 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1939 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1940 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001941 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001942 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1943 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001944 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001945 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1946 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1947 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1948 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1949 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001950 EXPECT_EQ(1,
1951 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001952 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001953 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001954}
1955
Erik Språng22c2b482016-03-01 09:40:42 +01001956TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1957 StreamDataCountersCallback* proxy =
1958 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1959 StreamDataCounters counters;
1960 StreamDataCounters rtx_counters;
1961 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001962
asapersson93e1e232017-02-06 05:18:35 -08001963 const int kMinRequiredPeriodSamples = 8;
1964 const int kPeriodIntervalMs = 2000;
1965 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1966 counters.transmitted.packets += 20;
1967 counters.transmitted.header_bytes += 500;
1968 counters.transmitted.padding_bytes += 1000;
1969 counters.transmitted.payload_bytes += 2000;
1970 counters.retransmitted.packets += 2;
1971 counters.retransmitted.header_bytes += 25;
1972 counters.retransmitted.padding_bytes += 100;
1973 counters.retransmitted.payload_bytes += 250;
1974 counters.fec = counters.retransmitted;
1975 rtx_counters.transmitted = counters.transmitted;
1976 // Advance one interval and update counters.
1977 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1978 proxy->DataCountersUpdated(counters, kFirstSsrc);
1979 proxy->DataCountersUpdated(counters, kSecondSsrc);
1980 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1981 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1982 }
Erik Språng22c2b482016-03-01 09:40:42 +01001983
1984 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001985 VideoEncoderConfig config;
1986 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001987 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01001988
asapersson93e1e232017-02-06 05:18:35 -08001989 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001990 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001991 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1992 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1993 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1994 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1995 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001996 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001997 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1998 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001999 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002000 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2001 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2002 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2003 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2004 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002005 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002006 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002007 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002008 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002009
asapersson93e1e232017-02-06 05:18:35 -08002010 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002011 // Double counter values, this should result in the same counts as before but
2012 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002013 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2014 counters.transmitted.packets += 20;
2015 counters.transmitted.header_bytes += 500;
2016 counters.transmitted.padding_bytes += 1000;
2017 counters.transmitted.payload_bytes += 2000;
2018 counters.retransmitted.packets += 2;
2019 counters.retransmitted.header_bytes += 25;
2020 counters.retransmitted.padding_bytes += 100;
2021 counters.retransmitted.payload_bytes += 250;
2022 counters.fec = counters.retransmitted;
2023 rtx_counters.transmitted = counters.transmitted;
2024 // Advance one interval and update counters.
2025 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2026 proxy->DataCountersUpdated(counters, kFirstSsrc);
2027 proxy->DataCountersUpdated(counters, kSecondSsrc);
2028 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2029 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2030 }
Erik Språng22c2b482016-03-01 09:40:42 +01002031
asapersson93e1e232017-02-06 05:18:35 -08002032 // Reset stats proxy also causes histograms to be reported.
2033 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002034
asapersson93e1e232017-02-06 05:18:35 -08002035 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002036 EXPECT_EQ(1,
2037 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002038 EXPECT_EQ(
2039 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2040 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2041 EXPECT_EQ(
2042 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2043 EXPECT_EQ(1, metrics::NumEvents(
2044 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2045 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 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.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002048 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002049 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2050 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002051 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002052 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002053 EXPECT_EQ(1, metrics::NumEvents(
2054 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2055 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2056 EXPECT_EQ(
2057 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2058 EXPECT_EQ(1, metrics::NumEvents(
2059 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2060 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002061 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002062 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002063 EXPECT_EQ(1,
2064 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002065 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2066}
Erik Språng22c2b482016-03-01 09:40:42 +01002067
asapersson93e1e232017-02-06 05:18:35 -08002068TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2069 StreamDataCountersCallback* proxy =
2070 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2071 StreamDataCounters counters;
2072 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002073
asapersson93e1e232017-02-06 05:18:35 -08002074 const int kMinRequiredPeriodSamples = 8;
2075 const int kPeriodIntervalMs = 2000;
2076 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2077 counters.transmitted.packets += 20;
2078 counters.transmitted.header_bytes += 500;
2079 counters.transmitted.payload_bytes += 2000;
2080 counters.fec = counters.retransmitted;
2081 // Advance one interval and update counters.
2082 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2083 proxy->DataCountersUpdated(counters, kFirstSsrc);
2084 }
2085
2086 // RTX enabled. No data sent over RTX.
2087 statistics_proxy_.reset();
2088 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2089 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2090}
2091
2092TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2093 VideoSendStream::Config config(nullptr);
2094 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2095 statistics_proxy_.reset(new SendStatisticsProxy(
2096 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2097
2098 StreamDataCountersCallback* proxy =
2099 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2100 StreamDataCounters counters;
2101
2102 const int kMinRequiredPeriodSamples = 8;
2103 const int kPeriodIntervalMs = 2000;
2104 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2105 counters.transmitted.packets += 20;
2106 counters.transmitted.header_bytes += 500;
2107 counters.transmitted.payload_bytes += 2000;
2108 counters.fec = counters.retransmitted;
2109 // Advance one interval and update counters.
2110 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2111 proxy->DataCountersUpdated(counters, kFirstSsrc);
2112 }
2113
2114 // RTX not enabled.
2115 statistics_proxy_.reset();
2116 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2117}
2118
2119TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2120 StreamDataCountersCallback* proxy =
2121 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2122 StreamDataCounters counters;
2123 StreamDataCounters rtx_counters;
2124
2125 const int kMinRequiredPeriodSamples = 8;
2126 const int kPeriodIntervalMs = 2000;
2127 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2128 counters.transmitted.packets += 20;
2129 counters.transmitted.header_bytes += 500;
2130 counters.transmitted.payload_bytes += 2000;
2131 // Advance one interval and update counters.
2132 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2133 proxy->DataCountersUpdated(counters, kFirstSsrc);
2134 }
2135
2136 // FEC enabled. No FEC data sent.
2137 statistics_proxy_.reset();
2138 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2139 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2140}
2141
2142TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2143 VideoSendStream::Config config(nullptr);
2144 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2145 statistics_proxy_.reset(new SendStatisticsProxy(
2146 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2147
2148 StreamDataCountersCallback* proxy =
2149 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2150 StreamDataCounters counters;
2151
2152 const int kMinRequiredPeriodSamples = 8;
2153 const int kPeriodIntervalMs = 2000;
2154 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2155 counters.transmitted.packets += 20;
2156 counters.transmitted.header_bytes += 500;
2157 counters.transmitted.payload_bytes += 2000;
2158 counters.fec = counters.retransmitted;
2159 // Advance one interval and update counters.
2160 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2161 proxy->DataCountersUpdated(counters, kFirstSsrc);
2162 }
2163
2164 // FEC not enabled.
2165 statistics_proxy_.reset();
2166 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002167}
2168
asapersson8d75ac72017-09-15 06:41:15 -07002169TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002170 const std::string kName = "encoderName";
2171 statistics_proxy_->OnEncoderImplementationChanged(kName);
2172 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002173}
2174
Sergey Silkinbb081a62018-09-04 18:34:22 +02002175TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2176 static const int kEncodedWidth = 123;
2177 static const int kEncodedHeight = 81;
2178 EncodedImage encoded_image;
2179 encoded_image._encodedWidth = kEncodedWidth;
2180 encoded_image._encodedHeight = kEncodedHeight;
2181 encoded_image.SetSpatialIndex(0);
2182
2183 CodecSpecificInfo codec_info;
2184 codec_info.codecType = kVideoCodecVP9;
2185
2186 // For first picture, it is expected that low layer updates resolution.
2187 codec_info.codecSpecific.VP9.end_of_picture = false;
2188 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2189 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2190 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2191 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2192
2193 // Top layer updates resolution.
2194 encoded_image._encodedWidth = kEncodedWidth * 2;
2195 encoded_image._encodedHeight = kEncodedHeight * 2;
2196 codec_info.codecSpecific.VP9.end_of_picture = true;
2197 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2198 stats = statistics_proxy_->GetStats();
2199 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2200 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2201
2202 // Low layer of next frame doesn't update resolution.
2203 encoded_image._encodedWidth = kEncodedWidth;
2204 encoded_image._encodedHeight = kEncodedHeight;
2205 codec_info.codecSpecific.VP9.end_of_picture = false;
2206 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2207 stats = statistics_proxy_->GetStats();
2208 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2209 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2210}
2211
asapersson8d75ac72017-09-15 06:41:15 -07002212class ForcedFallbackTest : public SendStatisticsProxyTest {
2213 public:
2214 explicit ForcedFallbackTest(const std::string& field_trials)
2215 : SendStatisticsProxyTest(field_trials) {
2216 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002217 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002218 encoded_image_._encodedWidth = kWidth;
2219 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002220 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002221 }
2222
2223 ~ForcedFallbackTest() override {}
2224
2225 protected:
2226 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002227 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2228
asapersson8d75ac72017-09-15 06:41:15 -07002229 // First frame is not updating stats, insert initial frame.
2230 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2231 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2232 }
2233 for (int i = 0; i < num_frames; ++i) {
2234 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2235 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2236 }
2237 // Add frame to include last time interval.
2238 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2239 }
2240
2241 EncodedImage encoded_image_;
2242 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002243 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002244 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2245 const int kFrameIntervalMs = 1000;
2246 const int kMinFrames = 20; // Min run time 20 sec.
2247};
2248
2249class ForcedFallbackDisabled : public ForcedFallbackTest {
2250 public:
2251 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002252 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2253 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002254};
2255
2256class ForcedFallbackEnabled : public ForcedFallbackTest {
2257 public:
2258 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002259 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2260 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002261};
2262
2263TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2264 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2265 statistics_proxy_.reset();
2266 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2267 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2268}
2269
2270TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2271 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002272 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002273 statistics_proxy_.reset();
2274 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2275 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2276 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2277 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2278}
2279
2280TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2281 codec_info_.codecType = kVideoCodecVP9;
2282 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2283 statistics_proxy_.reset();
2284 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2285 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2286}
2287
2288TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2289 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2290 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2291 statistics_proxy_.reset();
2292 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2293 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2294}
2295
2296TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002297 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002298 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2299 statistics_proxy_.reset();
2300 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2301 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2302}
2303
2304TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2305 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2306 statistics_proxy_.reset();
2307 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2308 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2309}
2310
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002311TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2312 InsertEncodedFrames(1, kFrameIntervalMs);
2313 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2314}
2315
2316TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2317 InsertEncodedFrames(1, kFrameIntervalMs);
2318 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2319}
2320
2321TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002322 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002323 InsertEncodedFrames(1, kFrameIntervalMs);
2324 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2325}
2326
2327TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2328 encoded_image_._encodedWidth = kWidth + 1;
2329 InsertEncodedFrames(1, kFrameIntervalMs);
2330 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2331}
2332
2333TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002334 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002335 InsertEncodedFrames(1, kFrameIntervalMs);
2336 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2337}
2338
2339TEST_F(ForcedFallbackDisabled,
2340 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2341 encoded_image_._encodedWidth = kWidth + 1;
2342 statistics_proxy_->OnMinPixelLimitReached();
2343 InsertEncodedFrames(1, kFrameIntervalMs);
2344 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2345}
2346
asapersson8d75ac72017-09-15 06:41:15 -07002347TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2348 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002349 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002350 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002351 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002352 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002353 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002354 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002355
2356 statistics_proxy_.reset();
2357 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2358 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2359 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2360 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2361}
2362
2363TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2364 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2365 const int kMaxFrameDiffMs = 2000;
2366
2367 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2368 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002369 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002370 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002371 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002372 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002373 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002374 InsertEncodedFrames(20, 1000);
2375 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2376 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002377 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002378 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002379 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002380 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002381 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002382 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002383 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002384
2385 statistics_proxy_.reset();
2386 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2387 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2388 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2389 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2390}
2391
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002392TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2393 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002394 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002395 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2396
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002397 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002398 statistics_proxy_.reset();
2399 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2400 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2401}
2402
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002403TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2404 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002405 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002406 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2407
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002408 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002409 statistics_proxy_.reset();
2410 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2411 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2412}
2413
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002414} // namespace webrtc