blob: 4823e95c7a742ebc8fa528061c44584fd6fb8e3a [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"
Henrik Boström23aff9b2019-05-20 15:15:38 +020020#include "api/units/timestamp.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020021#include "api/video/video_bitrate_allocation.h"
22#include "api/video/video_codec_type.h"
23#include "api/video_codecs/video_codec.h"
24#include "api/video_codecs/video_encoder_config.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020025#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070027#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000029
30namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070031namespace {
32const uint32_t kFirstSsrc = 17;
33const uint32_t kSecondSsrc = 42;
34const uint32_t kFirstRtxSsrc = 18;
35const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080036const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080037const int kFpsPeriodicIntervalMs = 2000;
38const int kWidth = 640;
39const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070040const int kQpIdx0 = 21;
41const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010042const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080043const CodecSpecificInfo kDefaultCodecInfo = []() {
44 CodecSpecificInfo codec_info;
45 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080046 return codec_info;
47}();
asapersson5265fed2016-04-18 02:58:47 -070048} // namespace
sprang07fb9be2016-02-24 07:55:00 -080049
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000050class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000051 public:
asapersson8d75ac72017-09-15 06:41:15 -070052 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
53 explicit SendStatisticsProxyTest(const std::string& field_trials)
54 : override_field_trials_(field_trials),
55 fake_clock_(1234),
56 config_(GetTestConfig()),
57 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070058 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000059 virtual ~SendStatisticsProxyTest() {}
60
61 protected:
62 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070063 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080064 statistics_proxy_.reset(new SendStatisticsProxy(
65 &fake_clock_, GetTestConfig(),
66 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000067 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070068 for (const auto& ssrc : config_.rtp.ssrcs)
69 expected_.substreams[ssrc].is_rtx = false;
70 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
71 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000072 }
73
74 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070075 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080076 config.rtp.ssrcs.push_back(kFirstSsrc);
77 config.rtp.ssrcs.push_back(kSecondSsrc);
78 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
79 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070080 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000081 return config;
82 }
83
asaperssona6a699a2016-11-25 03:52:46 -080084 VideoSendStream::Config GetTestConfigWithFlexFec() {
85 VideoSendStream::Config config(nullptr);
86 config.rtp.ssrcs.push_back(kFirstSsrc);
87 config.rtp.ssrcs.push_back(kSecondSsrc);
88 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
89 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080090 config.rtp.flexfec.payload_type = 50;
91 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080092 return config;
93 }
94
95 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
96 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
97 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
98 stats.substreams.find(ssrc);
99 EXPECT_NE(it, stats.substreams.end());
100 return it->second;
101 }
102
asapersson66d4b372016-12-19 06:50:53 -0800103 void UpdateDataCounters(uint32_t ssrc) {
104 StreamDataCountersCallback* proxy =
105 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
106 StreamDataCounters counters;
107 proxy->DataCountersUpdated(counters, ssrc);
108 }
109
sprang@webrtc.org09315702014-02-07 12:06:29 +0000110 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000111 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
112 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000113 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000114 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000115
116 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000117 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000118 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000119 it != one.substreams.end(); ++it) {
120 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
121 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000122 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000123 const VideoSendStream::StreamStats& a = it->second;
124 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000125
asapersson2e5cfcd2016-08-11 08:41:18 -0700126 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000127 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
128 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000129 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000130 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
131 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000133 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
134 b.rtp_stats.transmitted.payload_bytes);
135 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
136 b.rtp_stats.transmitted.header_bytes);
137 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
138 b.rtp_stats.transmitted.padding_bytes);
139 EXPECT_EQ(a.rtp_stats.transmitted.packets,
140 b.rtp_stats.transmitted.packets);
141 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
142 b.rtp_stats.retransmitted.packets);
143 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000144
145 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700146 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
147 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
148 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
150 }
151 }
152
asapersson8d75ac72017-09-15 06:41:15 -0700153 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000154 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800155 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156 VideoSendStream::Config config_;
157 int avg_delay_ms_;
158 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000159 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000160 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
161 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000162};
163
164TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
165 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700166 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000167 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000168
169 // Add statistics with some arbitrary, but unique, numbers.
170 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700171 ssrc_stats.rtcp_stats.packets_lost = offset;
172 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
174 ssrc_stats.rtcp_stats.jitter = offset + 3;
175 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
176 }
asapersson35151f32016-05-02 23:44:01 -0700177 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000178 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000179
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000180 // Add statistics with some arbitrary, but unique, numbers.
181 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700182 ssrc_stats.rtcp_stats.packets_lost = offset;
183 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000184 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
185 ssrc_stats.rtcp_stats.jitter = offset + 3;
186 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
187 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000188 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000189 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000190}
191
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000192TEST_F(SendStatisticsProxyTest, Suspended) {
193 // Verify that the value is false by default.
194 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
195
196 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200197 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000198 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
199
200 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200201 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000202 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
203}
204
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000205TEST_F(SendStatisticsProxyTest, FrameCounts) {
206 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700207 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000208 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000209 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
210 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000211 FrameCounts frame_counts;
212 frame_counts.key_frames = offset;
213 frame_counts.delta_frames = offset + 1;
214 stats.frame_counts = frame_counts;
215 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000216 }
asapersson35151f32016-05-02 23:44:01 -0700217 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000218 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000219 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
220 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000221 FrameCounts frame_counts;
222 frame_counts.key_frames = offset;
223 frame_counts.delta_frames = offset + 1;
224 stats.frame_counts = frame_counts;
225 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000226 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000227
228 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000229 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000230}
231
232TEST_F(SendStatisticsProxyTest, DataCounters) {
233 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700234 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000235 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
236 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000237 size_t offset = ssrc * sizeof(StreamDataCounters);
238 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000239 counters.transmitted.payload_bytes = offset;
240 counters.transmitted.header_bytes = offset + 1;
241 counters.fec.packets = offset_uint32 + 2;
242 counters.transmitted.padding_bytes = offset + 3;
243 counters.retransmitted.packets = offset_uint32 + 4;
244 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000245 callback->DataCountersUpdated(counters, ssrc);
246 }
asapersson35151f32016-05-02 23:44:01 -0700247 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000248 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
249 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000250 size_t offset = ssrc * sizeof(StreamDataCounters);
251 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000252 counters.transmitted.payload_bytes = offset;
253 counters.transmitted.header_bytes = offset + 1;
254 counters.fec.packets = offset_uint32 + 2;
255 counters.transmitted.padding_bytes = offset + 3;
256 counters.retransmitted.packets = offset_uint32 + 4;
257 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000258 callback->DataCountersUpdated(counters, ssrc);
259 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000260
261 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000262 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000263}
264
265TEST_F(SendStatisticsProxyTest, Bitrate) {
266 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700267 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700268 uint32_t total;
269 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000270 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700271 total = ssrc;
272 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000273 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700274 expected_.substreams[ssrc].total_bitrate_bps = total;
275 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000276 }
asapersson35151f32016-05-02 23:44:01 -0700277 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700278 uint32_t total;
279 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700281 total = ssrc;
282 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000283 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700284 expected_.substreams[ssrc].total_bitrate_bps = total;
285 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000286 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000287
288 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000289 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000290}
291
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000292TEST_F(SendStatisticsProxyTest, SendSideDelay) {
293 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700294 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000295 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
296 // stream.
297 int avg_delay_ms = ssrc;
298 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200299 uint64_t total_packet_send_delay_ms = ssrc + 2;
300 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
301 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000302 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
303 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200304 expected_.substreams[ssrc].total_packet_send_delay_ms =
305 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000306 }
asapersson35151f32016-05-02 23:44:01 -0700307 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000308 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
309 // stream.
310 int avg_delay_ms = ssrc;
311 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200312 uint64_t total_packet_send_delay_ms = ssrc + 2;
313 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
314 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000315 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
316 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200317 expected_.substreams[ssrc].total_packet_send_delay_ms =
318 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000319 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000320 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000321 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000322}
323
Peter Boströme4499152016-02-05 11:13:28 +0100324TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800325 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200326 int encode_usage_percent = 80;
327 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
328 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800329
330 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
331 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200332 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800333}
334
Henrik Boström5684af52019-04-02 15:05:21 +0200335TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
336 const int kEncodeUsagePercent = 0; // Don't care for this test.
337 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
338 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
339 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
340 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
341 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
342}
343
sakal43536c32016-10-24 01:46:43 -0700344TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
345 EncodedImage encoded_image;
346 CodecSpecificInfo codec_info;
347 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
348 for (uint32_t i = 1; i <= 3; ++i) {
349 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
350 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
351 }
352}
353
sakal87da4042016-10-31 06:53:47 -0700354TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
355 EncodedImage encoded_image;
356 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200357 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700358 encoded_image.qp_ = 3;
359 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100360 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700361 encoded_image.qp_ = 127;
362 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100363 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700364}
365
366TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
367 EncodedImage encoded_image;
368 CodecSpecificInfo codec_info;
369 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200370 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700371 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200372 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700373}
374
Henrik Boström23aff9b2019-05-20 15:15:38 +0200375TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
376 const uint32_t kTargetBytesPerSecond = 100000;
377 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
378 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
379
380 EncodedImage encoded_image;
381 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
382 // On the first frame we don't know the frame rate yet, calculation yields
383 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
384 // increment by a full |kTargetBytesPerSecond|.
385 EXPECT_EQ(kTargetBytesPerSecond,
386 statistics_proxy_->GetStats().total_encoded_bytes_target);
387}
388
389TEST_F(SendStatisticsProxyTest,
390 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
391 const uint32_t kTargetBytesPerSecond = 100000;
392 const int kInterframeDelayMs = 100;
393
394 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
395 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
396 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
397 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
398 // this test can stop relying on rtc::ScopedFakeClock.
399 rtc::ScopedFakeClock fake_global_clock;
400 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
401
402 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
403 EncodedImage encoded_image;
404
405 // First frame
406 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
407 uint64_t first_total_encoded_bytes_target =
408 statistics_proxy_->GetStats().total_encoded_bytes_target;
409 // Second frame
410 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
411 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
412 encoded_image.SetTimestamp(encoded_image.Timestamp() +
413 90 * kInterframeDelayMs);
414 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
415
416 auto stats = statistics_proxy_->GetStats();
417 // By the time the second frame arrives, one frame has previously arrived
418 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
419 // the second frame's arrival should be 10 FPS.
420 uint64_t delta_encoded_bytes_target =
421 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
422 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
423}
424
asapersson09f05612017-05-15 23:40:18 -0700425TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200426 SendStatisticsProxy::AdaptationSteps cpu_counts;
427 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700428 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700429 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200430 cpu_counts.num_framerate_reductions = 1;
431 cpu_counts.num_resolution_reductions = 0;
432 statistics_proxy_->OnAdaptationChanged(
433 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
434 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700435 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700436 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200437 cpu_counts.num_framerate_reductions = 0;
438 cpu_counts.num_resolution_reductions = 1;
439 statistics_proxy_->OnAdaptationChanged(
440 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
441 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700442 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700443 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200444 cpu_counts.num_framerate_reductions = 1;
445 cpu_counts.num_resolution_reductions = absl::nullopt;
446 statistics_proxy_->OnAdaptationChanged(
447 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
448 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700449 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700450 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200451 cpu_counts.num_framerate_reductions = absl::nullopt;
452 cpu_counts.num_resolution_reductions = absl::nullopt;
453 statistics_proxy_->OnAdaptationChanged(
454 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
455 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700456 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
457 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
458}
459
460TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200461 SendStatisticsProxy::AdaptationSteps cpu_counts;
462 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700463 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
464 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200465 quality_counts.num_framerate_reductions = 1;
466 quality_counts.num_resolution_reductions = 0;
467 statistics_proxy_->OnAdaptationChanged(
468 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
469 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700470 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
471 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200472 quality_counts.num_framerate_reductions = 0;
473 quality_counts.num_resolution_reductions = 1;
474 statistics_proxy_->OnAdaptationChanged(
475 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
476 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700477 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
478 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200479 quality_counts.num_framerate_reductions = 1;
480 quality_counts.num_resolution_reductions = absl::nullopt;
481 statistics_proxy_->OnAdaptationChanged(
482 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
483 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700484 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
485 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200486 quality_counts.num_framerate_reductions = absl::nullopt;
487 quality_counts.num_resolution_reductions = absl::nullopt;
488 statistics_proxy_->OnAdaptationChanged(
489 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
490 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700491 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
492 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
493}
494
495TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200496 SendStatisticsProxy::AdaptationSteps cpu_counts;
497 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700498 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
499
Niels Möller213618e2018-07-24 09:29:58 +0200500 cpu_counts.num_resolution_reductions = 1;
501 statistics_proxy_->OnAdaptationChanged(
502 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
503 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700504 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700505 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
506 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
507
Niels Möller213618e2018-07-24 09:29:58 +0200508 cpu_counts.num_resolution_reductions = 2;
509 statistics_proxy_->OnAdaptationChanged(
510 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
511 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700512 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
513 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700514 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700515 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700516}
517
asapersson09f05612017-05-15 23:40:18 -0700518TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200519 SendStatisticsProxy::AdaptationSteps cpu_counts;
520 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700521 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
522
Niels Möller213618e2018-07-24 09:29:58 +0200523 quality_counts.num_framerate_reductions = 1;
524 statistics_proxy_->OnAdaptationChanged(
525 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
526 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700527 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
528 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700529 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
530
Niels Möller213618e2018-07-24 09:29:58 +0200531 quality_counts.num_framerate_reductions = 0;
532 statistics_proxy_->OnAdaptationChanged(
533 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
534 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700535 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700536 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700537 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
538 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700539}
540
asapersson09f05612017-05-15 23:40:18 -0700541TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700542 // First RTP packet sent.
543 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700544 // Min runtime has passed.
545 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
546 statistics_proxy_.reset();
547 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
548 EXPECT_EQ(0,
549 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
550}
551
552TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700553 // First RTP packet sent.
554 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700555 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200556 SendStatisticsProxy::AdaptationSteps cpu_counts;
557 SendStatisticsProxy::AdaptationSteps quality_counts;
558 statistics_proxy_->OnAdaptationChanged(
559 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
560 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700561 // Min runtime has not passed.
562 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
563 statistics_proxy_.reset();
564 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
565 EXPECT_EQ(0,
566 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
567}
568
asapersson09f05612017-05-15 23:40:18 -0700569TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700570 // First RTP packet sent.
571 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700572 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200573 SendStatisticsProxy::AdaptationSteps cpu_counts;
574 SendStatisticsProxy::AdaptationSteps quality_counts;
575 statistics_proxy_->OnAdaptationChanged(
576 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
577 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700578 // Min runtime has passed.
579 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
580 statistics_proxy_.reset();
581 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
582 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700583 EXPECT_EQ(1,
584 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
585 EXPECT_EQ(
586 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
587}
588
589TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700590 // First RTP packet sent.
591 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700592 // 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);
asapersson0944a802017-04-07 00:57:58 -0700598 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200599 statistics_proxy_->OnAdaptationChanged(
600 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
601 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700602 fake_clock_.AdvanceTimeMilliseconds(10000);
603 statistics_proxy_.reset();
604 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
605 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
606}
607
Åsa Persson875841d2018-01-08 08:49:53 +0100608TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
609 // First RTP packet sent.
610 UpdateDataCounters(kFirstSsrc);
611 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200612 SendStatisticsProxy::AdaptationSteps cpu_counts;
613 SendStatisticsProxy::AdaptationSteps quality_counts;
614 statistics_proxy_->OnAdaptationChanged(
615 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
616 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100617 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200618 statistics_proxy_->OnAdaptationChanged(
619 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
620 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100621 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
622 fake_clock_.AdvanceTimeMilliseconds(10000);
623 statistics_proxy_.reset();
624 EXPECT_EQ(1,
625 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
626 EXPECT_EQ(
627 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
628}
629
630TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
631 // First RTP packet sent.
632 UpdateDataCounters(kFirstSsrc);
633 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200634 SendStatisticsProxy::AdaptationSteps cpu_counts;
635 SendStatisticsProxy::AdaptationSteps quality_counts;
636 statistics_proxy_->OnAdaptationChanged(
637 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
638 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100639 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200640 quality_counts.num_resolution_reductions = 1;
641 statistics_proxy_->OnAdaptationChanged(
642 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
643 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100644 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200645 quality_counts.num_resolution_reductions = 2;
646 statistics_proxy_->OnAdaptationChanged(
647 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
648 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100649 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200650 quality_counts.num_resolution_reductions = 3;
651 statistics_proxy_->OnAdaptationChanged(
652 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
653 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100654 fake_clock_.AdvanceTimeMilliseconds(10000);
655 statistics_proxy_.reset();
656 EXPECT_EQ(1,
657 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
658 EXPECT_EQ(
659 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
660}
661
662TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
663 // First RTP packet sent.
664 UpdateDataCounters(kFirstSsrc);
665 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200666 SendStatisticsProxy::AdaptationSteps cpu_counts;
667 SendStatisticsProxy::AdaptationSteps quality_counts;
668 statistics_proxy_->OnAdaptationChanged(
669 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
670 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100671 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200672 statistics_proxy_->OnAdaptationChanged(
673 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
674 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100675 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
676 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
677 fake_clock_.AdvanceTimeMilliseconds(10000);
678 statistics_proxy_.reset();
679 EXPECT_EQ(1,
680 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
681 EXPECT_EQ(
682 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
683}
684
685TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
686 // First RTP packet sent.
687 UpdateDataCounters(kFirstSsrc);
688 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200689 SendStatisticsProxy::AdaptationSteps cpu_counts;
690 SendStatisticsProxy::AdaptationSteps quality_counts;
691 statistics_proxy_->OnAdaptationChanged(
692 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
693 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100694 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200695 quality_counts.num_resolution_reductions = 1;
696 statistics_proxy_->OnAdaptationChanged(
697 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
698 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100699 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200700 quality_counts.num_resolution_reductions = 2;
701 statistics_proxy_->OnAdaptationChanged(
702 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
703 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100704 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200705 quality_counts.num_resolution_reductions = 3;
706 statistics_proxy_->OnAdaptationChanged(
707 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
708 quality_counts);
709 quality_counts.num_framerate_reductions = 1;
710 statistics_proxy_->OnAdaptationChanged(
711 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
712 quality_counts);
713 quality_counts.num_framerate_reductions = 0;
714 statistics_proxy_->OnAdaptationChanged(
715 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
716 quality_counts);
717 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
718 statistics_proxy_->OnAdaptationChanged(
719 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
720 quality_counts);
721 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
722 statistics_proxy_->OnAdaptationChanged(
723 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
724 quality_counts);
725 quality_counts.num_resolution_reductions = 0;
726 statistics_proxy_->OnAdaptationChanged(
727 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
728 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100729
730 fake_clock_.AdvanceTimeMilliseconds(10000);
731 statistics_proxy_.reset();
732 EXPECT_EQ(1,
733 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
734 EXPECT_EQ(
735 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
736}
737
asapersson6eca98b2017-04-04 23:40:50 -0700738TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700739 // First RTP packet sent.
740 UpdateDataCounters(kFirstSsrc);
741
asapersson09f05612017-05-15 23:40:18 -0700742 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200743 SendStatisticsProxy::AdaptationSteps cpu_counts;
744 SendStatisticsProxy::AdaptationSteps quality_counts;
745 quality_counts.num_framerate_reductions = absl::nullopt;
746 quality_counts.num_resolution_reductions = absl::nullopt;
747 statistics_proxy_->OnAdaptationChanged(
748 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
749 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700750 fake_clock_.AdvanceTimeMilliseconds(10000);
751
asapersson09f05612017-05-15 23:40:18 -0700752 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700753 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200754 quality_counts.num_framerate_reductions = 0;
755 statistics_proxy_->OnAdaptationChanged(
756 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
757 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700758 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200759 statistics_proxy_->OnAdaptationChanged(
760 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
761 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700762 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200763 statistics_proxy_->OnAdaptationChanged(
764 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
765 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700766 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200767 statistics_proxy_->OnAdaptationChanged(
768 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
769 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700770
asapersson09f05612017-05-15 23:40:18 -0700771 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200772 quality_counts.num_framerate_reductions = absl::nullopt;
773 statistics_proxy_->OnAdaptationChanged(
774 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
775 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700776 fake_clock_.AdvanceTimeMilliseconds(30000);
777
asapersson09f05612017-05-15 23:40:18 -0700778 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700779 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200780 quality_counts.num_resolution_reductions = 0;
781 statistics_proxy_->OnAdaptationChanged(
782 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
783 quality_counts);
784 statistics_proxy_->OnAdaptationChanged(
785 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
786 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700787 fake_clock_.AdvanceTimeMilliseconds(10000);
788
asapersson09f05612017-05-15 23:40:18 -0700789 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200790 quality_counts.num_resolution_reductions = absl::nullopt;
791 statistics_proxy_->OnAdaptationChanged(
792 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
793 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700794 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200795 statistics_proxy_->OnAdaptationChanged(
796 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
797 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700798 fake_clock_.AdvanceTimeMilliseconds(20000);
799
asapersson0944a802017-04-07 00:57:58 -0700800 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700801 statistics_proxy_.reset();
802 EXPECT_EQ(1,
803 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
804 EXPECT_EQ(
805 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
806}
807
asapersson0944a802017-04-07 00:57:58 -0700808TEST_F(SendStatisticsProxyTest,
809 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
810 // First RTP packet sent.
811 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700812
asapersson0944a802017-04-07 00:57:58 -0700813 // Suspend and resume video.
814 statistics_proxy_->OnSuspendChange(true);
815 fake_clock_.AdvanceTimeMilliseconds(5000);
816 statistics_proxy_->OnSuspendChange(false);
817
818 // Min runtime has passed but scaling not enabled.
819 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
820 statistics_proxy_.reset();
821 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
822 EXPECT_EQ(0,
823 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
824}
825
826TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
827 // First RTP packet sent.
828 UpdateDataCounters(kFirstSsrc);
829
asapersson09f05612017-05-15 23:40:18 -0700830 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200831 SendStatisticsProxy::AdaptationSteps cpu_counts;
832 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700833 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200834 statistics_proxy_->OnAdaptationChanged(
835 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
836 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700837 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200838 statistics_proxy_->OnAdaptationChanged(
839 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
840 quality_counts);
841 statistics_proxy_->OnAdaptationChanged(
842 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
843 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700844
845 // Suspend and resume video.
846 statistics_proxy_->OnSuspendChange(true);
847 fake_clock_.AdvanceTimeMilliseconds(30000);
848 statistics_proxy_->OnSuspendChange(false);
849
850 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200851 statistics_proxy_->OnAdaptationChanged(
852 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
853 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700854 fake_clock_.AdvanceTimeMilliseconds(10000);
855
856 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
857 statistics_proxy_.reset();
858 EXPECT_EQ(1,
859 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
860 EXPECT_EQ(
861 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
862}
863
864TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
865 // First RTP packet sent.
866 UpdateDataCounters(kFirstSsrc);
867
868 // Video not suspended.
869 statistics_proxy_->OnSuspendChange(false);
870 fake_clock_.AdvanceTimeMilliseconds(30000);
871
asapersson09f05612017-05-15 23:40:18 -0700872 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200873 SendStatisticsProxy::AdaptationSteps cpu_counts;
874 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700875 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200876 statistics_proxy_->OnAdaptationChanged(
877 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
878 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700879 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200880 statistics_proxy_->OnAdaptationChanged(
881 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
882 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700883
884 // Video not suspended, stats time already started.
885 statistics_proxy_->OnSuspendChange(false);
886 fake_clock_.AdvanceTimeMilliseconds(10000);
887
asapersson09f05612017-05-15 23:40:18 -0700888 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200889 cpu_counts.num_framerate_reductions = absl::nullopt;
890 cpu_counts.num_resolution_reductions = absl::nullopt;
891 statistics_proxy_->OnAdaptationChanged(
892 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
893 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700894 fake_clock_.AdvanceTimeMilliseconds(30000);
895
896 // Suspend and resume video, stats time not started when scaling not enabled.
897 statistics_proxy_->OnSuspendChange(true);
898 fake_clock_.AdvanceTimeMilliseconds(30000);
899 statistics_proxy_->OnSuspendChange(false);
900 fake_clock_.AdvanceTimeMilliseconds(30000);
901
asapersson09f05612017-05-15 23:40:18 -0700902 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700903 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200904 cpu_counts.num_framerate_reductions = 0;
905 cpu_counts.num_resolution_reductions = 0;
906 statistics_proxy_->OnAdaptationChanged(
907 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
908 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700909 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200910 statistics_proxy_->OnAdaptationChanged(
911 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
912 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700913
914 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
915 statistics_proxy_.reset();
916 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
917 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
918}
919
920TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
921 // First RTP packet sent.
922 UpdateDataCounters(kFirstSsrc);
923
924 // Video suspended.
925 statistics_proxy_->OnSuspendChange(true);
926
asapersson09f05612017-05-15 23:40:18 -0700927 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200928 SendStatisticsProxy::AdaptationSteps cpu_counts;
929 SendStatisticsProxy::AdaptationSteps quality_counts;
930 statistics_proxy_->OnAdaptationChanged(
931 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
932 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700933 fake_clock_.AdvanceTimeMilliseconds(10000);
934
935 // Resume video, stats time started.
936 // Adapt changes: 1, elapsed time: 10 sec.
937 statistics_proxy_->OnSuspendChange(false);
938 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200939 statistics_proxy_->OnAdaptationChanged(
940 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
941 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700942
943 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
944 statistics_proxy_.reset();
945 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
946 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
947}
948
949TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700950 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700951 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200952 SendStatisticsProxy::AdaptationSteps cpu_counts;
953 SendStatisticsProxy::AdaptationSteps quality_counts;
954 statistics_proxy_->OnAdaptationChanged(
955 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
956 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700957 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700958 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700959
asapersson0944a802017-04-07 00:57:58 -0700960 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700961 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200962 statistics_proxy_->OnAdaptationChanged(
963 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
964 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700965 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700966
asapersson0944a802017-04-07 00:57:58 -0700967 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700968 statistics_proxy_.reset();
969 EXPECT_EQ(1,
970 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
971 EXPECT_EQ(
972 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
973}
974
975TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700976 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200977 SendStatisticsProxy::AdaptationSteps cpu_counts;
978 SendStatisticsProxy::AdaptationSteps quality_counts;
979 statistics_proxy_->OnAdaptationChanged(
980 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
981 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700982 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200983 cpu_counts.num_framerate_reductions = absl::nullopt;
984 cpu_counts.num_resolution_reductions = absl::nullopt;
985 statistics_proxy_->OnAdaptationChanged(
986 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
987 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700988
989 // Send first packet, scaling disabled.
990 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700991 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700992 fake_clock_.AdvanceTimeMilliseconds(60000);
993
asapersson09f05612017-05-15 23:40:18 -0700994 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200995 cpu_counts.num_resolution_reductions = 0;
996 statistics_proxy_->OnAdaptationChanged(
997 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
998 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700999 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001000 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001001
asapersson0944a802017-04-07 00:57:58 -07001002 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001003 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001004 statistics_proxy_->OnAdaptationChanged(
1005 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1006 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001007
asapersson0944a802017-04-07 00:57:58 -07001008 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001009 statistics_proxy_.reset();
1010 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1011 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
1012}
1013
1014TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001015 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001016 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001017 SendStatisticsProxy::AdaptationSteps cpu_counts;
1018 SendStatisticsProxy::AdaptationSteps quality_counts;
1019 quality_counts.num_framerate_reductions = absl::nullopt;
1020 quality_counts.num_resolution_reductions = absl::nullopt;
1021 statistics_proxy_->OnAdaptationChanged(
1022 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1023 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001024
asapersson0944a802017-04-07 00:57:58 -07001025 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001026 statistics_proxy_->OnAdaptationChanged(
1027 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1028 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001029 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +02001030 statistics_proxy_->OnAdaptationChanged(
1031 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1032 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001033 fake_clock_.AdvanceTimeMilliseconds(9000);
1034
1035 // Switch content type, real-time stats should be updated.
1036 VideoEncoderConfig config;
1037 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001038 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -07001039 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1040 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1041 EXPECT_EQ(0,
1042 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1043
asapersson0944a802017-04-07 00:57:58 -07001044 // First RTP packet sent, scaling enabled.
1045 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001046 statistics_proxy_->OnAdaptationChanged(
1047 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1048 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001049
asapersson0944a802017-04-07 00:57:58 -07001050 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001051 statistics_proxy_->OnAdaptationChanged(
1052 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1053 quality_counts);
1054 statistics_proxy_->OnAdaptationChanged(
1055 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1056 quality_counts);
1057 statistics_proxy_->OnAdaptationChanged(
1058 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1059 quality_counts);
1060 statistics_proxy_->OnAdaptationChanged(
1061 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1062 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001063 fake_clock_.AdvanceTimeMilliseconds(120000);
1064
1065 statistics_proxy_.reset();
1066 EXPECT_EQ(1, metrics::NumSamples(
1067 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1068 EXPECT_EQ(1, metrics::NumEvents(
1069 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1070 EXPECT_EQ(0, metrics::NumSamples(
1071 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
1072}
1073
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001074TEST_F(SendStatisticsProxyTest,
1075 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
1076 SendStatisticsProxy::AdaptationSteps cpu_counts;
1077 SendStatisticsProxy::AdaptationSteps quality_counts;
1078
1079 cpu_counts.num_resolution_reductions = 1;
1080
1081 statistics_proxy_->OnAdaptationChanged(
1082 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1083 quality_counts);
1084
1085 EXPECT_EQ(QualityLimitationReason::kCpu,
1086 statistics_proxy_->GetStats().quality_limitation_reason);
1087}
1088
1089TEST_F(SendStatisticsProxyTest,
1090 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
1091 SendStatisticsProxy::AdaptationSteps cpu_counts;
1092 SendStatisticsProxy::AdaptationSteps quality_counts;
1093
1094 cpu_counts.num_framerate_reductions = 1;
1095
1096 statistics_proxy_->OnAdaptationChanged(
1097 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1098 quality_counts);
1099
1100 EXPECT_EQ(QualityLimitationReason::kCpu,
1101 statistics_proxy_->GetStats().quality_limitation_reason);
1102}
1103
1104TEST_F(SendStatisticsProxyTest,
1105 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
1106 SendStatisticsProxy::AdaptationSteps cpu_counts;
1107 SendStatisticsProxy::AdaptationSteps quality_counts;
1108
1109 quality_counts.num_resolution_reductions = 1;
1110
1111 statistics_proxy_->OnAdaptationChanged(
1112 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1113 quality_counts);
1114
1115 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1116 statistics_proxy_->GetStats().quality_limitation_reason);
1117}
1118
1119TEST_F(SendStatisticsProxyTest,
1120 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
1121 SendStatisticsProxy::AdaptationSteps cpu_counts;
1122 SendStatisticsProxy::AdaptationSteps quality_counts;
1123
1124 quality_counts.num_framerate_reductions = 1;
1125
1126 statistics_proxy_->OnAdaptationChanged(
1127 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1128 quality_counts);
1129
1130 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1131 statistics_proxy_->GetStats().quality_limitation_reason);
1132}
1133
1134TEST_F(SendStatisticsProxyTest,
1135 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
1136 SendStatisticsProxy::AdaptationSteps cpu_counts;
1137 SendStatisticsProxy::AdaptationSteps quality_counts;
1138
1139 cpu_counts.num_resolution_reductions = 1;
1140 quality_counts.num_resolution_reductions = 1;
1141
1142 // Even if the last adaptation reason is kCpu, if the counters indicate being
1143 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
1144 statistics_proxy_->OnAdaptationChanged(
1145 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1146 quality_counts);
1147
1148 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1149 statistics_proxy_->GetStats().quality_limitation_reason);
1150}
1151
1152TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
1153 SendStatisticsProxy::AdaptationSteps cpu_counts;
1154 SendStatisticsProxy::AdaptationSteps quality_counts;
1155
1156 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1157 // due to "none" being the default value.
1158 cpu_counts.num_resolution_reductions = 1;
1159 statistics_proxy_->OnAdaptationChanged(
1160 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1161 quality_counts);
1162 // Go back to not being limited.
1163 cpu_counts.num_resolution_reductions = 0;
1164 statistics_proxy_->OnAdaptationChanged(
1165 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1166 quality_counts);
1167
1168 EXPECT_EQ(QualityLimitationReason::kNone,
1169 statistics_proxy_->GetStats().quality_limitation_reason);
1170}
1171
1172TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
1173 SendStatisticsProxy::AdaptationSteps cpu_counts;
1174 SendStatisticsProxy::AdaptationSteps quality_counts;
1175
1176 // Not limited for 3000 ms
1177 fake_clock_.AdvanceTimeMilliseconds(3000);
1178 // CPU limited for 2000 ms
1179 cpu_counts.num_resolution_reductions = 1;
1180 statistics_proxy_->OnAdaptationChanged(
1181 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1182 quality_counts);
1183 fake_clock_.AdvanceTimeMilliseconds(2000);
1184 // Bandwidth limited for 1000 ms
1185 cpu_counts.num_resolution_reductions = 0;
1186 quality_counts.num_resolution_reductions = 1;
1187 statistics_proxy_->OnAdaptationChanged(
1188 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1189 quality_counts);
1190 fake_clock_.AdvanceTimeMilliseconds(1000);
1191 // CPU limited for another 2000 ms
1192 cpu_counts.num_resolution_reductions = 1;
1193 quality_counts.num_resolution_reductions = 0;
1194 statistics_proxy_->OnAdaptationChanged(
1195 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1196 quality_counts);
1197 fake_clock_.AdvanceTimeMilliseconds(2000);
1198
1199 auto quality_limitation_durations_ms =
1200 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1201
1202 EXPECT_EQ(3000,
1203 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1204 EXPECT_EQ(4000,
1205 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1206 EXPECT_EQ(
1207 1000,
1208 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1209 EXPECT_EQ(0,
1210 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1211}
1212
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001213TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1214 EXPECT_EQ(
1215 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1216}
1217
1218TEST_F(SendStatisticsProxyTest,
1219 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1220 VideoCodec codec;
1221 VideoBitrateAllocation allocation;
1222 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1223 EXPECT_EQ(
1224 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1225}
1226
1227TEST_F(SendStatisticsProxyTest,
1228 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1229 VideoCodec codec;
1230 codec.simulcastStream[0].active = true;
1231 codec.simulcastStream[1].active = true;
1232 codec.simulcastStream[2].active = true;
1233 VideoBitrateAllocation allocation;
1234 allocation.SetBitrate(0, 0, 100);
1235 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1236 EXPECT_EQ(
1237 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1238}
1239
1240TEST_F(SendStatisticsProxyTest,
1241 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1242 VideoCodec codec;
1243 codec.simulcastStream[0].active = true;
1244 codec.simulcastStream[1].active = true;
1245 codec.simulcastStream[2].active = true;
1246 VideoBitrateAllocation allocation;
1247 allocation.SetBitrate(0, 0, 100);
1248 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1249 allocation.SetBitrate(1, 0, 100);
1250 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1251 EXPECT_EQ(
1252 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1253}
1254
1255TEST_F(SendStatisticsProxyTest,
1256 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1257 VideoCodec codec;
1258 codec.simulcastStream[0].active = true;
1259 VideoBitrateAllocation allocation;
1260 allocation.SetBitrate(0, 0, 100);
1261 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1262 // Layer 0 got more bandwidth, but still only one layer on
1263 allocation.SetBitrate(0, 0, 200);
1264 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1265 EXPECT_EQ(
1266 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1267}
1268
1269TEST_F(SendStatisticsProxyTest,
1270 QualityLimitationResolutionChangesWithTogglingLayers) {
1271 VideoCodec codec;
1272 codec.simulcastStream[0].active = true;
1273 codec.simulcastStream[1].active = true;
1274 codec.simulcastStream[2].active = true;
1275 VideoBitrateAllocation allocation;
1276 allocation.SetBitrate(0, 0, 100);
1277 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1278 EXPECT_EQ(
1279 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1280 allocation.SetBitrate(1, 0, 300);
1281 allocation.SetBitrate(2, 0, 500);
1282 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1283 EXPECT_EQ(
1284 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1285 // Layer 2 off
1286 allocation.SetBitrate(2, 0, 0);
1287 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1288 EXPECT_EQ(
1289 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1290 // Layer 2 back on
1291 allocation.SetBitrate(2, 0, 500);
1292 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1293 EXPECT_EQ(
1294 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1295 allocation.SetBitrate(0, 0, 0);
1296 allocation.SetBitrate(1, 0, 0);
1297 allocation.SetBitrate(2, 0, 0);
1298 // All layers off
1299 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1300 EXPECT_EQ(
1301 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1302}
1303
1304TEST_F(SendStatisticsProxyTest,
1305 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1306 VideoCodec codec;
1307 // 3 layers
1308 codec.simulcastStream[0].active = true;
1309 codec.simulcastStream[1].active = true;
1310 codec.simulcastStream[2].active = true;
1311 VideoBitrateAllocation allocation;
1312 allocation.SetBitrate(0, 0, 500);
1313 allocation.SetBitrate(1, 0, 500);
1314 allocation.SetBitrate(2, 0, 500);
1315 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1316 EXPECT_EQ(
1317 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1318
1319 // Down to one layer now, triggered by a config change
1320 codec.numberOfSimulcastStreams = 1;
1321 codec.simulcastStream[1].active = false;
1322 codec.simulcastStream[2].active = false;
1323 allocation.SetBitrate(0, 0, 100);
1324 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1325 EXPECT_EQ(
1326 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1327
1328 // Up to 3 layers again.
1329 codec.numberOfSimulcastStreams = 3;
1330 codec.simulcastStream[1].active = true;
1331 codec.simulcastStream[2].active = true;
1332 allocation.SetBitrate(0, 0, 500);
1333 allocation.SetBitrate(1, 0, 500);
1334 allocation.SetBitrate(2, 0, 500);
1335 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1336 EXPECT_EQ(
1337 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1338}
1339
1340TEST_F(SendStatisticsProxyTest,
1341 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1342 VideoCodec codec;
1343 codec.simulcastStream[0].active = true;
1344 codec.spatialLayers[0].active = true;
1345 codec.spatialLayers[1].active = true;
1346 codec.spatialLayers[2].active = true;
1347 VideoBitrateAllocation allocation;
1348 allocation.SetBitrate(0, 0, 500);
1349 allocation.SetBitrate(1, 0, 500);
1350 allocation.SetBitrate(2, 0, 500);
1351 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1352 EXPECT_EQ(
1353 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1354
1355 // Down to one layer now, triggered by a config change
1356 codec.spatialLayers[1].active = false;
1357 codec.spatialLayers[2].active = false;
1358 allocation.SetBitrate(0, 0, 100);
1359 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1360 EXPECT_EQ(
1361 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1362
1363 // Up to 3 layers again.
1364 codec.spatialLayers[1].active = true;
1365 codec.spatialLayers[2].active = true;
1366 allocation.SetBitrate(0, 0, 500);
1367 allocation.SetBitrate(1, 0, 500);
1368 allocation.SetBitrate(2, 0, 500);
1369 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1370 EXPECT_EQ(
1371 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1372}
1373
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001374TEST_F(SendStatisticsProxyTest,
1375 QualityLimitationReasonsAreCorrectForContentType) {
1376 // Realtime case.
1377 // Configure two streams.
1378 VideoEncoderConfig config;
1379 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1380 config.number_of_streams = 2;
1381 VideoStream stream1;
1382 stream1.width = kWidth / 2;
1383 stream1.height = kHeight / 2;
1384 VideoStream stream2;
1385 stream2.width = kWidth;
1386 stream2.height = kHeight;
1387 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1388 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1389 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1390 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1391 QualityLimitationReason::kNone);
1392 // Bw disabled one layer.
1393 VideoCodec codec;
1394 codec.numberOfSimulcastStreams = 2;
1395 codec.simulcastStream[0].active = true;
1396 codec.simulcastStream[1].active = true;
1397 VideoBitrateAllocation allocation;
1398 // Some positive bitrate only on the first stream.
1399 allocation.SetBitrate(0, 0, 10000);
1400 allocation.SetBitrate(1, 0, 0);
1401 allocation.set_bw_limited(true);
1402 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1403 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1404 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1405 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1406 QualityLimitationReason::kBandwidth);
1407 // Bw enabled all layers.
1408 allocation.SetBitrate(1, 0, 10000);
1409 allocation.set_bw_limited(false);
1410 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1411 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1412 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1413 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1414 QualityLimitationReason::kNone);
1415
1416 // Screencast case
1417 // Configure two streams.
1418 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1419 config.number_of_streams = 2;
1420 stream1.width = kWidth;
1421 stream1.height = kHeight;
1422 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1423 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1424 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1425 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1426 QualityLimitationReason::kNone);
1427 // Bw disabled one layer.
1428 // Some positive bitrate only on the second stream.
1429 allocation.SetBitrate(0, 0, 10000);
1430 allocation.SetBitrate(1, 0, 0);
1431 allocation.set_bw_limited(true);
1432 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1433 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1434 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1435 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1436 QualityLimitationReason::kBandwidth);
1437 // Bw enabled all layers.
1438 allocation.SetBitrate(1, 0, 10000);
1439 allocation.set_bw_limited(false);
1440 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1441 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1442 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1443 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1444 QualityLimitationReason::kNone);
1445}
1446
asapersson59bac1a2016-01-07 23:36:00 -08001447TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001448 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001449 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1450
Pera48ddb72016-09-29 11:48:50 +02001451 // No switch, stats should not be updated.
1452 VideoEncoderConfig config;
1453 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001454 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001455 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001456
1457 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001458 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001459 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001460 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001461}
1462
asapersson320e45a2016-11-29 01:40:35 -08001463TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1464 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1465 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001466
asapersson320e45a2016-11-29 01:40:35 -08001467 statistics_proxy_.reset();
1468 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1469 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1470 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1471 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1472}
1473
1474TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001475 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001476 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001477 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1478 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1479 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001480 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001481
1482 // Not enough samples, stats should not be updated.
1483 for (int i = 0; i < kMinSamples - 1; ++i) {
1484 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001485 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001486 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1487 }
Åsa Persson0122e842017-10-16 12:19:23 +02001488 SetUp(); // Reset stats proxy also causes histograms to be reported.
1489 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1490 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1491
1492 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001493 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001494 for (int i = 0; i < kMinSamples; ++i) {
1495 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001496 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001497 encoded_image._encodedWidth = kWidth;
1498 encoded_image._encodedHeight = kHeight;
1499 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1500 encoded_image._encodedWidth = kWidth / 2;
1501 encoded_image._encodedHeight = kHeight / 2;
1502 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1503 }
1504
asapersson320e45a2016-11-29 01:40:35 -08001505 statistics_proxy_.reset();
1506 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1507 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1508 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1509 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1510}
1511
1512TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1513 const int kFps = 20;
1514 const int kMinPeriodicSamples = 6;
1515 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1516 for (int i = 0; i <= frames; ++i) {
1517 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1518 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1519 }
1520 statistics_proxy_.reset();
1521 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1522 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1523}
1524
1525TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1526 EncodedImage encoded_image;
1527 const int kFps = 20;
1528 const int kMinPeriodicSamples = 6;
1529 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001530 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001531 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001532 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001533 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1534 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001535 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1536 }
1537 statistics_proxy_.reset();
1538 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1539 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1540}
1541
1542TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1543 const int kFps = 20;
1544 const int kSuspendTimeMs = 10000;
1545 const int kMinPeriodicSamples = 6;
1546 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1547 for (int i = 0; i < frames; ++i) {
1548 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1549 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1550 }
1551 // Suspend.
1552 statistics_proxy_->OnSuspendChange(true);
1553 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1554
1555 for (int i = 0; i < frames; ++i) {
1556 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1557 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1558 }
1559 // Suspended time interval should not affect the framerate.
1560 statistics_proxy_.reset();
1561 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1562 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1563}
1564
1565TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1566 EncodedImage encoded_image;
1567 const int kFps = 20;
1568 const int kSuspendTimeMs = 10000;
1569 const int kMinPeriodicSamples = 6;
1570 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001571 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001572 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001573 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001574 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1575 }
1576 // Suspend.
1577 statistics_proxy_->OnSuspendChange(true);
1578 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1579
Åsa Persson0122e842017-10-16 12:19:23 +02001580 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001581 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001582 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001583 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1584 }
1585 // Suspended time interval should not affect the framerate.
1586 statistics_proxy_.reset();
1587 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1588 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1589}
1590
asaperssonf4e44af2017-04-19 02:01:06 -07001591TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001592 SendStatisticsProxy::AdaptationSteps cpu_counts;
1593 SendStatisticsProxy::AdaptationSteps quality_counts;
1594 cpu_counts.num_resolution_reductions = absl::nullopt;
1595 statistics_proxy_->OnAdaptationChanged(
1596 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1597 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001598
1599 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1600 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1601
1602 statistics_proxy_.reset();
1603 EXPECT_EQ(0,
1604 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1605}
1606
1607TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001608 SendStatisticsProxy::AdaptationSteps cpu_counts;
1609 SendStatisticsProxy::AdaptationSteps quality_counts;
1610 cpu_counts.num_resolution_reductions = 0;
1611 statistics_proxy_->OnAdaptationChanged(
1612 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1613 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001614
perkj803d97f2016-11-01 11:45:46 -07001615 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1616 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1617
Niels Möller213618e2018-07-24 09:29:58 +02001618 cpu_counts.num_resolution_reductions = 1;
1619 statistics_proxy_->OnAdaptationChanged(
1620 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1621 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001622
1623 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1624 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1625
1626 statistics_proxy_.reset();
1627 EXPECT_EQ(1,
1628 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1629 EXPECT_EQ(
1630 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1631}
1632
asapersson4374a092016-07-27 00:39:09 -07001633TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1634 const int64_t kTimeSec = 3;
1635 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1636 statistics_proxy_.reset();
1637 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1638 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1639 kTimeSec));
1640}
1641
1642TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1643 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1644 statistics_proxy_.reset();
1645 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1646}
1647
asapersson66d4b372016-12-19 06:50:53 -08001648TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1649 // First RTP packet sent.
1650 UpdateDataCounters(kFirstSsrc);
1651
1652 // Min runtime has passed.
1653 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1654 statistics_proxy_.reset();
1655 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1656 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1657}
1658
1659TEST_F(SendStatisticsProxyTest,
1660 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1661 // First RTP packet sent.
1662 UpdateDataCounters(kFirstSsrc);
1663
1664 // Min runtime has not passed.
1665 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1666 statistics_proxy_.reset();
1667 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1668 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1669}
1670
1671TEST_F(SendStatisticsProxyTest,
1672 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1673 // First RTP packet not sent.
1674 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1675 statistics_proxy_.reset();
1676 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1677}
1678
1679TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1680 // First RTP packet sent and min runtime passed.
1681 UpdateDataCounters(kFirstSsrc);
1682
1683 // No change. Video: 10000 ms, paused: 0 ms (0%).
1684 statistics_proxy_->OnSetEncoderTargetRate(50000);
1685 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1686 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1687
1688 statistics_proxy_.reset();
1689 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1690 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1691 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1692 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1693}
1694
1695TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1696 // First RTP packet sent and min runtime passed.
1697 UpdateDataCounters(kFirstSsrc);
1698
1699 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1700 statistics_proxy_->OnSetEncoderTargetRate(50000);
1701 fake_clock_.AdvanceTimeMilliseconds(7000);
1702 statistics_proxy_->OnSetEncoderTargetRate(0);
1703 fake_clock_.AdvanceTimeMilliseconds(3000);
1704 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1705
1706 statistics_proxy_.reset();
1707 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1708 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1709 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1710 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1711}
1712
1713TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1714 // First RTP packet sent.
1715 UpdateDataCounters(kFirstSsrc);
1716
1717 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1718 statistics_proxy_->OnSetEncoderTargetRate(0);
1719 fake_clock_.AdvanceTimeMilliseconds(1000);
1720 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1721 fake_clock_.AdvanceTimeMilliseconds(7000);
1722 statistics_proxy_->OnSetEncoderTargetRate(60000);
1723 fake_clock_.AdvanceTimeMilliseconds(3000);
1724 statistics_proxy_->OnSetEncoderTargetRate(0);
1725 fake_clock_.AdvanceTimeMilliseconds(250);
1726 statistics_proxy_->OnSetEncoderTargetRate(0);
1727 fake_clock_.AdvanceTimeMilliseconds(750);
1728 statistics_proxy_->OnSetEncoderTargetRate(60000);
1729 fake_clock_.AdvanceTimeMilliseconds(5000);
1730 statistics_proxy_->OnSetEncoderTargetRate(50000);
1731 fake_clock_.AdvanceTimeMilliseconds(4000);
1732 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1733
1734 statistics_proxy_.reset();
1735 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1736 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1737 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1738 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1739}
1740
1741TEST_F(SendStatisticsProxyTest,
1742 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1743 // First RTP packet sent.
1744 UpdateDataCounters(kFirstSsrc);
1745 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1746
1747 // Min runtime has not passed.
1748 statistics_proxy_->OnSetEncoderTargetRate(50000);
1749 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1750 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1751
1752 statistics_proxy_.reset();
1753 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1754}
1755
asapersson118ef002016-03-31 00:00:19 -07001756TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001757 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001758 CodecSpecificInfo codec_info;
1759 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001760
perkj803d97f2016-11-01 11:45:46 -07001761 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001762 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001763 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001764 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001765 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001766 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001767 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001768 }
1769 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001770 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1771 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1772 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1773 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001774}
1775
1776TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1777 VideoSendStream::Config config(nullptr);
1778 config.rtp.ssrcs.push_back(kFirstSsrc);
1779 statistics_proxy_.reset(new SendStatisticsProxy(
1780 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1781
asapersson118ef002016-03-31 00:00:19 -07001782 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001783 CodecSpecificInfo codec_info;
1784 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001785
perkj803d97f2016-11-01 11:45:46 -07001786 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001787 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001788 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001789 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001790 }
1791 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001792 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1793 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001794}
1795
asapersson5265fed2016-04-18 02:58:47 -07001796TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001797 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001798 CodecSpecificInfo codec_info;
1799 codec_info.codecType = kVideoCodecVP9;
1800 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001801
perkj803d97f2016-11-01 11:45:46 -07001802 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001803 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001804 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001805 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001806 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001807 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001808 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001809 }
1810 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001811 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1812 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1813 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1814 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001815}
1816
1817TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1818 VideoSendStream::Config config(nullptr);
1819 config.rtp.ssrcs.push_back(kFirstSsrc);
1820 statistics_proxy_.reset(new SendStatisticsProxy(
1821 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1822
asapersson5265fed2016-04-18 02:58:47 -07001823 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001824 CodecSpecificInfo codec_info;
1825 codec_info.codecType = kVideoCodecVP9;
1826 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001827
perkj803d97f2016-11-01 11:45:46 -07001828 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001829 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001830 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001831 }
1832 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001833 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1834 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001835}
1836
asapersson827cab32016-11-02 09:08:47 -07001837TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1838 EncodedImage encoded_image;
1839 CodecSpecificInfo codec_info;
1840 codec_info.codecType = kVideoCodecH264;
1841
1842 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001843 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001844 encoded_image.qp_ = kQpIdx0;
1845 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001846 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001847 encoded_image.qp_ = kQpIdx1;
1848 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001849 }
1850 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001851 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1852 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1853 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1854 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001855}
1856
asapersson4ee70462016-10-31 04:05:12 -07001857TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001858 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1859 // Configure one stream.
1860 VideoEncoderConfig config;
1861 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1862 VideoStream stream1;
1863 stream1.width = kWidth;
1864 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001865 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001866
1867 const int64_t kMaxEncodedFrameWindowMs = 800;
1868 const int kFps = 20;
1869 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1870 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1871 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1872
1873 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001874 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001875 encoded_image._encodedWidth = kWidth;
1876 encoded_image._encodedHeight = kHeight;
1877 for (int i = 0; i < kMinSamples; ++i) {
1878 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001879 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1880 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001881 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001882 }
asapersson4ee70462016-10-31 04:05:12 -07001883
1884 // Histograms are updated when the statistics_proxy_ is deleted.
1885 statistics_proxy_.reset();
1886 EXPECT_EQ(0, metrics::NumSamples(
1887 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1888 EXPECT_EQ(0, metrics::NumSamples(
1889 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1890}
1891
1892TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001893 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1894 // Configure two streams.
1895 VideoEncoderConfig config;
1896 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1897 VideoStream stream1;
1898 stream1.width = kWidth / 2;
1899 stream1.height = kHeight / 2;
1900 VideoStream stream2;
1901 stream2.width = kWidth;
1902 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001903 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001904
1905 const int64_t kMaxEncodedFrameWindowMs = 800;
1906 const int kFps = 20;
1907 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1908 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1909 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1910
1911 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001912 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001913 for (int i = 0; i < kMinSamples; ++i) {
1914 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001915 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1916 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001917 encoded_image._encodedWidth = kWidth;
1918 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001919 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001920 encoded_image._encodedWidth = kWidth / 2;
1921 encoded_image._encodedHeight = kHeight / 2;
1922 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1923 }
asapersson4ee70462016-10-31 04:05:12 -07001924
1925 // Histograms are updated when the statistics_proxy_ is deleted.
1926 statistics_proxy_.reset();
1927 EXPECT_EQ(1, metrics::NumSamples(
1928 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1929 EXPECT_EQ(1, metrics::NumEvents(
1930 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1931 // No resolution disabled.
1932 EXPECT_EQ(0, metrics::NumSamples(
1933 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1934}
1935
1936TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001937 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1938 // Configure two streams.
1939 VideoEncoderConfig config;
1940 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1941 VideoStream stream1;
1942 stream1.width = kWidth / 2;
1943 stream1.height = kHeight / 2;
1944 VideoStream stream2;
1945 stream2.width = kWidth;
1946 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001947 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001948
1949 const int64_t kMaxEncodedFrameWindowMs = 800;
1950 const int kFps = 20;
1951 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1952 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1953 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1954
1955 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001956 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001957 encoded_image._encodedWidth = kWidth / 2;
1958 encoded_image._encodedHeight = kHeight / 2;
1959 for (int i = 0; i < kMinSamples; ++i) {
1960 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001961 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1962 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001963 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001964 }
asapersson4ee70462016-10-31 04:05:12 -07001965
1966 // Histograms are updated when the statistics_proxy_ is deleted.
1967 statistics_proxy_.reset();
1968 EXPECT_EQ(1, metrics::NumSamples(
1969 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1970 EXPECT_EQ(1, metrics::NumEvents(
1971 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001972 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001973 EXPECT_EQ(1, metrics::NumSamples(
1974 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001975 EXPECT_EQ(1, metrics::NumEvents(
1976 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001977}
1978
1979TEST_F(SendStatisticsProxyTest,
1980 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001981 SendStatisticsProxy::AdaptationSteps cpu_counts;
1982 SendStatisticsProxy::AdaptationSteps quality_counts;
1983 quality_counts.num_resolution_reductions = absl::nullopt;
1984 statistics_proxy_->OnAdaptationChanged(
1985 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1986 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001987 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001988 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001989 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001990 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001991
1992 // Histograms are updated when the statistics_proxy_ is deleted.
1993 statistics_proxy_.reset();
1994 EXPECT_EQ(
1995 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1996 EXPECT_EQ(0, metrics::NumSamples(
1997 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1998}
1999
2000TEST_F(SendStatisticsProxyTest,
2001 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02002002 SendStatisticsProxy::AdaptationSteps cpu_counts;
2003 SendStatisticsProxy::AdaptationSteps quality_counts;
2004 quality_counts.num_resolution_reductions = 0;
2005 statistics_proxy_->OnAdaptationChanged(
2006 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2007 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002008 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002009 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002010 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002011 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002012
2013 // Histograms are updated when the statistics_proxy_ is deleted.
2014 statistics_proxy_.reset();
2015 EXPECT_EQ(
2016 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
2017 EXPECT_EQ(1, metrics::NumEvents(
2018 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
2019 // No resolution downscale.
2020 EXPECT_EQ(0, metrics::NumSamples(
2021 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2022}
2023
2024TEST_F(SendStatisticsProxyTest,
2025 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2026 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02002027 SendStatisticsProxy::AdaptationSteps cpu_counts;
2028 SendStatisticsProxy::AdaptationSteps quality_counts;
2029 quality_counts.num_resolution_reductions = kDownscales;
2030 statistics_proxy_->OnAdaptationChanged(
2031 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2032 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002033 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002034 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002035 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002036 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002037 // Histograms are updated when the statistics_proxy_ is deleted.
2038 statistics_proxy_.reset();
2039 EXPECT_EQ(
2040 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
2041 EXPECT_EQ(1, metrics::NumEvents(
2042 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
2043 // Resolution downscales.
2044 EXPECT_EQ(1, metrics::NumSamples(
2045 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2046 EXPECT_EQ(
2047 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2048 kDownscales));
2049}
2050
2051TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2052 // Initially false.
2053 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002054
Åsa Perssonaa329e72017-12-15 15:54:44 +01002055 // Configure two streams.
2056 VideoEncoderConfig config;
2057 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002058 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002059 VideoStream stream1;
2060 stream1.width = kWidth / 2;
2061 stream1.height = kHeight / 2;
2062 VideoStream stream2;
2063 stream2.width = kWidth;
2064 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002065 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002066
2067 const int64_t kMaxEncodedFrameWindowMs = 800;
2068 const int kFps = 20;
2069 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2070 kFps * kMaxEncodedFrameWindowMs / 1000;
2071
2072 // One stream encoded.
2073 EncodedImage encoded_image;
2074 encoded_image._encodedWidth = kWidth / 2;
2075 encoded_image._encodedHeight = kHeight / 2;
2076 for (int i = 0; i < kMinSamples; ++i) {
2077 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002078 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2079 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002080 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2081 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2082 }
2083
2084 // First frame removed from EncodedFrameMap, stats updated.
2085 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002086 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08002087 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2088 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2089
Åsa Perssonaa329e72017-12-15 15:54:44 +01002090 // Two streams encoded.
2091 for (int i = 0; i < kMinSamples; ++i) {
2092 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002093 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2094 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002095 encoded_image._encodedWidth = kWidth;
2096 encoded_image._encodedHeight = kHeight;
2097 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2098 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2099 encoded_image._encodedWidth = kWidth / 2;
2100 encoded_image._encodedHeight = kHeight / 2;
2101 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2102 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2103 }
2104
2105 // First frame with two streams removed, expect no resolution limit.
2106 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002107 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2108 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002109 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2110 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08002111
2112 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02002113 SendStatisticsProxy::AdaptationSteps cpu_counts;
2114 SendStatisticsProxy::AdaptationSteps quality_counts;
2115 quality_counts.num_resolution_reductions = 1;
2116 statistics_proxy_->OnAdaptationChanged(
2117 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2118 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002119 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2120 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002121
2122 // Adapt up.
2123 quality_counts.num_resolution_reductions = 0;
2124 statistics_proxy_->OnAdaptationChanged(
2125 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2126 quality_counts);
2127 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2128 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2129
2130 // Bw disabled one layer.
2131 VideoCodec codec;
2132 codec.numberOfSimulcastStreams = 2;
2133 codec.simulcastStream[0].active = true;
2134 codec.simulcastStream[1].active = true;
2135 VideoBitrateAllocation allocation;
2136 // Some positive bitrate only on the second stream.
2137 allocation.SetBitrate(1, 0, 10000);
2138 allocation.set_bw_limited(true);
2139 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2140 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002141}
2142
asapersson66d4b372016-12-19 06:50:53 -08002143TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2144 // Initially zero.
2145 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2146
2147 const int kBitrate = 100000;
2148 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2149 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2150
2151 statistics_proxy_->OnSetEncoderTargetRate(0);
2152 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2153}
2154
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002155TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002156 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002157 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2158 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002159 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002160 // From RtcpStatisticsCallback.
2161 RtcpStatistics rtcp_stats;
2162 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002163 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002164
2165 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002166 uint32_t total = 0;
2167 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002168 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002169 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002170
2171 // From FrameCountObserver.
2172 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002173 FrameCounts frame_counts;
2174 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002175 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002176
2177 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2178 EXPECT_TRUE(stats.substreams.empty());
2179}
2180
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002181TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2182 static const int kEncodedWidth = 123;
2183 static const int kEncodedHeight = 81;
2184 EncodedImage encoded_image;
2185 encoded_image._encodedWidth = kEncodedWidth;
2186 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002187 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002188
kjellander02b3d272016-04-20 05:05:54 -07002189 CodecSpecificInfo codec_info;
2190 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002191
kjellander02b3d272016-04-20 05:05:54 -07002192 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002193 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002194 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002195
2196 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002197 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2198 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2199 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2200 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002201
2202 // Forward almost to timeout, this should not have removed stats.
2203 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2204 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002205 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2206 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002207
2208 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2209 // resolution still times out (no global timeout for all stats).
2210 RtcpStatistics rtcp_statistics;
2211 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2212 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2213
2214 // Report stats for second SSRC to make sure it's not outdated along with the
2215 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002216 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002217
2218 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2219 // reported, but substream 1 should.
2220 fake_clock_.AdvanceTimeMilliseconds(1);
2221 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002222 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2223 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2224 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2225 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002226}
2227
Peter Boström20f3f942015-05-15 11:33:39 +02002228TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2229 static const int kEncodedWidth = 123;
2230 static const int kEncodedHeight = 81;
2231 EncodedImage encoded_image;
2232 encoded_image._encodedWidth = kEncodedWidth;
2233 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002234 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002235
kjellander02b3d272016-04-20 05:05:54 -07002236 CodecSpecificInfo codec_info;
2237 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002238
kjellander02b3d272016-04-20 05:05:54 -07002239 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002240 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002241 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002242
2243 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2244 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2245 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2246 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2247 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2248 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2249}
2250
2251TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002252 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002253 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2254 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2255 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2256
2257 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2258
2259 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002260 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002261 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002262 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002263 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2264 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2265 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2266}
2267
sprang07fb9be2016-02-24 07:55:00 -08002268TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2269 RtcpPacketTypeCounterObserver* proxy =
2270 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2271 RtcpPacketTypeCounter counters;
2272 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2273 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2274 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2275
2276 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2277
2278 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2279 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2280 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2281 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2282 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2283
2284 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2285 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2286
2287 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002288 VideoEncoderConfig config;
2289 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002290 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002291
asapersson01d70a32016-05-20 06:29:46 -07002292 EXPECT_EQ(1,
2293 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2294 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2295 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2296 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002297 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2298
2299 const int kRate = 60 * 2; // Packets per minute with two streams.
2300
asapersson01d70a32016-05-20 06:29:46 -07002301 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2302 1 * kRate));
2303 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2304 2 * kRate));
2305 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2306 3 * kRate));
2307 EXPECT_EQ(
2308 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2309 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002310
2311 // New start time but same counter values.
2312 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2313 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2314
2315 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2316
2317 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2318 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2319 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2320 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2321 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2322
2323 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2324 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2325
2326 SetUp(); // Reset stats proxy also causes histograms to be reported.
2327
asapersson01d70a32016-05-20 06:29:46 -07002328 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002329 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07002330 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002331 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07002332 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002333 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2334 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002335 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002336 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2337
asapersson01d70a32016-05-20 06:29:46 -07002338 EXPECT_EQ(1, metrics::NumEvents(
2339 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
2340 1 * kRate));
2341 EXPECT_EQ(1, metrics::NumEvents(
2342 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2343 2 * kRate));
2344 EXPECT_EQ(1, metrics::NumEvents(
2345 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2346 3 * kRate));
2347 EXPECT_EQ(1,
2348 metrics::NumEvents(
2349 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2350 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002351}
2352
asaperssona6a699a2016-11-25 03:52:46 -08002353TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2354 statistics_proxy_.reset(
2355 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2356 VideoEncoderConfig::ContentType::kRealtimeVideo));
2357
2358 StreamDataCountersCallback* proxy =
2359 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2360 StreamDataCounters counters;
2361 proxy->DataCountersUpdated(counters, kFirstSsrc);
2362 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2363
2364 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
2365 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
2366}
2367
2368TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2369 statistics_proxy_.reset(
2370 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2371 VideoEncoderConfig::ContentType::kRealtimeVideo));
2372
2373 StreamDataCountersCallback* proxy =
2374 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002375 StreamDataCounters counters;
2376 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002377
asapersson93e1e232017-02-06 05:18:35 -08002378 const int kMinRequiredPeriodSamples = 8;
2379 const int kPeriodIntervalMs = 2000;
2380 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2381 counters.transmitted.packets += 20;
2382 counters.transmitted.header_bytes += 500;
2383 counters.transmitted.padding_bytes += 1000;
2384 counters.transmitted.payload_bytes += 2000;
2385 counters.retransmitted.packets += 2;
2386 counters.retransmitted.header_bytes += 25;
2387 counters.retransmitted.padding_bytes += 100;
2388 counters.retransmitted.payload_bytes += 250;
2389 counters.fec = counters.retransmitted;
2390 rtx_counters.transmitted = counters.transmitted;
2391 // Advance one interval and update counters.
2392 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2393 proxy->DataCountersUpdated(counters, kFirstSsrc);
2394 proxy->DataCountersUpdated(counters, kSecondSsrc);
2395 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2396 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2397 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2398 }
asaperssona6a699a2016-11-25 03:52:46 -08002399
asaperssona6a699a2016-11-25 03:52:46 -08002400 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002401 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002402 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002403 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2404 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2405 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2406 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2407 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002408 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002409 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2410 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002411 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002412 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2413 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2414 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2415 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2416 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002417 EXPECT_EQ(1,
2418 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08002419 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002420 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002421}
2422
Erik Språng22c2b482016-03-01 09:40:42 +01002423TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2424 StreamDataCountersCallback* proxy =
2425 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2426 StreamDataCounters counters;
2427 StreamDataCounters rtx_counters;
2428 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002429
asapersson93e1e232017-02-06 05:18:35 -08002430 const int kMinRequiredPeriodSamples = 8;
2431 const int kPeriodIntervalMs = 2000;
2432 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2433 counters.transmitted.packets += 20;
2434 counters.transmitted.header_bytes += 500;
2435 counters.transmitted.padding_bytes += 1000;
2436 counters.transmitted.payload_bytes += 2000;
2437 counters.retransmitted.packets += 2;
2438 counters.retransmitted.header_bytes += 25;
2439 counters.retransmitted.padding_bytes += 100;
2440 counters.retransmitted.payload_bytes += 250;
2441 counters.fec = counters.retransmitted;
2442 rtx_counters.transmitted = counters.transmitted;
2443 // Advance one interval and update counters.
2444 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2445 proxy->DataCountersUpdated(counters, kFirstSsrc);
2446 proxy->DataCountersUpdated(counters, kSecondSsrc);
2447 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2448 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2449 }
Erik Språng22c2b482016-03-01 09:40:42 +01002450
2451 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002452 VideoEncoderConfig config;
2453 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002454 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002455
asapersson93e1e232017-02-06 05:18:35 -08002456 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002457 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002458 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2459 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2460 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2461 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2462 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002463 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002464 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2465 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002466 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002467 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2468 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2469 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2470 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2471 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002472 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002473 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002474 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002475 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002476
asapersson93e1e232017-02-06 05:18:35 -08002477 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002478 // Double counter values, this should result in the same counts as before but
2479 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002480 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2481 counters.transmitted.packets += 20;
2482 counters.transmitted.header_bytes += 500;
2483 counters.transmitted.padding_bytes += 1000;
2484 counters.transmitted.payload_bytes += 2000;
2485 counters.retransmitted.packets += 2;
2486 counters.retransmitted.header_bytes += 25;
2487 counters.retransmitted.padding_bytes += 100;
2488 counters.retransmitted.payload_bytes += 250;
2489 counters.fec = counters.retransmitted;
2490 rtx_counters.transmitted = counters.transmitted;
2491 // Advance one interval and update counters.
2492 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2493 proxy->DataCountersUpdated(counters, kFirstSsrc);
2494 proxy->DataCountersUpdated(counters, kSecondSsrc);
2495 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2496 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2497 }
Erik Språng22c2b482016-03-01 09:40:42 +01002498
asapersson93e1e232017-02-06 05:18:35 -08002499 // Reset stats proxy also causes histograms to be reported.
2500 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002501
asapersson93e1e232017-02-06 05:18:35 -08002502 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002503 EXPECT_EQ(1,
2504 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002505 EXPECT_EQ(
2506 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2507 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2508 EXPECT_EQ(
2509 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2510 EXPECT_EQ(1, metrics::NumEvents(
2511 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2512 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002513 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002514 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002515 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002516 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2517 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002518 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002519 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002520 EXPECT_EQ(1, metrics::NumEvents(
2521 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2522 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2523 EXPECT_EQ(
2524 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2525 EXPECT_EQ(1, metrics::NumEvents(
2526 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2527 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002528 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002529 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002530 EXPECT_EQ(1,
2531 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002532 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2533}
Erik Språng22c2b482016-03-01 09:40:42 +01002534
asapersson93e1e232017-02-06 05:18:35 -08002535TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2536 StreamDataCountersCallback* proxy =
2537 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2538 StreamDataCounters counters;
2539 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002540
asapersson93e1e232017-02-06 05:18:35 -08002541 const int kMinRequiredPeriodSamples = 8;
2542 const int kPeriodIntervalMs = 2000;
2543 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2544 counters.transmitted.packets += 20;
2545 counters.transmitted.header_bytes += 500;
2546 counters.transmitted.payload_bytes += 2000;
2547 counters.fec = counters.retransmitted;
2548 // Advance one interval and update counters.
2549 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2550 proxy->DataCountersUpdated(counters, kFirstSsrc);
2551 }
2552
2553 // RTX enabled. No data sent over RTX.
2554 statistics_proxy_.reset();
2555 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2556 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2557}
2558
2559TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2560 VideoSendStream::Config config(nullptr);
2561 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2562 statistics_proxy_.reset(new SendStatisticsProxy(
2563 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2564
2565 StreamDataCountersCallback* proxy =
2566 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2567 StreamDataCounters counters;
2568
2569 const int kMinRequiredPeriodSamples = 8;
2570 const int kPeriodIntervalMs = 2000;
2571 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2572 counters.transmitted.packets += 20;
2573 counters.transmitted.header_bytes += 500;
2574 counters.transmitted.payload_bytes += 2000;
2575 counters.fec = counters.retransmitted;
2576 // Advance one interval and update counters.
2577 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2578 proxy->DataCountersUpdated(counters, kFirstSsrc);
2579 }
2580
2581 // RTX not enabled.
2582 statistics_proxy_.reset();
2583 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2584}
2585
2586TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2587 StreamDataCountersCallback* proxy =
2588 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2589 StreamDataCounters counters;
2590 StreamDataCounters rtx_counters;
2591
2592 const int kMinRequiredPeriodSamples = 8;
2593 const int kPeriodIntervalMs = 2000;
2594 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2595 counters.transmitted.packets += 20;
2596 counters.transmitted.header_bytes += 500;
2597 counters.transmitted.payload_bytes += 2000;
2598 // Advance one interval and update counters.
2599 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2600 proxy->DataCountersUpdated(counters, kFirstSsrc);
2601 }
2602
2603 // FEC enabled. No FEC data sent.
2604 statistics_proxy_.reset();
2605 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2606 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2607}
2608
2609TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2610 VideoSendStream::Config config(nullptr);
2611 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2612 statistics_proxy_.reset(new SendStatisticsProxy(
2613 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2614
2615 StreamDataCountersCallback* proxy =
2616 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2617 StreamDataCounters counters;
2618
2619 const int kMinRequiredPeriodSamples = 8;
2620 const int kPeriodIntervalMs = 2000;
2621 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2622 counters.transmitted.packets += 20;
2623 counters.transmitted.header_bytes += 500;
2624 counters.transmitted.payload_bytes += 2000;
2625 counters.fec = counters.retransmitted;
2626 // Advance one interval and update counters.
2627 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2628 proxy->DataCountersUpdated(counters, kFirstSsrc);
2629 }
2630
2631 // FEC not enabled.
2632 statistics_proxy_.reset();
2633 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002634}
2635
asapersson8d75ac72017-09-15 06:41:15 -07002636TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002637 const std::string kName = "encoderName";
2638 statistics_proxy_->OnEncoderImplementationChanged(kName);
2639 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002640}
2641
Sergey Silkinbb081a62018-09-04 18:34:22 +02002642TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2643 static const int kEncodedWidth = 123;
2644 static const int kEncodedHeight = 81;
2645 EncodedImage encoded_image;
2646 encoded_image._encodedWidth = kEncodedWidth;
2647 encoded_image._encodedHeight = kEncodedHeight;
2648 encoded_image.SetSpatialIndex(0);
2649
2650 CodecSpecificInfo codec_info;
2651 codec_info.codecType = kVideoCodecVP9;
2652
2653 // For first picture, it is expected that low layer updates resolution.
2654 codec_info.codecSpecific.VP9.end_of_picture = false;
2655 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2656 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2657 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2658 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2659
2660 // Top layer updates resolution.
2661 encoded_image._encodedWidth = kEncodedWidth * 2;
2662 encoded_image._encodedHeight = kEncodedHeight * 2;
2663 codec_info.codecSpecific.VP9.end_of_picture = true;
2664 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2665 stats = statistics_proxy_->GetStats();
2666 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2667 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2668
2669 // Low layer of next frame doesn't update resolution.
2670 encoded_image._encodedWidth = kEncodedWidth;
2671 encoded_image._encodedHeight = kEncodedHeight;
2672 codec_info.codecSpecific.VP9.end_of_picture = false;
2673 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2674 stats = statistics_proxy_->GetStats();
2675 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2676 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2677}
2678
asapersson8d75ac72017-09-15 06:41:15 -07002679class ForcedFallbackTest : public SendStatisticsProxyTest {
2680 public:
2681 explicit ForcedFallbackTest(const std::string& field_trials)
2682 : SendStatisticsProxyTest(field_trials) {
2683 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002684 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002685 encoded_image_._encodedWidth = kWidth;
2686 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002687 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002688 }
2689
2690 ~ForcedFallbackTest() override {}
2691
2692 protected:
2693 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002694 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2695
asapersson8d75ac72017-09-15 06:41:15 -07002696 // First frame is not updating stats, insert initial frame.
2697 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2698 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2699 }
2700 for (int i = 0; i < num_frames; ++i) {
2701 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2702 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2703 }
2704 // Add frame to include last time interval.
2705 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2706 }
2707
2708 EncodedImage encoded_image_;
2709 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002710 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002711 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2712 const int kFrameIntervalMs = 1000;
2713 const int kMinFrames = 20; // Min run time 20 sec.
2714};
2715
2716class ForcedFallbackDisabled : public ForcedFallbackTest {
2717 public:
2718 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002719 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2720 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002721};
2722
2723class ForcedFallbackEnabled : public ForcedFallbackTest {
2724 public:
2725 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002726 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2727 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002728};
2729
2730TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2731 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2732 statistics_proxy_.reset();
2733 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2734 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2735}
2736
2737TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2738 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002739 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002740 statistics_proxy_.reset();
2741 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2742 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2743 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2744 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2745}
2746
2747TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2748 codec_info_.codecType = kVideoCodecVP9;
2749 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2750 statistics_proxy_.reset();
2751 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2752 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2753}
2754
2755TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2756 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2757 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2758 statistics_proxy_.reset();
2759 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2760 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2761}
2762
2763TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002764 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002765 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2766 statistics_proxy_.reset();
2767 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2768 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2769}
2770
2771TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2772 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2773 statistics_proxy_.reset();
2774 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2775 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2776}
2777
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002778TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2779 InsertEncodedFrames(1, kFrameIntervalMs);
2780 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2781}
2782
2783TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2784 InsertEncodedFrames(1, kFrameIntervalMs);
2785 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2786}
2787
2788TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002789 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002790 InsertEncodedFrames(1, kFrameIntervalMs);
2791 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2792}
2793
2794TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2795 encoded_image_._encodedWidth = kWidth + 1;
2796 InsertEncodedFrames(1, kFrameIntervalMs);
2797 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2798}
2799
2800TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002801 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002802 InsertEncodedFrames(1, kFrameIntervalMs);
2803 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2804}
2805
2806TEST_F(ForcedFallbackDisabled,
2807 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2808 encoded_image_._encodedWidth = kWidth + 1;
2809 statistics_proxy_->OnMinPixelLimitReached();
2810 InsertEncodedFrames(1, kFrameIntervalMs);
2811 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2812}
2813
asapersson8d75ac72017-09-15 06:41:15 -07002814TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2815 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002816 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002817 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002818 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002819 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002820 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002821 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002822
2823 statistics_proxy_.reset();
2824 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2825 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2826 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2827 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2828}
2829
2830TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2831 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2832 const int kMaxFrameDiffMs = 2000;
2833
2834 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2835 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002836 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002837 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002838 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002839 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002840 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002841 InsertEncodedFrames(20, 1000);
2842 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2843 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002844 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002845 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002846 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002847 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002848 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002849 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002850 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002851
2852 statistics_proxy_.reset();
2853 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2854 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2855 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2856 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2857}
2858
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002859TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2860 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002861 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002862 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2863
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002864 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002865 statistics_proxy_.reset();
2866 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2867 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2868}
2869
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002870TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2871 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002872 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002873 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2874
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002875 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002876 statistics_proxy_.reset();
2877 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2878 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2879}
2880
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002881} // namespace webrtc