blob: 3f5ebd53b4ed147c6f4dda5e7e8da114af96fd5f [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;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100400 fake_global_clock.SetTime(
401 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200402
403 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
404 EncodedImage encoded_image;
405
406 // First frame
407 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
408 uint64_t first_total_encoded_bytes_target =
409 statistics_proxy_->GetStats().total_encoded_bytes_target;
410 // Second frame
411 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100412 fake_global_clock.SetTime(
413 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200414 encoded_image.SetTimestamp(encoded_image.Timestamp() +
415 90 * kInterframeDelayMs);
416 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
417
418 auto stats = statistics_proxy_->GetStats();
419 // By the time the second frame arrives, one frame has previously arrived
420 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
421 // the second frame's arrival should be 10 FPS.
422 uint64_t delta_encoded_bytes_target =
423 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
424 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
425}
426
asapersson09f05612017-05-15 23:40:18 -0700427TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200428 SendStatisticsProxy::AdaptationSteps cpu_counts;
429 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700430 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700431 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200432 cpu_counts.num_framerate_reductions = 1;
433 cpu_counts.num_resolution_reductions = 0;
434 statistics_proxy_->OnAdaptationChanged(
435 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
436 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700437 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700438 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200439 cpu_counts.num_framerate_reductions = 0;
440 cpu_counts.num_resolution_reductions = 1;
441 statistics_proxy_->OnAdaptationChanged(
442 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
443 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700444 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700445 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200446 cpu_counts.num_framerate_reductions = 1;
447 cpu_counts.num_resolution_reductions = absl::nullopt;
448 statistics_proxy_->OnAdaptationChanged(
449 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
450 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700451 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700452 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200453 cpu_counts.num_framerate_reductions = absl::nullopt;
454 cpu_counts.num_resolution_reductions = absl::nullopt;
455 statistics_proxy_->OnAdaptationChanged(
456 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
457 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700458 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
459 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
460}
461
462TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200463 SendStatisticsProxy::AdaptationSteps cpu_counts;
464 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700465 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
466 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200467 quality_counts.num_framerate_reductions = 1;
468 quality_counts.num_resolution_reductions = 0;
469 statistics_proxy_->OnAdaptationChanged(
470 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
471 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700472 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
473 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200474 quality_counts.num_framerate_reductions = 0;
475 quality_counts.num_resolution_reductions = 1;
476 statistics_proxy_->OnAdaptationChanged(
477 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
478 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700479 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
480 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200481 quality_counts.num_framerate_reductions = 1;
482 quality_counts.num_resolution_reductions = absl::nullopt;
483 statistics_proxy_->OnAdaptationChanged(
484 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
485 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700486 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
487 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200488 quality_counts.num_framerate_reductions = absl::nullopt;
489 quality_counts.num_resolution_reductions = absl::nullopt;
490 statistics_proxy_->OnAdaptationChanged(
491 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
492 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700493 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
494 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
495}
496
497TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200498 SendStatisticsProxy::AdaptationSteps cpu_counts;
499 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700500 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
501
Niels Möller213618e2018-07-24 09:29:58 +0200502 cpu_counts.num_resolution_reductions = 1;
503 statistics_proxy_->OnAdaptationChanged(
504 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
505 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700506 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700507 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
508 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
509
Niels Möller213618e2018-07-24 09:29:58 +0200510 cpu_counts.num_resolution_reductions = 2;
511 statistics_proxy_->OnAdaptationChanged(
512 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
513 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700514 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
515 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700516 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700517 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700518}
519
asapersson09f05612017-05-15 23:40:18 -0700520TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200521 SendStatisticsProxy::AdaptationSteps cpu_counts;
522 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700523 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
524
Niels Möller213618e2018-07-24 09:29:58 +0200525 quality_counts.num_framerate_reductions = 1;
526 statistics_proxy_->OnAdaptationChanged(
527 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
528 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700529 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
530 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700531 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
532
Niels Möller213618e2018-07-24 09:29:58 +0200533 quality_counts.num_framerate_reductions = 0;
534 statistics_proxy_->OnAdaptationChanged(
535 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
536 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700537 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700538 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700539 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
540 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700541}
542
asapersson09f05612017-05-15 23:40:18 -0700543TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700544 // First RTP packet sent.
545 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700546 // Min runtime has passed.
547 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
548 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100549 EXPECT_METRIC_EQ(
550 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
551 EXPECT_METRIC_EQ(
552 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700553}
554
555TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700556 // First RTP packet sent.
557 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700558 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200559 SendStatisticsProxy::AdaptationSteps cpu_counts;
560 SendStatisticsProxy::AdaptationSteps quality_counts;
561 statistics_proxy_->OnAdaptationChanged(
562 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
563 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700564 // Min runtime has not passed.
565 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
566 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100567 EXPECT_METRIC_EQ(
568 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
569 EXPECT_METRIC_EQ(
570 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700571}
572
asapersson09f05612017-05-15 23:40:18 -0700573TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700574 // First RTP packet sent.
575 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700576 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200577 SendStatisticsProxy::AdaptationSteps cpu_counts;
578 SendStatisticsProxy::AdaptationSteps quality_counts;
579 statistics_proxy_->OnAdaptationChanged(
580 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
581 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700582 // Min runtime has passed.
583 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
584 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100585 EXPECT_METRIC_EQ(
586 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
587 EXPECT_METRIC_EQ(
588 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
589 EXPECT_METRIC_EQ(
590 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
591 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700592 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
593}
594
595TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700596 // First RTP packet sent.
597 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700598 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200599 SendStatisticsProxy::AdaptationSteps cpu_counts;
600 SendStatisticsProxy::AdaptationSteps quality_counts;
601 statistics_proxy_->OnAdaptationChanged(
602 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
603 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700604 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200605 statistics_proxy_->OnAdaptationChanged(
606 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
607 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700608 fake_clock_.AdvanceTimeMilliseconds(10000);
609 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100610 EXPECT_METRIC_EQ(
611 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
612 EXPECT_METRIC_EQ(
613 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700614}
615
Åsa Persson875841d2018-01-08 08:49:53 +0100616TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
617 // First RTP packet sent.
618 UpdateDataCounters(kFirstSsrc);
619 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200620 SendStatisticsProxy::AdaptationSteps cpu_counts;
621 SendStatisticsProxy::AdaptationSteps quality_counts;
622 statistics_proxy_->OnAdaptationChanged(
623 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
624 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100625 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200626 statistics_proxy_->OnAdaptationChanged(
627 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
628 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100629 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
630 fake_clock_.AdvanceTimeMilliseconds(10000);
631 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100632 EXPECT_METRIC_EQ(
633 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
634 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100635 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
636}
637
638TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
639 // First RTP packet sent.
640 UpdateDataCounters(kFirstSsrc);
641 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200642 SendStatisticsProxy::AdaptationSteps cpu_counts;
643 SendStatisticsProxy::AdaptationSteps quality_counts;
644 statistics_proxy_->OnAdaptationChanged(
645 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
646 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100647 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200648 quality_counts.num_resolution_reductions = 1;
649 statistics_proxy_->OnAdaptationChanged(
650 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
651 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100652 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200653 quality_counts.num_resolution_reductions = 2;
654 statistics_proxy_->OnAdaptationChanged(
655 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
656 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100657 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200658 quality_counts.num_resolution_reductions = 3;
659 statistics_proxy_->OnAdaptationChanged(
660 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
661 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100662 fake_clock_.AdvanceTimeMilliseconds(10000);
663 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100664 EXPECT_METRIC_EQ(
665 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
666 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100667 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
668}
669
670TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
671 // First RTP packet sent.
672 UpdateDataCounters(kFirstSsrc);
673 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200674 SendStatisticsProxy::AdaptationSteps cpu_counts;
675 SendStatisticsProxy::AdaptationSteps quality_counts;
676 statistics_proxy_->OnAdaptationChanged(
677 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
678 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100679 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200680 statistics_proxy_->OnAdaptationChanged(
681 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
682 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100683 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
684 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
685 fake_clock_.AdvanceTimeMilliseconds(10000);
686 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100687 EXPECT_METRIC_EQ(
688 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
689 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100690 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
691}
692
693TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
694 // First RTP packet sent.
695 UpdateDataCounters(kFirstSsrc);
696 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200697 SendStatisticsProxy::AdaptationSteps cpu_counts;
698 SendStatisticsProxy::AdaptationSteps quality_counts;
699 statistics_proxy_->OnAdaptationChanged(
700 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
701 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100702 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200703 quality_counts.num_resolution_reductions = 1;
704 statistics_proxy_->OnAdaptationChanged(
705 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
706 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100707 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200708 quality_counts.num_resolution_reductions = 2;
709 statistics_proxy_->OnAdaptationChanged(
710 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
711 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100712 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200713 quality_counts.num_resolution_reductions = 3;
714 statistics_proxy_->OnAdaptationChanged(
715 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
716 quality_counts);
717 quality_counts.num_framerate_reductions = 1;
718 statistics_proxy_->OnAdaptationChanged(
719 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
720 quality_counts);
721 quality_counts.num_framerate_reductions = 0;
722 statistics_proxy_->OnAdaptationChanged(
723 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
724 quality_counts);
725 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
726 statistics_proxy_->OnAdaptationChanged(
727 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
728 quality_counts);
729 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
730 statistics_proxy_->OnAdaptationChanged(
731 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
732 quality_counts);
733 quality_counts.num_resolution_reductions = 0;
734 statistics_proxy_->OnAdaptationChanged(
735 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
736 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100737
738 fake_clock_.AdvanceTimeMilliseconds(10000);
739 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100740 EXPECT_METRIC_EQ(
741 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
742 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100743 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
744}
745
asapersson6eca98b2017-04-04 23:40:50 -0700746TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700747 // First RTP packet sent.
748 UpdateDataCounters(kFirstSsrc);
749
asapersson09f05612017-05-15 23:40:18 -0700750 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200751 SendStatisticsProxy::AdaptationSteps cpu_counts;
752 SendStatisticsProxy::AdaptationSteps quality_counts;
753 quality_counts.num_framerate_reductions = absl::nullopt;
754 quality_counts.num_resolution_reductions = absl::nullopt;
755 statistics_proxy_->OnAdaptationChanged(
756 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
757 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700758 fake_clock_.AdvanceTimeMilliseconds(10000);
759
asapersson09f05612017-05-15 23:40:18 -0700760 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700761 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200762 quality_counts.num_framerate_reductions = 0;
763 statistics_proxy_->OnAdaptationChanged(
764 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
765 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700766 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200767 statistics_proxy_->OnAdaptationChanged(
768 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
769 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700770 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200771 statistics_proxy_->OnAdaptationChanged(
772 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
773 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700774 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200775 statistics_proxy_->OnAdaptationChanged(
776 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
777 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700778
asapersson09f05612017-05-15 23:40:18 -0700779 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200780 quality_counts.num_framerate_reductions = absl::nullopt;
781 statistics_proxy_->OnAdaptationChanged(
782 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
783 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700784 fake_clock_.AdvanceTimeMilliseconds(30000);
785
asapersson09f05612017-05-15 23:40:18 -0700786 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700787 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200788 quality_counts.num_resolution_reductions = 0;
789 statistics_proxy_->OnAdaptationChanged(
790 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
791 quality_counts);
792 statistics_proxy_->OnAdaptationChanged(
793 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
794 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700795 fake_clock_.AdvanceTimeMilliseconds(10000);
796
asapersson09f05612017-05-15 23:40:18 -0700797 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200798 quality_counts.num_resolution_reductions = absl::nullopt;
799 statistics_proxy_->OnAdaptationChanged(
800 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
801 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700802 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200803 statistics_proxy_->OnAdaptationChanged(
804 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
805 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700806 fake_clock_.AdvanceTimeMilliseconds(20000);
807
asapersson0944a802017-04-07 00:57:58 -0700808 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700809 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100810 EXPECT_METRIC_EQ(
811 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
812 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700813 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
814}
815
asapersson0944a802017-04-07 00:57:58 -0700816TEST_F(SendStatisticsProxyTest,
817 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
818 // First RTP packet sent.
819 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700820
asapersson0944a802017-04-07 00:57:58 -0700821 // Suspend and resume video.
822 statistics_proxy_->OnSuspendChange(true);
823 fake_clock_.AdvanceTimeMilliseconds(5000);
824 statistics_proxy_->OnSuspendChange(false);
825
826 // Min runtime has passed but scaling not enabled.
827 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
828 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100829 EXPECT_METRIC_EQ(
830 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
831 EXPECT_METRIC_EQ(
832 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700833}
834
835TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
836 // First RTP packet sent.
837 UpdateDataCounters(kFirstSsrc);
838
asapersson09f05612017-05-15 23:40:18 -0700839 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200840 SendStatisticsProxy::AdaptationSteps cpu_counts;
841 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700842 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200843 statistics_proxy_->OnAdaptationChanged(
844 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
845 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700846 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200847 statistics_proxy_->OnAdaptationChanged(
848 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
849 quality_counts);
850 statistics_proxy_->OnAdaptationChanged(
851 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
852 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700853
854 // Suspend and resume video.
855 statistics_proxy_->OnSuspendChange(true);
856 fake_clock_.AdvanceTimeMilliseconds(30000);
857 statistics_proxy_->OnSuspendChange(false);
858
859 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200860 statistics_proxy_->OnAdaptationChanged(
861 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
862 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700863 fake_clock_.AdvanceTimeMilliseconds(10000);
864
865 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
866 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100867 EXPECT_METRIC_EQ(
868 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
869 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700870 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
871}
872
873TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
874 // First RTP packet sent.
875 UpdateDataCounters(kFirstSsrc);
876
877 // Video not suspended.
878 statistics_proxy_->OnSuspendChange(false);
879 fake_clock_.AdvanceTimeMilliseconds(30000);
880
asapersson09f05612017-05-15 23:40:18 -0700881 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200882 SendStatisticsProxy::AdaptationSteps cpu_counts;
883 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700884 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200885 statistics_proxy_->OnAdaptationChanged(
886 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
887 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700888 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200889 statistics_proxy_->OnAdaptationChanged(
890 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
891 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700892
893 // Video not suspended, stats time already started.
894 statistics_proxy_->OnSuspendChange(false);
895 fake_clock_.AdvanceTimeMilliseconds(10000);
896
asapersson09f05612017-05-15 23:40:18 -0700897 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200898 cpu_counts.num_framerate_reductions = absl::nullopt;
899 cpu_counts.num_resolution_reductions = absl::nullopt;
900 statistics_proxy_->OnAdaptationChanged(
901 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
902 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700903 fake_clock_.AdvanceTimeMilliseconds(30000);
904
905 // Suspend and resume video, stats time not started when scaling not enabled.
906 statistics_proxy_->OnSuspendChange(true);
907 fake_clock_.AdvanceTimeMilliseconds(30000);
908 statistics_proxy_->OnSuspendChange(false);
909 fake_clock_.AdvanceTimeMilliseconds(30000);
910
asapersson09f05612017-05-15 23:40:18 -0700911 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700912 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200913 cpu_counts.num_framerate_reductions = 0;
914 cpu_counts.num_resolution_reductions = 0;
915 statistics_proxy_->OnAdaptationChanged(
916 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
917 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700918 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200919 statistics_proxy_->OnAdaptationChanged(
920 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
921 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700922
923 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
924 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100925 EXPECT_METRIC_EQ(
926 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
927 EXPECT_METRIC_EQ(
928 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700929}
930
931TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
932 // First RTP packet sent.
933 UpdateDataCounters(kFirstSsrc);
934
935 // Video suspended.
936 statistics_proxy_->OnSuspendChange(true);
937
asapersson09f05612017-05-15 23:40:18 -0700938 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200939 SendStatisticsProxy::AdaptationSteps cpu_counts;
940 SendStatisticsProxy::AdaptationSteps quality_counts;
941 statistics_proxy_->OnAdaptationChanged(
942 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
943 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700944 fake_clock_.AdvanceTimeMilliseconds(10000);
945
946 // Resume video, stats time started.
947 // Adapt changes: 1, elapsed time: 10 sec.
948 statistics_proxy_->OnSuspendChange(false);
949 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200950 statistics_proxy_->OnAdaptationChanged(
951 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
952 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700953
954 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
955 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100956 EXPECT_METRIC_EQ(
957 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
958 EXPECT_METRIC_EQ(
959 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -0700960}
961
962TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700963 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700964 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200965 SendStatisticsProxy::AdaptationSteps cpu_counts;
966 SendStatisticsProxy::AdaptationSteps quality_counts;
967 statistics_proxy_->OnAdaptationChanged(
968 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
969 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700970 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700971 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700972
asapersson0944a802017-04-07 00:57:58 -0700973 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700974 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200975 statistics_proxy_->OnAdaptationChanged(
976 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
977 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700978 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700979
asapersson0944a802017-04-07 00:57:58 -0700980 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700981 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100982 EXPECT_METRIC_EQ(
983 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
984 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700985 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
986}
987
988TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700989 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200990 SendStatisticsProxy::AdaptationSteps cpu_counts;
991 SendStatisticsProxy::AdaptationSteps quality_counts;
992 statistics_proxy_->OnAdaptationChanged(
993 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
994 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700995 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200996 cpu_counts.num_framerate_reductions = absl::nullopt;
997 cpu_counts.num_resolution_reductions = absl::nullopt;
998 statistics_proxy_->OnAdaptationChanged(
999 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1000 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001001
1002 // Send first packet, scaling disabled.
1003 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001004 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001005 fake_clock_.AdvanceTimeMilliseconds(60000);
1006
asapersson09f05612017-05-15 23:40:18 -07001007 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +02001008 cpu_counts.num_resolution_reductions = 0;
1009 statistics_proxy_->OnAdaptationChanged(
1010 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1011 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001012 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001013 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001014
asapersson0944a802017-04-07 00:57:58 -07001015 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001016 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001017 statistics_proxy_->OnAdaptationChanged(
1018 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1019 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001020
asapersson0944a802017-04-07 00:57:58 -07001021 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001022 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001023 EXPECT_METRIC_EQ(
1024 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1025 EXPECT_METRIC_EQ(
1026 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001027}
1028
1029TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001030 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001031 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001032 SendStatisticsProxy::AdaptationSteps cpu_counts;
1033 SendStatisticsProxy::AdaptationSteps quality_counts;
1034 quality_counts.num_framerate_reductions = absl::nullopt;
1035 quality_counts.num_resolution_reductions = absl::nullopt;
1036 statistics_proxy_->OnAdaptationChanged(
1037 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1038 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001039
asapersson0944a802017-04-07 00:57:58 -07001040 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001041 statistics_proxy_->OnAdaptationChanged(
1042 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1043 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001044 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +02001045 statistics_proxy_->OnAdaptationChanged(
1046 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1047 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001048 fake_clock_.AdvanceTimeMilliseconds(9000);
1049
1050 // Switch content type, real-time stats should be updated.
1051 VideoEncoderConfig config;
1052 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001053 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001054 EXPECT_METRIC_EQ(
1055 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1056 EXPECT_METRIC_EQ(
1057 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1058 EXPECT_METRIC_EQ(
1059 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001060
asapersson0944a802017-04-07 00:57:58 -07001061 // First RTP packet sent, scaling enabled.
1062 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001063 statistics_proxy_->OnAdaptationChanged(
1064 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1065 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001066
asapersson0944a802017-04-07 00:57:58 -07001067 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001068 statistics_proxy_->OnAdaptationChanged(
1069 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1070 quality_counts);
1071 statistics_proxy_->OnAdaptationChanged(
1072 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1073 quality_counts);
1074 statistics_proxy_->OnAdaptationChanged(
1075 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1076 quality_counts);
1077 statistics_proxy_->OnAdaptationChanged(
1078 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1079 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001080 fake_clock_.AdvanceTimeMilliseconds(120000);
1081
1082 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001083 EXPECT_METRIC_EQ(1,
1084 metrics::NumSamples(
1085 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1086 EXPECT_METRIC_EQ(
1087 1, metrics::NumEvents(
1088 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1089 EXPECT_METRIC_EQ(
1090 0, metrics::NumSamples(
1091 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001092}
1093
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001094TEST_F(SendStatisticsProxyTest,
1095 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
1096 SendStatisticsProxy::AdaptationSteps cpu_counts;
1097 SendStatisticsProxy::AdaptationSteps quality_counts;
1098
1099 cpu_counts.num_resolution_reductions = 1;
1100
1101 statistics_proxy_->OnAdaptationChanged(
1102 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1103 quality_counts);
1104
1105 EXPECT_EQ(QualityLimitationReason::kCpu,
1106 statistics_proxy_->GetStats().quality_limitation_reason);
1107}
1108
1109TEST_F(SendStatisticsProxyTest,
1110 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
1111 SendStatisticsProxy::AdaptationSteps cpu_counts;
1112 SendStatisticsProxy::AdaptationSteps quality_counts;
1113
1114 cpu_counts.num_framerate_reductions = 1;
1115
1116 statistics_proxy_->OnAdaptationChanged(
1117 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1118 quality_counts);
1119
1120 EXPECT_EQ(QualityLimitationReason::kCpu,
1121 statistics_proxy_->GetStats().quality_limitation_reason);
1122}
1123
1124TEST_F(SendStatisticsProxyTest,
1125 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
1126 SendStatisticsProxy::AdaptationSteps cpu_counts;
1127 SendStatisticsProxy::AdaptationSteps quality_counts;
1128
1129 quality_counts.num_resolution_reductions = 1;
1130
1131 statistics_proxy_->OnAdaptationChanged(
1132 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1133 quality_counts);
1134
1135 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1136 statistics_proxy_->GetStats().quality_limitation_reason);
1137}
1138
1139TEST_F(SendStatisticsProxyTest,
1140 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
1141 SendStatisticsProxy::AdaptationSteps cpu_counts;
1142 SendStatisticsProxy::AdaptationSteps quality_counts;
1143
1144 quality_counts.num_framerate_reductions = 1;
1145
1146 statistics_proxy_->OnAdaptationChanged(
1147 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1148 quality_counts);
1149
1150 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1151 statistics_proxy_->GetStats().quality_limitation_reason);
1152}
1153
1154TEST_F(SendStatisticsProxyTest,
1155 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
1156 SendStatisticsProxy::AdaptationSteps cpu_counts;
1157 SendStatisticsProxy::AdaptationSteps quality_counts;
1158
1159 cpu_counts.num_resolution_reductions = 1;
1160 quality_counts.num_resolution_reductions = 1;
1161
1162 // Even if the last adaptation reason is kCpu, if the counters indicate being
1163 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
1164 statistics_proxy_->OnAdaptationChanged(
1165 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1166 quality_counts);
1167
1168 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1169 statistics_proxy_->GetStats().quality_limitation_reason);
1170}
1171
1172TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
1173 SendStatisticsProxy::AdaptationSteps cpu_counts;
1174 SendStatisticsProxy::AdaptationSteps quality_counts;
1175
1176 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1177 // due to "none" being the default value.
1178 cpu_counts.num_resolution_reductions = 1;
1179 statistics_proxy_->OnAdaptationChanged(
1180 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1181 quality_counts);
1182 // Go back to not being limited.
1183 cpu_counts.num_resolution_reductions = 0;
1184 statistics_proxy_->OnAdaptationChanged(
1185 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1186 quality_counts);
1187
1188 EXPECT_EQ(QualityLimitationReason::kNone,
1189 statistics_proxy_->GetStats().quality_limitation_reason);
1190}
1191
1192TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
1193 SendStatisticsProxy::AdaptationSteps cpu_counts;
1194 SendStatisticsProxy::AdaptationSteps quality_counts;
1195
1196 // Not limited for 3000 ms
1197 fake_clock_.AdvanceTimeMilliseconds(3000);
1198 // CPU limited for 2000 ms
1199 cpu_counts.num_resolution_reductions = 1;
1200 statistics_proxy_->OnAdaptationChanged(
1201 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1202 quality_counts);
1203 fake_clock_.AdvanceTimeMilliseconds(2000);
1204 // Bandwidth limited for 1000 ms
1205 cpu_counts.num_resolution_reductions = 0;
1206 quality_counts.num_resolution_reductions = 1;
1207 statistics_proxy_->OnAdaptationChanged(
1208 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1209 quality_counts);
1210 fake_clock_.AdvanceTimeMilliseconds(1000);
1211 // CPU limited for another 2000 ms
1212 cpu_counts.num_resolution_reductions = 1;
1213 quality_counts.num_resolution_reductions = 0;
1214 statistics_proxy_->OnAdaptationChanged(
1215 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1216 quality_counts);
1217 fake_clock_.AdvanceTimeMilliseconds(2000);
1218
1219 auto quality_limitation_durations_ms =
1220 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1221
1222 EXPECT_EQ(3000,
1223 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1224 EXPECT_EQ(4000,
1225 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1226 EXPECT_EQ(
1227 1000,
1228 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1229 EXPECT_EQ(0,
1230 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1231}
1232
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001233TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1234 EXPECT_EQ(
1235 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1236}
1237
1238TEST_F(SendStatisticsProxyTest,
1239 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1240 VideoCodec codec;
1241 VideoBitrateAllocation allocation;
1242 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1243 EXPECT_EQ(
1244 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1245}
1246
1247TEST_F(SendStatisticsProxyTest,
1248 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1249 VideoCodec codec;
1250 codec.simulcastStream[0].active = true;
1251 codec.simulcastStream[1].active = true;
1252 codec.simulcastStream[2].active = true;
1253 VideoBitrateAllocation allocation;
1254 allocation.SetBitrate(0, 0, 100);
1255 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1256 EXPECT_EQ(
1257 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1258}
1259
1260TEST_F(SendStatisticsProxyTest,
1261 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1262 VideoCodec codec;
1263 codec.simulcastStream[0].active = true;
1264 codec.simulcastStream[1].active = true;
1265 codec.simulcastStream[2].active = true;
1266 VideoBitrateAllocation allocation;
1267 allocation.SetBitrate(0, 0, 100);
1268 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1269 allocation.SetBitrate(1, 0, 100);
1270 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1271 EXPECT_EQ(
1272 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1273}
1274
1275TEST_F(SendStatisticsProxyTest,
1276 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1277 VideoCodec codec;
1278 codec.simulcastStream[0].active = true;
1279 VideoBitrateAllocation allocation;
1280 allocation.SetBitrate(0, 0, 100);
1281 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1282 // Layer 0 got more bandwidth, but still only one layer on
1283 allocation.SetBitrate(0, 0, 200);
1284 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1285 EXPECT_EQ(
1286 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1287}
1288
1289TEST_F(SendStatisticsProxyTest,
1290 QualityLimitationResolutionChangesWithTogglingLayers) {
1291 VideoCodec codec;
1292 codec.simulcastStream[0].active = true;
1293 codec.simulcastStream[1].active = true;
1294 codec.simulcastStream[2].active = true;
1295 VideoBitrateAllocation allocation;
1296 allocation.SetBitrate(0, 0, 100);
1297 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1298 EXPECT_EQ(
1299 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1300 allocation.SetBitrate(1, 0, 300);
1301 allocation.SetBitrate(2, 0, 500);
1302 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1303 EXPECT_EQ(
1304 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1305 // Layer 2 off
1306 allocation.SetBitrate(2, 0, 0);
1307 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1308 EXPECT_EQ(
1309 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1310 // Layer 2 back on
1311 allocation.SetBitrate(2, 0, 500);
1312 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1313 EXPECT_EQ(
1314 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1315 allocation.SetBitrate(0, 0, 0);
1316 allocation.SetBitrate(1, 0, 0);
1317 allocation.SetBitrate(2, 0, 0);
1318 // All layers off
1319 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1320 EXPECT_EQ(
1321 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1322}
1323
1324TEST_F(SendStatisticsProxyTest,
1325 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1326 VideoCodec codec;
1327 // 3 layers
1328 codec.simulcastStream[0].active = true;
1329 codec.simulcastStream[1].active = true;
1330 codec.simulcastStream[2].active = true;
1331 VideoBitrateAllocation allocation;
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 // Down to one layer now, triggered by a config change
1340 codec.numberOfSimulcastStreams = 1;
1341 codec.simulcastStream[1].active = false;
1342 codec.simulcastStream[2].active = false;
1343 allocation.SetBitrate(0, 0, 100);
1344 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1345 EXPECT_EQ(
1346 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1347
1348 // Up to 3 layers again.
1349 codec.numberOfSimulcastStreams = 3;
1350 codec.simulcastStream[1].active = true;
1351 codec.simulcastStream[2].active = true;
1352 allocation.SetBitrate(0, 0, 500);
1353 allocation.SetBitrate(1, 0, 500);
1354 allocation.SetBitrate(2, 0, 500);
1355 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1356 EXPECT_EQ(
1357 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1358}
1359
1360TEST_F(SendStatisticsProxyTest,
1361 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1362 VideoCodec codec;
1363 codec.simulcastStream[0].active = true;
1364 codec.spatialLayers[0].active = true;
1365 codec.spatialLayers[1].active = true;
1366 codec.spatialLayers[2].active = true;
1367 VideoBitrateAllocation allocation;
1368 allocation.SetBitrate(0, 0, 500);
1369 allocation.SetBitrate(1, 0, 500);
1370 allocation.SetBitrate(2, 0, 500);
1371 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1372 EXPECT_EQ(
1373 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1374
1375 // Down to one layer now, triggered by a config change
1376 codec.spatialLayers[1].active = false;
1377 codec.spatialLayers[2].active = false;
1378 allocation.SetBitrate(0, 0, 100);
1379 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1380 EXPECT_EQ(
1381 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1382
1383 // Up to 3 layers again.
1384 codec.spatialLayers[1].active = true;
1385 codec.spatialLayers[2].active = true;
1386 allocation.SetBitrate(0, 0, 500);
1387 allocation.SetBitrate(1, 0, 500);
1388 allocation.SetBitrate(2, 0, 500);
1389 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1390 EXPECT_EQ(
1391 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1392}
1393
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001394TEST_F(SendStatisticsProxyTest,
1395 QualityLimitationReasonsAreCorrectForContentType) {
1396 // Realtime case.
1397 // Configure two streams.
1398 VideoEncoderConfig config;
1399 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1400 config.number_of_streams = 2;
1401 VideoStream stream1;
1402 stream1.width = kWidth / 2;
1403 stream1.height = kHeight / 2;
1404 VideoStream stream2;
1405 stream2.width = kWidth;
1406 stream2.height = kHeight;
1407 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1408 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1409 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1410 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1411 QualityLimitationReason::kNone);
1412 // Bw disabled one layer.
1413 VideoCodec codec;
1414 codec.numberOfSimulcastStreams = 2;
1415 codec.simulcastStream[0].active = true;
1416 codec.simulcastStream[1].active = true;
1417 VideoBitrateAllocation allocation;
1418 // Some positive bitrate only on the first stream.
1419 allocation.SetBitrate(0, 0, 10000);
1420 allocation.SetBitrate(1, 0, 0);
1421 allocation.set_bw_limited(true);
1422 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1423 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1424 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1425 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1426 QualityLimitationReason::kBandwidth);
1427 // Bw enabled all layers.
1428 allocation.SetBitrate(1, 0, 10000);
1429 allocation.set_bw_limited(false);
1430 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1431 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1432 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1433 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1434 QualityLimitationReason::kNone);
1435
1436 // Screencast case
1437 // Configure two streams.
1438 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1439 config.number_of_streams = 2;
1440 stream1.width = kWidth;
1441 stream1.height = kHeight;
1442 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1443 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1444 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1445 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1446 QualityLimitationReason::kNone);
1447 // Bw disabled one layer.
1448 // Some positive bitrate only on the second stream.
1449 allocation.SetBitrate(0, 0, 10000);
1450 allocation.SetBitrate(1, 0, 0);
1451 allocation.set_bw_limited(true);
1452 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1453 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1454 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1455 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1456 QualityLimitationReason::kBandwidth);
1457 // Bw enabled all layers.
1458 allocation.SetBitrate(1, 0, 10000);
1459 allocation.set_bw_limited(false);
1460 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1461 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1462 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1463 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1464 QualityLimitationReason::kNone);
1465}
1466
asapersson59bac1a2016-01-07 23:36:00 -08001467TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001468 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001469 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1470
Pera48ddb72016-09-29 11:48:50 +02001471 // No switch, stats should not be updated.
1472 VideoEncoderConfig config;
1473 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001474 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001475 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001476
1477 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001478 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001479 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001480 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001481}
1482
asapersson320e45a2016-11-29 01:40:35 -08001483TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1484 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1485 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001486
asapersson320e45a2016-11-29 01:40:35 -08001487 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001488 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1489 EXPECT_METRIC_EQ(
1490 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1491 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1492 EXPECT_METRIC_EQ(
1493 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001494}
1495
1496TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001497 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001498 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001499 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1500 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1501 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001502 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001503
1504 // Not enough samples, stats should not be updated.
1505 for (int i = 0; i < kMinSamples - 1; ++i) {
1506 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001507 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001508 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1509 }
Åsa Persson0122e842017-10-16 12:19:23 +02001510 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001511 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1512 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001513
1514 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001515 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001516 for (int i = 0; i < kMinSamples; ++i) {
1517 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001518 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001519 encoded_image._encodedWidth = kWidth;
1520 encoded_image._encodedHeight = kHeight;
1521 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1522 encoded_image._encodedWidth = kWidth / 2;
1523 encoded_image._encodedHeight = kHeight / 2;
1524 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1525 }
1526
asapersson320e45a2016-11-29 01:40:35 -08001527 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001528 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1529 EXPECT_METRIC_EQ(
1530 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1531 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1532 EXPECT_METRIC_EQ(
1533 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001534}
1535
1536TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1537 const int kFps = 20;
1538 const int kMinPeriodicSamples = 6;
1539 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1540 for (int i = 0; i <= frames; ++i) {
1541 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1542 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1543 }
1544 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001545 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1546 EXPECT_METRIC_EQ(
1547 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001548}
1549
1550TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1551 EncodedImage encoded_image;
1552 const int kFps = 20;
1553 const int kMinPeriodicSamples = 6;
1554 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001555 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001556 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001557 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001558 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1559 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001560 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1561 }
1562 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001563 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1564 EXPECT_METRIC_EQ(
1565 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001566}
1567
1568TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1569 const int kFps = 20;
1570 const int kSuspendTimeMs = 10000;
1571 const int kMinPeriodicSamples = 6;
1572 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1573 for (int i = 0; i < frames; ++i) {
1574 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1575 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1576 }
1577 // Suspend.
1578 statistics_proxy_->OnSuspendChange(true);
1579 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1580
1581 for (int i = 0; i < frames; ++i) {
1582 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1583 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1584 }
1585 // Suspended time interval should not affect the framerate.
1586 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001587 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1588 EXPECT_METRIC_EQ(
1589 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001590}
1591
1592TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1593 EncodedImage encoded_image;
1594 const int kFps = 20;
1595 const int kSuspendTimeMs = 10000;
1596 const int kMinPeriodicSamples = 6;
1597 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001598 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001599 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001600 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001601 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1602 }
1603 // Suspend.
1604 statistics_proxy_->OnSuspendChange(true);
1605 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1606
Åsa Persson0122e842017-10-16 12:19:23 +02001607 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001608 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001609 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001610 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1611 }
1612 // Suspended time interval should not affect the framerate.
1613 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001614 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1615 EXPECT_METRIC_EQ(
1616 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001617}
1618
asaperssonf4e44af2017-04-19 02:01:06 -07001619TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001620 SendStatisticsProxy::AdaptationSteps cpu_counts;
1621 SendStatisticsProxy::AdaptationSteps quality_counts;
1622 cpu_counts.num_resolution_reductions = absl::nullopt;
1623 statistics_proxy_->OnAdaptationChanged(
1624 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1625 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001626
1627 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1628 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1629
1630 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001631 EXPECT_METRIC_EQ(
1632 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001633}
1634
1635TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001636 SendStatisticsProxy::AdaptationSteps cpu_counts;
1637 SendStatisticsProxy::AdaptationSteps quality_counts;
1638 cpu_counts.num_resolution_reductions = 0;
1639 statistics_proxy_->OnAdaptationChanged(
1640 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1641 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001642
perkj803d97f2016-11-01 11:45:46 -07001643 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1644 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1645
Niels Möller213618e2018-07-24 09:29:58 +02001646 cpu_counts.num_resolution_reductions = 1;
1647 statistics_proxy_->OnAdaptationChanged(
1648 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1649 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001650
1651 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1652 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1653
1654 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001655 EXPECT_METRIC_EQ(
1656 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1657 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001658 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1659}
1660
asapersson4374a092016-07-27 00:39:09 -07001661TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1662 const int64_t kTimeSec = 3;
1663 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1664 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001665 EXPECT_METRIC_EQ(
1666 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1667 EXPECT_METRIC_EQ(
1668 1,
1669 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001670}
1671
1672TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1673 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1674 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001675 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001676}
1677
asapersson66d4b372016-12-19 06:50:53 -08001678TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1679 // First RTP packet sent.
1680 UpdateDataCounters(kFirstSsrc);
1681
1682 // Min runtime has passed.
1683 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1684 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001685 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1686 EXPECT_METRIC_EQ(1,
1687 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001688}
1689
1690TEST_F(SendStatisticsProxyTest,
1691 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1692 // First RTP packet sent.
1693 UpdateDataCounters(kFirstSsrc);
1694
1695 // Min runtime has not passed.
1696 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1697 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001698 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1699 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001700}
1701
1702TEST_F(SendStatisticsProxyTest,
1703 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1704 // First RTP packet not sent.
1705 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1706 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001707 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001708}
1709
1710TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1711 // First RTP packet sent and min runtime passed.
1712 UpdateDataCounters(kFirstSsrc);
1713
1714 // No change. Video: 10000 ms, paused: 0 ms (0%).
1715 statistics_proxy_->OnSetEncoderTargetRate(50000);
1716 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1717 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1718
1719 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001720 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1721 EXPECT_METRIC_EQ(1,
1722 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1723 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1724 EXPECT_METRIC_EQ(1,
1725 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001726}
1727
1728TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1729 // First RTP packet sent and min runtime passed.
1730 UpdateDataCounters(kFirstSsrc);
1731
1732 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1733 statistics_proxy_->OnSetEncoderTargetRate(50000);
1734 fake_clock_.AdvanceTimeMilliseconds(7000);
1735 statistics_proxy_->OnSetEncoderTargetRate(0);
1736 fake_clock_.AdvanceTimeMilliseconds(3000);
1737 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1738
1739 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001740 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1741 EXPECT_METRIC_EQ(1,
1742 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1743 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1744 EXPECT_METRIC_EQ(1,
1745 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001746}
1747
1748TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1749 // First RTP packet sent.
1750 UpdateDataCounters(kFirstSsrc);
1751
1752 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1753 statistics_proxy_->OnSetEncoderTargetRate(0);
1754 fake_clock_.AdvanceTimeMilliseconds(1000);
1755 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1756 fake_clock_.AdvanceTimeMilliseconds(7000);
1757 statistics_proxy_->OnSetEncoderTargetRate(60000);
1758 fake_clock_.AdvanceTimeMilliseconds(3000);
1759 statistics_proxy_->OnSetEncoderTargetRate(0);
1760 fake_clock_.AdvanceTimeMilliseconds(250);
1761 statistics_proxy_->OnSetEncoderTargetRate(0);
1762 fake_clock_.AdvanceTimeMilliseconds(750);
1763 statistics_proxy_->OnSetEncoderTargetRate(60000);
1764 fake_clock_.AdvanceTimeMilliseconds(5000);
1765 statistics_proxy_->OnSetEncoderTargetRate(50000);
1766 fake_clock_.AdvanceTimeMilliseconds(4000);
1767 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1768
1769 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001770 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1771 EXPECT_METRIC_EQ(1,
1772 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1773 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1774 EXPECT_METRIC_EQ(1,
1775 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001776}
1777
1778TEST_F(SendStatisticsProxyTest,
1779 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1780 // First RTP packet sent.
1781 UpdateDataCounters(kFirstSsrc);
1782 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1783
1784 // Min runtime has not passed.
1785 statistics_proxy_->OnSetEncoderTargetRate(50000);
1786 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1787 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1788
1789 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001790 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001791}
1792
asapersson118ef002016-03-31 00:00:19 -07001793TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001794 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001795 CodecSpecificInfo codec_info;
1796 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001797
perkj803d97f2016-11-01 11:45:46 -07001798 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001799 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001800 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001801 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001802 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001803 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001804 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001805 }
1806 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001807 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1808 EXPECT_METRIC_EQ(
1809 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1810 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1811 EXPECT_METRIC_EQ(
1812 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001813}
1814
1815TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1816 VideoSendStream::Config config(nullptr);
1817 config.rtp.ssrcs.push_back(kFirstSsrc);
1818 statistics_proxy_.reset(new SendStatisticsProxy(
1819 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1820
asapersson118ef002016-03-31 00:00:19 -07001821 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001822 CodecSpecificInfo codec_info;
1823 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001824
perkj803d97f2016-11-01 11:45:46 -07001825 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001826 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001827 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001828 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001829 }
1830 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001831 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1832 EXPECT_METRIC_EQ(1,
1833 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001834}
1835
asapersson5265fed2016-04-18 02:58:47 -07001836TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001837 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001838 CodecSpecificInfo codec_info;
1839 codec_info.codecType = kVideoCodecVP9;
1840 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001841
perkj803d97f2016-11-01 11:45:46 -07001842 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001843 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001844 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001845 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001846 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001847 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001848 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001849 }
1850 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001851 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1852 EXPECT_METRIC_EQ(
1853 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1854 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1855 EXPECT_METRIC_EQ(
1856 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001857}
1858
1859TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1860 VideoSendStream::Config config(nullptr);
1861 config.rtp.ssrcs.push_back(kFirstSsrc);
1862 statistics_proxy_.reset(new SendStatisticsProxy(
1863 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1864
asapersson5265fed2016-04-18 02:58:47 -07001865 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001866 CodecSpecificInfo codec_info;
1867 codec_info.codecType = kVideoCodecVP9;
1868 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001869
perkj803d97f2016-11-01 11:45:46 -07001870 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001871 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001872 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001873 }
1874 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001875 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1876 EXPECT_METRIC_EQ(1,
1877 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001878}
1879
asapersson827cab32016-11-02 09:08:47 -07001880TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1881 EncodedImage encoded_image;
1882 CodecSpecificInfo codec_info;
1883 codec_info.codecType = kVideoCodecH264;
1884
1885 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001886 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001887 encoded_image.qp_ = kQpIdx0;
1888 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001889 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001890 encoded_image.qp_ = kQpIdx1;
1891 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001892 }
1893 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001894 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1895 EXPECT_METRIC_EQ(
1896 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1897 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1898 EXPECT_METRIC_EQ(
1899 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001900}
1901
asapersson4ee70462016-10-31 04:05:12 -07001902TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001903 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1904 // Configure one stream.
1905 VideoEncoderConfig config;
1906 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1907 VideoStream stream1;
1908 stream1.width = kWidth;
1909 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001910 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001911
1912 const int64_t kMaxEncodedFrameWindowMs = 800;
1913 const int kFps = 20;
1914 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1915 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1916 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1917
1918 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001919 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001920 encoded_image._encodedWidth = kWidth;
1921 encoded_image._encodedHeight = kHeight;
1922 for (int i = 0; i < kMinSamples; ++i) {
1923 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001924 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1925 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001926 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001927 }
asapersson4ee70462016-10-31 04:05:12 -07001928
1929 // Histograms are updated when the statistics_proxy_ is deleted.
1930 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001931 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1932 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1933 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1934 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001935}
1936
1937TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001938 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1939 // Configure two streams.
1940 VideoEncoderConfig config;
1941 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1942 VideoStream stream1;
1943 stream1.width = kWidth / 2;
1944 stream1.height = kHeight / 2;
1945 VideoStream stream2;
1946 stream2.width = kWidth;
1947 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001948 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001949
1950 const int64_t kMaxEncodedFrameWindowMs = 800;
1951 const int kFps = 20;
1952 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1953 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1954 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1955
1956 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001957 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001958 for (int i = 0; i < kMinSamples; ++i) {
1959 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001960 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1961 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001962 encoded_image._encodedWidth = kWidth;
1963 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001964 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001965 encoded_image._encodedWidth = kWidth / 2;
1966 encoded_image._encodedHeight = kHeight / 2;
1967 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1968 }
asapersson4ee70462016-10-31 04:05:12 -07001969
1970 // Histograms are updated when the statistics_proxy_ is deleted.
1971 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001972 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1973 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1974 EXPECT_METRIC_EQ(
1975 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
1976 0));
asapersson4ee70462016-10-31 04:05:12 -07001977 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01001978 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1979 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001980}
1981
1982TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001983 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1984 // Configure two streams.
1985 VideoEncoderConfig config;
1986 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1987 VideoStream stream1;
1988 stream1.width = kWidth / 2;
1989 stream1.height = kHeight / 2;
1990 VideoStream stream2;
1991 stream2.width = kWidth;
1992 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001993 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001994
1995 const int64_t kMaxEncodedFrameWindowMs = 800;
1996 const int kFps = 20;
1997 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1998 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1999 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2000
2001 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002002 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002003 encoded_image._encodedWidth = kWidth / 2;
2004 encoded_image._encodedHeight = kHeight / 2;
2005 for (int i = 0; i < kMinSamples; ++i) {
2006 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002007 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2008 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002009 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002010 }
asapersson4ee70462016-10-31 04:05:12 -07002011
2012 // Histograms are updated when the statistics_proxy_ is deleted.
2013 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002014 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2015 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2016 EXPECT_METRIC_EQ(
2017 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2018 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002019 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002020 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2021 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2022 EXPECT_METRIC_EQ(
2023 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2024 1));
asapersson4ee70462016-10-31 04:05:12 -07002025}
2026
2027TEST_F(SendStatisticsProxyTest,
2028 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02002029 SendStatisticsProxy::AdaptationSteps cpu_counts;
2030 SendStatisticsProxy::AdaptationSteps quality_counts;
2031 quality_counts.num_resolution_reductions = absl::nullopt;
2032 statistics_proxy_->OnAdaptationChanged(
2033 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2034 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002035 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002036 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002037 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002038 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002039
2040 // Histograms are updated when the statistics_proxy_ is deleted.
2041 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002042 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002043 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002044 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2045 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002046}
2047
2048TEST_F(SendStatisticsProxyTest,
2049 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02002050 SendStatisticsProxy::AdaptationSteps cpu_counts;
2051 SendStatisticsProxy::AdaptationSteps quality_counts;
2052 quality_counts.num_resolution_reductions = 0;
2053 statistics_proxy_->OnAdaptationChanged(
2054 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2055 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002056 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002057 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002058 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002059 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002060
2061 // Histograms are updated when the statistics_proxy_ is deleted.
2062 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002063 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002064 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002065 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2066 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002067 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002068 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2069 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002070}
2071
2072TEST_F(SendStatisticsProxyTest,
2073 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2074 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02002075 SendStatisticsProxy::AdaptationSteps cpu_counts;
2076 SendStatisticsProxy::AdaptationSteps quality_counts;
2077 quality_counts.num_resolution_reductions = kDownscales;
2078 statistics_proxy_->OnAdaptationChanged(
2079 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2080 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002081 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002082 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002083 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002084 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002085 // Histograms are updated when the statistics_proxy_ is deleted.
2086 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002087 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002088 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002089 EXPECT_METRIC_EQ(
2090 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2091 100));
asapersson4ee70462016-10-31 04:05:12 -07002092 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002093 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2094 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2095 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002096 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2097 kDownscales));
2098}
2099
2100TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2101 // Initially false.
2102 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002103
Åsa Perssonaa329e72017-12-15 15:54:44 +01002104 // Configure two streams.
2105 VideoEncoderConfig config;
2106 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002107 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002108 VideoStream stream1;
2109 stream1.width = kWidth / 2;
2110 stream1.height = kHeight / 2;
2111 VideoStream stream2;
2112 stream2.width = kWidth;
2113 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002114 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002115
Åsa Perssonaa329e72017-12-15 15:54:44 +01002116 // One stream encoded.
2117 EncodedImage encoded_image;
2118 encoded_image._encodedWidth = kWidth / 2;
2119 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002120
2121 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02002122 SendStatisticsProxy::AdaptationSteps cpu_counts;
2123 SendStatisticsProxy::AdaptationSteps quality_counts;
2124 quality_counts.num_resolution_reductions = 1;
2125 statistics_proxy_->OnAdaptationChanged(
2126 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2127 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002128 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2129 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002130
2131 // Adapt up.
2132 quality_counts.num_resolution_reductions = 0;
2133 statistics_proxy_->OnAdaptationChanged(
2134 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2135 quality_counts);
2136 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2137 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2138
2139 // Bw disabled one layer.
2140 VideoCodec codec;
2141 codec.numberOfSimulcastStreams = 2;
2142 codec.simulcastStream[0].active = true;
2143 codec.simulcastStream[1].active = true;
2144 VideoBitrateAllocation allocation;
2145 // Some positive bitrate only on the second stream.
2146 allocation.SetBitrate(1, 0, 10000);
2147 allocation.set_bw_limited(true);
2148 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2149 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002150
2151 // Revert for the next test.
2152 allocation.set_bw_limited(false);
2153 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2154 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2155
2156 // Internal encoder scaler reduced resolution.
2157 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2158 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002159}
2160
asapersson66d4b372016-12-19 06:50:53 -08002161TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2162 // Initially zero.
2163 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2164
2165 const int kBitrate = 100000;
2166 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2167 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2168
2169 statistics_proxy_->OnSetEncoderTargetRate(0);
2170 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2171}
2172
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002173TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002174 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002175 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2176 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002177 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002178 // From RtcpStatisticsCallback.
2179 RtcpStatistics rtcp_stats;
2180 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002181 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002182
2183 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002184 uint32_t total = 0;
2185 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002186 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002187 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002188
2189 // From FrameCountObserver.
2190 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002191 FrameCounts frame_counts;
2192 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002193 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002194
2195 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2196 EXPECT_TRUE(stats.substreams.empty());
2197}
2198
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002199TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2200 static const int kEncodedWidth = 123;
2201 static const int kEncodedHeight = 81;
2202 EncodedImage encoded_image;
2203 encoded_image._encodedWidth = kEncodedWidth;
2204 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002205 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002206
kjellander02b3d272016-04-20 05:05:54 -07002207 CodecSpecificInfo codec_info;
2208 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002209
kjellander02b3d272016-04-20 05:05:54 -07002210 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002211 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002212 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002213
2214 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002215 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2216 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2217 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2218 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002219
2220 // Forward almost to timeout, this should not have removed stats.
2221 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2222 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002223 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2224 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002225
2226 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2227 // resolution still times out (no global timeout for all stats).
2228 RtcpStatistics rtcp_statistics;
2229 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2230 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2231
2232 // Report stats for second SSRC to make sure it's not outdated along with the
2233 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002234 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002235
2236 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2237 // reported, but substream 1 should.
2238 fake_clock_.AdvanceTimeMilliseconds(1);
2239 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002240 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2241 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2242 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2243 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002244}
2245
Peter Boström20f3f942015-05-15 11:33:39 +02002246TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2247 static const int kEncodedWidth = 123;
2248 static const int kEncodedHeight = 81;
2249 EncodedImage encoded_image;
2250 encoded_image._encodedWidth = kEncodedWidth;
2251 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002252 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002253
kjellander02b3d272016-04-20 05:05:54 -07002254 CodecSpecificInfo codec_info;
2255 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002256
kjellander02b3d272016-04-20 05:05:54 -07002257 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002258 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002259 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002260
2261 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2262 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2263 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2264 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2265 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2266 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2267}
2268
2269TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002270 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002271 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2272 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2273 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2274
2275 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2276
2277 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002278 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002279 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002280 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002281 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2282 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2283 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2284}
2285
sprang07fb9be2016-02-24 07:55:00 -08002286TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2287 RtcpPacketTypeCounterObserver* proxy =
2288 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2289 RtcpPacketTypeCounter counters;
2290 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2291 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2292 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2293
2294 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2295
2296 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2297 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2298 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2299 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2300 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2301
2302 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2303 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2304
2305 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002306 VideoEncoderConfig config;
2307 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002308 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002309
Ying Wangef3998f2019-12-09 13:06:53 +01002310 EXPECT_METRIC_EQ(
2311 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2312 EXPECT_METRIC_EQ(
2313 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2314 EXPECT_METRIC_EQ(
2315 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2316 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2317 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002318
2319 const int kRate = 60 * 2; // Packets per minute with two streams.
2320
Ying Wangef3998f2019-12-09 13:06:53 +01002321 EXPECT_METRIC_EQ(
2322 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2323 1 * kRate));
2324 EXPECT_METRIC_EQ(
2325 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2326 2 * kRate));
2327 EXPECT_METRIC_EQ(
2328 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2329 3 * kRate));
2330 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002331 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2332 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002333
2334 // New start time but same counter values.
2335 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2336 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2337
2338 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2339
2340 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2341 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2342 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2343 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2344 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2345
2346 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2347 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2348
2349 SetUp(); // Reset stats proxy also causes histograms to be reported.
2350
Ying Wangef3998f2019-12-09 13:06:53 +01002351 EXPECT_METRIC_EQ(
2352 1, metrics::NumSamples(
2353 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2354 EXPECT_METRIC_EQ(1,
2355 metrics::NumSamples(
2356 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2357 EXPECT_METRIC_EQ(1,
2358 metrics::NumSamples(
2359 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2360 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002361 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002362 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2363
Ying Wangef3998f2019-12-09 13:06:53 +01002364 EXPECT_METRIC_EQ(
2365 1,
2366 metrics::NumEvents(
2367 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2368 EXPECT_METRIC_EQ(
2369 1,
2370 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2371 2 * kRate));
2372 EXPECT_METRIC_EQ(
2373 1,
2374 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2375 3 * kRate));
2376 EXPECT_METRIC_EQ(
2377 1, metrics::NumEvents(
2378 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2379 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002380}
2381
asaperssona6a699a2016-11-25 03:52:46 -08002382TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2383 statistics_proxy_.reset(
2384 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2385 VideoEncoderConfig::ContentType::kRealtimeVideo));
2386
2387 StreamDataCountersCallback* proxy =
2388 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2389 StreamDataCounters counters;
2390 proxy->DataCountersUpdated(counters, kFirstSsrc);
2391 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2392
2393 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
2394 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
2395}
2396
2397TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2398 statistics_proxy_.reset(
2399 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2400 VideoEncoderConfig::ContentType::kRealtimeVideo));
2401
2402 StreamDataCountersCallback* proxy =
2403 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002404 StreamDataCounters counters;
2405 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002406
asapersson93e1e232017-02-06 05:18:35 -08002407 const int kMinRequiredPeriodSamples = 8;
2408 const int kPeriodIntervalMs = 2000;
2409 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2410 counters.transmitted.packets += 20;
2411 counters.transmitted.header_bytes += 500;
2412 counters.transmitted.padding_bytes += 1000;
2413 counters.transmitted.payload_bytes += 2000;
2414 counters.retransmitted.packets += 2;
2415 counters.retransmitted.header_bytes += 25;
2416 counters.retransmitted.padding_bytes += 100;
2417 counters.retransmitted.payload_bytes += 250;
2418 counters.fec = counters.retransmitted;
2419 rtx_counters.transmitted = counters.transmitted;
2420 // Advance one interval and update counters.
2421 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2422 proxy->DataCountersUpdated(counters, kFirstSsrc);
2423 proxy->DataCountersUpdated(counters, kSecondSsrc);
2424 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2425 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2426 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2427 }
asaperssona6a699a2016-11-25 03:52:46 -08002428
asaperssona6a699a2016-11-25 03:52:46 -08002429 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002430 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002431 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2432 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002433 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002434 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2435 EXPECT_METRIC_EQ(1,
2436 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002437 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002438 EXPECT_METRIC_EQ(1,
2439 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2440 EXPECT_METRIC_EQ(
2441 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002442 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002443 EXPECT_METRIC_EQ(
2444 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2445 EXPECT_METRIC_EQ(
2446 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002447 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002448 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2449 EXPECT_METRIC_EQ(1,
2450 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002451 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002452 EXPECT_METRIC_EQ(
2453 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2454 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002455 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002456}
2457
Erik Språng22c2b482016-03-01 09:40:42 +01002458TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2459 StreamDataCountersCallback* proxy =
2460 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2461 StreamDataCounters counters;
2462 StreamDataCounters rtx_counters;
2463 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002464
asapersson93e1e232017-02-06 05:18:35 -08002465 const int kMinRequiredPeriodSamples = 8;
2466 const int kPeriodIntervalMs = 2000;
2467 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2468 counters.transmitted.packets += 20;
2469 counters.transmitted.header_bytes += 500;
2470 counters.transmitted.padding_bytes += 1000;
2471 counters.transmitted.payload_bytes += 2000;
2472 counters.retransmitted.packets += 2;
2473 counters.retransmitted.header_bytes += 25;
2474 counters.retransmitted.padding_bytes += 100;
2475 counters.retransmitted.payload_bytes += 250;
2476 counters.fec = counters.retransmitted;
2477 rtx_counters.transmitted = counters.transmitted;
2478 // Advance one interval and update counters.
2479 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2480 proxy->DataCountersUpdated(counters, kFirstSsrc);
2481 proxy->DataCountersUpdated(counters, kSecondSsrc);
2482 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2483 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2484 }
Erik Språng22c2b482016-03-01 09:40:42 +01002485
2486 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002487 VideoEncoderConfig config;
2488 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002489 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002490
asapersson93e1e232017-02-06 05:18:35 -08002491 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002492 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2493 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002494 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002495 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2496 EXPECT_METRIC_EQ(1,
2497 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002498 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002499 EXPECT_METRIC_EQ(1,
2500 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2501 EXPECT_METRIC_EQ(
2502 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002503 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002504 EXPECT_METRIC_EQ(
2505 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2506 EXPECT_METRIC_EQ(
2507 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002508 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002509 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2510 EXPECT_METRIC_EQ(1,
2511 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002512 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002513 EXPECT_METRIC_EQ(
2514 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2515 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002516 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002517
asapersson93e1e232017-02-06 05:18:35 -08002518 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002519 // Double counter values, this should result in the same counts as before but
2520 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002521 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2522 counters.transmitted.packets += 20;
2523 counters.transmitted.header_bytes += 500;
2524 counters.transmitted.padding_bytes += 1000;
2525 counters.transmitted.payload_bytes += 2000;
2526 counters.retransmitted.packets += 2;
2527 counters.retransmitted.header_bytes += 25;
2528 counters.retransmitted.padding_bytes += 100;
2529 counters.retransmitted.payload_bytes += 250;
2530 counters.fec = counters.retransmitted;
2531 rtx_counters.transmitted = counters.transmitted;
2532 // Advance one interval and update counters.
2533 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2534 proxy->DataCountersUpdated(counters, kFirstSsrc);
2535 proxy->DataCountersUpdated(counters, kSecondSsrc);
2536 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2537 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2538 }
Erik Språng22c2b482016-03-01 09:40:42 +01002539
asapersson93e1e232017-02-06 05:18:35 -08002540 // Reset stats proxy also causes histograms to be reported.
2541 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002542
asapersson93e1e232017-02-06 05:18:35 -08002543 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002544 EXPECT_METRIC_EQ(
2545 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2546 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002547 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2548 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002549 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002550 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002551 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2552 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002553 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002554 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2555 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2556 EXPECT_METRIC_EQ(
2557 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2558 12));
asapersson93e1e232017-02-06 05:18:35 -08002559 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002560 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2561 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2562 EXPECT_METRIC_EQ(
2563 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2564 16));
asapersson93e1e232017-02-06 05:18:35 -08002565 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002566 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002567 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002568 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2569 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002570 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002571 EXPECT_METRIC_EQ(
2572 1, metrics::NumSamples(
2573 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2574 EXPECT_METRIC_EQ(
2575 1, metrics::NumEvents(
2576 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002577}
Erik Språng22c2b482016-03-01 09:40:42 +01002578
asapersson93e1e232017-02-06 05:18:35 -08002579TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2580 StreamDataCountersCallback* proxy =
2581 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2582 StreamDataCounters counters;
2583 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002584
asapersson93e1e232017-02-06 05:18:35 -08002585 const int kMinRequiredPeriodSamples = 8;
2586 const int kPeriodIntervalMs = 2000;
2587 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2588 counters.transmitted.packets += 20;
2589 counters.transmitted.header_bytes += 500;
2590 counters.transmitted.payload_bytes += 2000;
2591 counters.fec = counters.retransmitted;
2592 // Advance one interval and update counters.
2593 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2594 proxy->DataCountersUpdated(counters, kFirstSsrc);
2595 }
2596
2597 // RTX enabled. No data sent over RTX.
2598 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002599 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2600 EXPECT_METRIC_EQ(1,
2601 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002602}
2603
2604TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2605 VideoSendStream::Config config(nullptr);
2606 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2607 statistics_proxy_.reset(new SendStatisticsProxy(
2608 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2609
2610 StreamDataCountersCallback* proxy =
2611 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2612 StreamDataCounters counters;
2613
2614 const int kMinRequiredPeriodSamples = 8;
2615 const int kPeriodIntervalMs = 2000;
2616 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2617 counters.transmitted.packets += 20;
2618 counters.transmitted.header_bytes += 500;
2619 counters.transmitted.payload_bytes += 2000;
2620 counters.fec = counters.retransmitted;
2621 // Advance one interval and update counters.
2622 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2623 proxy->DataCountersUpdated(counters, kFirstSsrc);
2624 }
2625
2626 // RTX not enabled.
2627 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002628 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002629}
2630
2631TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2632 StreamDataCountersCallback* proxy =
2633 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2634 StreamDataCounters counters;
2635 StreamDataCounters rtx_counters;
2636
2637 const int kMinRequiredPeriodSamples = 8;
2638 const int kPeriodIntervalMs = 2000;
2639 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2640 counters.transmitted.packets += 20;
2641 counters.transmitted.header_bytes += 500;
2642 counters.transmitted.payload_bytes += 2000;
2643 // Advance one interval and update counters.
2644 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2645 proxy->DataCountersUpdated(counters, kFirstSsrc);
2646 }
2647
2648 // FEC enabled. No FEC data sent.
2649 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002650 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2651 EXPECT_METRIC_EQ(1,
2652 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002653}
2654
2655TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2656 VideoSendStream::Config config(nullptr);
2657 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2658 statistics_proxy_.reset(new SendStatisticsProxy(
2659 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2660
2661 StreamDataCountersCallback* proxy =
2662 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2663 StreamDataCounters counters;
2664
2665 const int kMinRequiredPeriodSamples = 8;
2666 const int kPeriodIntervalMs = 2000;
2667 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2668 counters.transmitted.packets += 20;
2669 counters.transmitted.header_bytes += 500;
2670 counters.transmitted.payload_bytes += 2000;
2671 counters.fec = counters.retransmitted;
2672 // Advance one interval and update counters.
2673 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2674 proxy->DataCountersUpdated(counters, kFirstSsrc);
2675 }
2676
2677 // FEC not enabled.
2678 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002679 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002680}
2681
asapersson8d75ac72017-09-15 06:41:15 -07002682TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002683 const std::string kName = "encoderName";
2684 statistics_proxy_->OnEncoderImplementationChanged(kName);
2685 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002686}
2687
Sergey Silkinbb081a62018-09-04 18:34:22 +02002688TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2689 static const int kEncodedWidth = 123;
2690 static const int kEncodedHeight = 81;
2691 EncodedImage encoded_image;
2692 encoded_image._encodedWidth = kEncodedWidth;
2693 encoded_image._encodedHeight = kEncodedHeight;
2694 encoded_image.SetSpatialIndex(0);
2695
2696 CodecSpecificInfo codec_info;
2697 codec_info.codecType = kVideoCodecVP9;
2698
2699 // For first picture, it is expected that low layer updates resolution.
2700 codec_info.codecSpecific.VP9.end_of_picture = false;
2701 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2702 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2703 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2704 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2705
2706 // Top layer updates resolution.
2707 encoded_image._encodedWidth = kEncodedWidth * 2;
2708 encoded_image._encodedHeight = kEncodedHeight * 2;
2709 codec_info.codecSpecific.VP9.end_of_picture = true;
2710 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2711 stats = statistics_proxy_->GetStats();
2712 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2713 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2714
2715 // Low layer of next frame doesn't update resolution.
2716 encoded_image._encodedWidth = kEncodedWidth;
2717 encoded_image._encodedHeight = kEncodedHeight;
2718 codec_info.codecSpecific.VP9.end_of_picture = false;
2719 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2720 stats = statistics_proxy_->GetStats();
2721 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2722 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2723}
2724
asapersson8d75ac72017-09-15 06:41:15 -07002725class ForcedFallbackTest : public SendStatisticsProxyTest {
2726 public:
2727 explicit ForcedFallbackTest(const std::string& field_trials)
2728 : SendStatisticsProxyTest(field_trials) {
2729 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002730 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002731 encoded_image_._encodedWidth = kWidth;
2732 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002733 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002734 }
2735
2736 ~ForcedFallbackTest() override {}
2737
2738 protected:
2739 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002740 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2741
asapersson8d75ac72017-09-15 06:41:15 -07002742 // First frame is not updating stats, insert initial frame.
2743 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2744 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2745 }
2746 for (int i = 0; i < num_frames; ++i) {
2747 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2748 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2749 }
2750 // Add frame to include last time interval.
2751 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2752 }
2753
2754 EncodedImage encoded_image_;
2755 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002756 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002757 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2758 const int kFrameIntervalMs = 1000;
2759 const int kMinFrames = 20; // Min run time 20 sec.
2760};
2761
2762class ForcedFallbackDisabled : public ForcedFallbackTest {
2763 public:
2764 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002765 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2766 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002767};
2768
2769class ForcedFallbackEnabled : public ForcedFallbackTest {
2770 public:
2771 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002772 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2773 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002774};
2775
2776TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2777 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2778 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002779 EXPECT_METRIC_EQ(0,
2780 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2781 EXPECT_METRIC_EQ(
2782 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002783}
2784
2785TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2786 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002787 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002788 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002789 EXPECT_METRIC_EQ(1,
2790 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2791 EXPECT_METRIC_EQ(
2792 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2793 EXPECT_METRIC_EQ(
2794 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2795 EXPECT_METRIC_EQ(
2796 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002797}
2798
2799TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2800 codec_info_.codecType = kVideoCodecVP9;
2801 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2802 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002803 EXPECT_METRIC_EQ(0,
2804 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2805 EXPECT_METRIC_EQ(
2806 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002807}
2808
2809TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2810 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2811 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2812 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002813 EXPECT_METRIC_EQ(0,
2814 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2815 EXPECT_METRIC_EQ(
2816 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002817}
2818
2819TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002820 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002821 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2822 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002823 EXPECT_METRIC_EQ(0,
2824 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2825 EXPECT_METRIC_EQ(
2826 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002827}
2828
2829TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2830 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2831 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002832 EXPECT_METRIC_EQ(0,
2833 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2834 EXPECT_METRIC_EQ(
2835 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002836}
2837
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002838TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2839 InsertEncodedFrames(1, kFrameIntervalMs);
2840 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2841}
2842
2843TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2844 InsertEncodedFrames(1, kFrameIntervalMs);
2845 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2846}
2847
2848TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002849 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002850 InsertEncodedFrames(1, kFrameIntervalMs);
2851 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2852}
2853
2854TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2855 encoded_image_._encodedWidth = kWidth + 1;
2856 InsertEncodedFrames(1, kFrameIntervalMs);
2857 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2858}
2859
2860TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002861 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002862 InsertEncodedFrames(1, kFrameIntervalMs);
2863 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2864}
2865
2866TEST_F(ForcedFallbackDisabled,
2867 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2868 encoded_image_._encodedWidth = kWidth + 1;
2869 statistics_proxy_->OnMinPixelLimitReached();
2870 InsertEncodedFrames(1, kFrameIntervalMs);
2871 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2872}
2873
asapersson8d75ac72017-09-15 06:41:15 -07002874TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2875 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002876 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002877 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002878 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002879 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002880 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002881 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002882
2883 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002884 EXPECT_METRIC_EQ(1,
2885 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2886 EXPECT_METRIC_EQ(
2887 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2888 EXPECT_METRIC_EQ(
2889 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2890 EXPECT_METRIC_EQ(
2891 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002892}
2893
2894TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2895 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2896 const int kMaxFrameDiffMs = 2000;
2897
2898 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2899 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002900 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002901 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002902 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002903 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002904 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002905 InsertEncodedFrames(20, 1000);
2906 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2907 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002908 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002909 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002910 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002911 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002912 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002913 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002914 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002915
2916 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002917 EXPECT_METRIC_EQ(1,
2918 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2919 EXPECT_METRIC_EQ(
2920 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2921 EXPECT_METRIC_EQ(
2922 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2923 EXPECT_METRIC_EQ(
2924 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002925}
2926
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002927TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2928 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002929 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002930 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2931
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002932 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002933 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002934 EXPECT_METRIC_EQ(0,
2935 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2936 EXPECT_METRIC_EQ(
2937 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002938}
2939
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002940TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2941 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002942 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002943 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2944
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002945 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002946 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002947 EXPECT_METRIC_EQ(1,
2948 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2949 EXPECT_METRIC_EQ(
2950 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002951}
2952
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002953} // namespace webrtc