blob: 2532c292155cb02ced9eb092c2fb19f21e705701 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
Steve Antonbd631a02019-03-28 10:51:27 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 10:51:27 -070019#include "absl/algorithm/container.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020020#include "api/units/timestamp.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020021#include "api/video/video_bitrate_allocation.h"
22#include "api/video/video_codec_type.h"
23#include "api/video_codecs/video_codec.h"
24#include "api/video_codecs/video_encoder_config.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020025#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070027#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000029
30namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070031namespace {
32const uint32_t kFirstSsrc = 17;
33const uint32_t kSecondSsrc = 42;
34const uint32_t kFirstRtxSsrc = 18;
35const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080036const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080037const int kFpsPeriodicIntervalMs = 2000;
38const int kWidth = 640;
39const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070040const int kQpIdx0 = 21;
41const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010042const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080043const CodecSpecificInfo kDefaultCodecInfo = []() {
44 CodecSpecificInfo codec_info;
45 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080046 return codec_info;
47}();
asapersson5265fed2016-04-18 02:58:47 -070048} // namespace
sprang07fb9be2016-02-24 07:55:00 -080049
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000050class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000051 public:
asapersson8d75ac72017-09-15 06:41:15 -070052 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
53 explicit SendStatisticsProxyTest(const std::string& field_trials)
54 : override_field_trials_(field_trials),
55 fake_clock_(1234),
56 config_(GetTestConfig()),
57 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070058 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000059 virtual ~SendStatisticsProxyTest() {}
60
61 protected:
62 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070063 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080064 statistics_proxy_.reset(new SendStatisticsProxy(
65 &fake_clock_, GetTestConfig(),
66 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000067 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070068 for (const auto& ssrc : config_.rtp.ssrcs)
69 expected_.substreams[ssrc].is_rtx = false;
70 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
71 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000072 }
73
74 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070075 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080076 config.rtp.ssrcs.push_back(kFirstSsrc);
77 config.rtp.ssrcs.push_back(kSecondSsrc);
78 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
79 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070080 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000081 return config;
82 }
83
asaperssona6a699a2016-11-25 03:52:46 -080084 VideoSendStream::Config GetTestConfigWithFlexFec() {
85 VideoSendStream::Config config(nullptr);
86 config.rtp.ssrcs.push_back(kFirstSsrc);
87 config.rtp.ssrcs.push_back(kSecondSsrc);
88 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
89 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080090 config.rtp.flexfec.payload_type = 50;
91 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080092 return config;
93 }
94
95 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
96 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
97 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
98 stats.substreams.find(ssrc);
99 EXPECT_NE(it, stats.substreams.end());
100 return it->second;
101 }
102
asapersson66d4b372016-12-19 06:50:53 -0800103 void UpdateDataCounters(uint32_t ssrc) {
104 StreamDataCountersCallback* proxy =
105 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
106 StreamDataCounters counters;
107 proxy->DataCountersUpdated(counters, ssrc);
108 }
109
sprang@webrtc.org09315702014-02-07 12:06:29 +0000110 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000111 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
112 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000113 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000114 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000115
116 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000117 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000118 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000119 it != one.substreams.end(); ++it) {
120 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
121 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000122 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000123 const VideoSendStream::StreamStats& a = it->second;
124 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000125
asapersson2e5cfcd2016-08-11 08:41:18 -0700126 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000127 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
128 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000129 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000130 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
131 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000133 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
134 b.rtp_stats.transmitted.payload_bytes);
135 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
136 b.rtp_stats.transmitted.header_bytes);
137 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
138 b.rtp_stats.transmitted.padding_bytes);
139 EXPECT_EQ(a.rtp_stats.transmitted.packets,
140 b.rtp_stats.transmitted.packets);
141 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
142 b.rtp_stats.retransmitted.packets);
143 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000144
145 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700146 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
147 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
148 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
150 }
151 }
152
asapersson8d75ac72017-09-15 06:41:15 -0700153 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000154 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800155 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156 VideoSendStream::Config config_;
157 int avg_delay_ms_;
158 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000159 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000160 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
161 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000162};
163
164TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
165 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700166 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000167 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000168
169 // Add statistics with some arbitrary, but unique, numbers.
170 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700171 ssrc_stats.rtcp_stats.packets_lost = offset;
172 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
174 ssrc_stats.rtcp_stats.jitter = offset + 3;
175 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
176 }
asapersson35151f32016-05-02 23:44:01 -0700177 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000178 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000179
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000180 // Add statistics with some arbitrary, but unique, numbers.
181 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700182 ssrc_stats.rtcp_stats.packets_lost = offset;
183 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000184 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
185 ssrc_stats.rtcp_stats.jitter = offset + 3;
186 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
187 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000188 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000189 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000190}
191
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000192TEST_F(SendStatisticsProxyTest, Suspended) {
193 // Verify that the value is false by default.
194 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
195
196 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200197 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000198 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
199
200 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200201 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000202 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
203}
204
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000205TEST_F(SendStatisticsProxyTest, FrameCounts) {
206 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700207 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000208 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000209 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
210 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000211 FrameCounts frame_counts;
212 frame_counts.key_frames = offset;
213 frame_counts.delta_frames = offset + 1;
214 stats.frame_counts = frame_counts;
215 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000216 }
asapersson35151f32016-05-02 23:44:01 -0700217 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000218 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000219 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
220 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000221 FrameCounts frame_counts;
222 frame_counts.key_frames = offset;
223 frame_counts.delta_frames = offset + 1;
224 stats.frame_counts = frame_counts;
225 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000226 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000227
228 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000229 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000230}
231
232TEST_F(SendStatisticsProxyTest, DataCounters) {
233 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700234 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000235 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
236 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000237 size_t offset = ssrc * sizeof(StreamDataCounters);
238 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000239 counters.transmitted.payload_bytes = offset;
240 counters.transmitted.header_bytes = offset + 1;
241 counters.fec.packets = offset_uint32 + 2;
242 counters.transmitted.padding_bytes = offset + 3;
243 counters.retransmitted.packets = offset_uint32 + 4;
244 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000245 callback->DataCountersUpdated(counters, ssrc);
246 }
asapersson35151f32016-05-02 23:44:01 -0700247 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000248 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
249 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000250 size_t offset = ssrc * sizeof(StreamDataCounters);
251 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000252 counters.transmitted.payload_bytes = offset;
253 counters.transmitted.header_bytes = offset + 1;
254 counters.fec.packets = offset_uint32 + 2;
255 counters.transmitted.padding_bytes = offset + 3;
256 counters.retransmitted.packets = offset_uint32 + 4;
257 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000258 callback->DataCountersUpdated(counters, ssrc);
259 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000260
261 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000262 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000263}
264
265TEST_F(SendStatisticsProxyTest, Bitrate) {
266 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700267 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700268 uint32_t total;
269 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000270 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700271 total = ssrc;
272 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000273 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700274 expected_.substreams[ssrc].total_bitrate_bps = total;
275 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000276 }
asapersson35151f32016-05-02 23:44:01 -0700277 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700278 uint32_t total;
279 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700281 total = ssrc;
282 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000283 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700284 expected_.substreams[ssrc].total_bitrate_bps = total;
285 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000286 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000287
288 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000289 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000290}
291
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000292TEST_F(SendStatisticsProxyTest, SendSideDelay) {
293 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700294 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000295 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
296 // stream.
297 int avg_delay_ms = ssrc;
298 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200299 uint64_t total_packet_send_delay_ms = ssrc + 2;
300 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
301 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000302 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
303 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200304 expected_.substreams[ssrc].total_packet_send_delay_ms =
305 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000306 }
asapersson35151f32016-05-02 23:44:01 -0700307 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000308 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
309 // stream.
310 int avg_delay_ms = ssrc;
311 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200312 uint64_t total_packet_send_delay_ms = ssrc + 2;
313 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
314 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000315 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
316 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200317 expected_.substreams[ssrc].total_packet_send_delay_ms =
318 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000319 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000320 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000321 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000322}
323
Peter Boströme4499152016-02-05 11:13:28 +0100324TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800325 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200326 int encode_usage_percent = 80;
327 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
328 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800329
330 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
331 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200332 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800333}
334
Henrik Boström5684af52019-04-02 15:05:21 +0200335TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
336 const int kEncodeUsagePercent = 0; // Don't care for this test.
337 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
338 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
339 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
340 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
341 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
342}
343
sakal43536c32016-10-24 01:46:43 -0700344TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
345 EncodedImage encoded_image;
346 CodecSpecificInfo codec_info;
347 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
348 for (uint32_t i = 1; i <= 3; ++i) {
349 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
350 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
351 }
352}
353
sakal87da4042016-10-31 06:53:47 -0700354TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
355 EncodedImage encoded_image;
356 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200357 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700358 encoded_image.qp_ = 3;
359 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100360 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700361 encoded_image.qp_ = 127;
362 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100363 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700364}
365
366TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
367 EncodedImage encoded_image;
368 CodecSpecificInfo codec_info;
369 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200370 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700371 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200372 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700373}
374
Henrik Boström23aff9b2019-05-20 15:15:38 +0200375TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
376 const uint32_t kTargetBytesPerSecond = 100000;
377 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
378 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
379
380 EncodedImage encoded_image;
381 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
382 // On the first frame we don't know the frame rate yet, calculation yields
383 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
384 // increment by a full |kTargetBytesPerSecond|.
385 EXPECT_EQ(kTargetBytesPerSecond,
386 statistics_proxy_->GetStats().total_encoded_bytes_target);
387}
388
389TEST_F(SendStatisticsProxyTest,
390 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
391 const uint32_t kTargetBytesPerSecond = 100000;
392 const int kInterframeDelayMs = 100;
393
394 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
395 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
396 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
397 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
398 // this test can stop relying on rtc::ScopedFakeClock.
399 rtc::ScopedFakeClock fake_global_clock;
400 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
401
402 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
403 EncodedImage encoded_image;
404
405 // First frame
406 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
407 uint64_t first_total_encoded_bytes_target =
408 statistics_proxy_->GetStats().total_encoded_bytes_target;
409 // Second frame
410 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
411 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
412 encoded_image.SetTimestamp(encoded_image.Timestamp() +
413 90 * kInterframeDelayMs);
414 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
415
416 auto stats = statistics_proxy_->GetStats();
417 // By the time the second frame arrives, one frame has previously arrived
418 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
419 // the second frame's arrival should be 10 FPS.
420 uint64_t delta_encoded_bytes_target =
421 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
422 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
423}
424
asapersson09f05612017-05-15 23:40:18 -0700425TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200426 SendStatisticsProxy::AdaptationSteps cpu_counts;
427 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700428 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700429 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200430 cpu_counts.num_framerate_reductions = 1;
431 cpu_counts.num_resolution_reductions = 0;
432 statistics_proxy_->OnAdaptationChanged(
433 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
434 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700435 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700436 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200437 cpu_counts.num_framerate_reductions = 0;
438 cpu_counts.num_resolution_reductions = 1;
439 statistics_proxy_->OnAdaptationChanged(
440 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
441 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700442 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700443 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200444 cpu_counts.num_framerate_reductions = 1;
445 cpu_counts.num_resolution_reductions = absl::nullopt;
446 statistics_proxy_->OnAdaptationChanged(
447 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
448 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700449 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700450 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200451 cpu_counts.num_framerate_reductions = absl::nullopt;
452 cpu_counts.num_resolution_reductions = absl::nullopt;
453 statistics_proxy_->OnAdaptationChanged(
454 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
455 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700456 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
457 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
458}
459
460TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200461 SendStatisticsProxy::AdaptationSteps cpu_counts;
462 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700463 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
464 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200465 quality_counts.num_framerate_reductions = 1;
466 quality_counts.num_resolution_reductions = 0;
467 statistics_proxy_->OnAdaptationChanged(
468 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
469 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700470 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
471 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200472 quality_counts.num_framerate_reductions = 0;
473 quality_counts.num_resolution_reductions = 1;
474 statistics_proxy_->OnAdaptationChanged(
475 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
476 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700477 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
478 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200479 quality_counts.num_framerate_reductions = 1;
480 quality_counts.num_resolution_reductions = absl::nullopt;
481 statistics_proxy_->OnAdaptationChanged(
482 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
483 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700484 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
485 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200486 quality_counts.num_framerate_reductions = absl::nullopt;
487 quality_counts.num_resolution_reductions = absl::nullopt;
488 statistics_proxy_->OnAdaptationChanged(
489 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
490 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700491 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
492 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
493}
494
495TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200496 SendStatisticsProxy::AdaptationSteps cpu_counts;
497 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700498 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
499
Niels Möller213618e2018-07-24 09:29:58 +0200500 cpu_counts.num_resolution_reductions = 1;
501 statistics_proxy_->OnAdaptationChanged(
502 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
503 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700504 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700505 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
506 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
507
Niels Möller213618e2018-07-24 09:29:58 +0200508 cpu_counts.num_resolution_reductions = 2;
509 statistics_proxy_->OnAdaptationChanged(
510 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
511 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700512 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
513 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700514 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700515 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700516}
517
asapersson09f05612017-05-15 23:40:18 -0700518TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200519 SendStatisticsProxy::AdaptationSteps cpu_counts;
520 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700521 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
522
Niels Möller213618e2018-07-24 09:29:58 +0200523 quality_counts.num_framerate_reductions = 1;
524 statistics_proxy_->OnAdaptationChanged(
525 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
526 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700527 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
528 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700529 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
530
Niels Möller213618e2018-07-24 09:29:58 +0200531 quality_counts.num_framerate_reductions = 0;
532 statistics_proxy_->OnAdaptationChanged(
533 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
534 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700535 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700536 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700537 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
538 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700539}
540
asapersson09f05612017-05-15 23:40:18 -0700541TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700542 // First RTP packet sent.
543 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700544 // Min runtime has passed.
545 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
546 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100547 EXPECT_METRIC_EQ(
548 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
549 EXPECT_METRIC_EQ(
550 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700551}
552
553TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700554 // First RTP packet sent.
555 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700556 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200557 SendStatisticsProxy::AdaptationSteps cpu_counts;
558 SendStatisticsProxy::AdaptationSteps quality_counts;
559 statistics_proxy_->OnAdaptationChanged(
560 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
561 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700562 // Min runtime has not passed.
563 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
564 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100565 EXPECT_METRIC_EQ(
566 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
567 EXPECT_METRIC_EQ(
568 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700569}
570
asapersson09f05612017-05-15 23:40:18 -0700571TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700572 // First RTP packet sent.
573 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700574 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200575 SendStatisticsProxy::AdaptationSteps cpu_counts;
576 SendStatisticsProxy::AdaptationSteps quality_counts;
577 statistics_proxy_->OnAdaptationChanged(
578 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
579 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700580 // Min runtime has passed.
581 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
582 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100583 EXPECT_METRIC_EQ(
584 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
585 EXPECT_METRIC_EQ(
586 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
587 EXPECT_METRIC_EQ(
588 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
589 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700590 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
591}
592
593TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700594 // First RTP packet sent.
595 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700596 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200597 SendStatisticsProxy::AdaptationSteps cpu_counts;
598 SendStatisticsProxy::AdaptationSteps quality_counts;
599 statistics_proxy_->OnAdaptationChanged(
600 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
601 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700602 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200603 statistics_proxy_->OnAdaptationChanged(
604 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
605 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700606 fake_clock_.AdvanceTimeMilliseconds(10000);
607 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100608 EXPECT_METRIC_EQ(
609 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
610 EXPECT_METRIC_EQ(
611 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700612}
613
Åsa Persson875841d2018-01-08 08:49:53 +0100614TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
615 // First RTP packet sent.
616 UpdateDataCounters(kFirstSsrc);
617 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200618 SendStatisticsProxy::AdaptationSteps cpu_counts;
619 SendStatisticsProxy::AdaptationSteps quality_counts;
620 statistics_proxy_->OnAdaptationChanged(
621 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
622 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100623 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200624 statistics_proxy_->OnAdaptationChanged(
625 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
626 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100627 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
628 fake_clock_.AdvanceTimeMilliseconds(10000);
629 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100630 EXPECT_METRIC_EQ(
631 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
632 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100633 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
634}
635
636TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
637 // First RTP packet sent.
638 UpdateDataCounters(kFirstSsrc);
639 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200640 SendStatisticsProxy::AdaptationSteps cpu_counts;
641 SendStatisticsProxy::AdaptationSteps quality_counts;
642 statistics_proxy_->OnAdaptationChanged(
643 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
644 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100645 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200646 quality_counts.num_resolution_reductions = 1;
647 statistics_proxy_->OnAdaptationChanged(
648 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
649 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100650 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200651 quality_counts.num_resolution_reductions = 2;
652 statistics_proxy_->OnAdaptationChanged(
653 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
654 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100655 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200656 quality_counts.num_resolution_reductions = 3;
657 statistics_proxy_->OnAdaptationChanged(
658 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
659 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100660 fake_clock_.AdvanceTimeMilliseconds(10000);
661 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100662 EXPECT_METRIC_EQ(
663 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
664 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100665 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
666}
667
668TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
669 // First RTP packet sent.
670 UpdateDataCounters(kFirstSsrc);
671 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200672 SendStatisticsProxy::AdaptationSteps cpu_counts;
673 SendStatisticsProxy::AdaptationSteps quality_counts;
674 statistics_proxy_->OnAdaptationChanged(
675 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
676 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100677 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200678 statistics_proxy_->OnAdaptationChanged(
679 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
680 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100681 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
682 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
683 fake_clock_.AdvanceTimeMilliseconds(10000);
684 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100685 EXPECT_METRIC_EQ(
686 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
687 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100688 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
689}
690
691TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
692 // First RTP packet sent.
693 UpdateDataCounters(kFirstSsrc);
694 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200695 SendStatisticsProxy::AdaptationSteps cpu_counts;
696 SendStatisticsProxy::AdaptationSteps quality_counts;
697 statistics_proxy_->OnAdaptationChanged(
698 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
699 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100700 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200701 quality_counts.num_resolution_reductions = 1;
702 statistics_proxy_->OnAdaptationChanged(
703 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
704 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100705 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200706 quality_counts.num_resolution_reductions = 2;
707 statistics_proxy_->OnAdaptationChanged(
708 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
709 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100710 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200711 quality_counts.num_resolution_reductions = 3;
712 statistics_proxy_->OnAdaptationChanged(
713 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
714 quality_counts);
715 quality_counts.num_framerate_reductions = 1;
716 statistics_proxy_->OnAdaptationChanged(
717 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
718 quality_counts);
719 quality_counts.num_framerate_reductions = 0;
720 statistics_proxy_->OnAdaptationChanged(
721 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
722 quality_counts);
723 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
724 statistics_proxy_->OnAdaptationChanged(
725 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
726 quality_counts);
727 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
728 statistics_proxy_->OnAdaptationChanged(
729 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
730 quality_counts);
731 quality_counts.num_resolution_reductions = 0;
732 statistics_proxy_->OnAdaptationChanged(
733 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
734 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100735
736 fake_clock_.AdvanceTimeMilliseconds(10000);
737 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100738 EXPECT_METRIC_EQ(
739 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
740 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100741 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
742}
743
asapersson6eca98b2017-04-04 23:40:50 -0700744TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700745 // First RTP packet sent.
746 UpdateDataCounters(kFirstSsrc);
747
asapersson09f05612017-05-15 23:40:18 -0700748 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200749 SendStatisticsProxy::AdaptationSteps cpu_counts;
750 SendStatisticsProxy::AdaptationSteps quality_counts;
751 quality_counts.num_framerate_reductions = absl::nullopt;
752 quality_counts.num_resolution_reductions = absl::nullopt;
753 statistics_proxy_->OnAdaptationChanged(
754 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
755 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700756 fake_clock_.AdvanceTimeMilliseconds(10000);
757
asapersson09f05612017-05-15 23:40:18 -0700758 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700759 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200760 quality_counts.num_framerate_reductions = 0;
761 statistics_proxy_->OnAdaptationChanged(
762 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
763 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700764 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200765 statistics_proxy_->OnAdaptationChanged(
766 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
767 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700768 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200769 statistics_proxy_->OnAdaptationChanged(
770 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
771 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700772 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200773 statistics_proxy_->OnAdaptationChanged(
774 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
775 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700776
asapersson09f05612017-05-15 23:40:18 -0700777 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200778 quality_counts.num_framerate_reductions = absl::nullopt;
779 statistics_proxy_->OnAdaptationChanged(
780 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
781 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700782 fake_clock_.AdvanceTimeMilliseconds(30000);
783
asapersson09f05612017-05-15 23:40:18 -0700784 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700785 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200786 quality_counts.num_resolution_reductions = 0;
787 statistics_proxy_->OnAdaptationChanged(
788 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
789 quality_counts);
790 statistics_proxy_->OnAdaptationChanged(
791 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
792 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700793 fake_clock_.AdvanceTimeMilliseconds(10000);
794
asapersson09f05612017-05-15 23:40:18 -0700795 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200796 quality_counts.num_resolution_reductions = absl::nullopt;
797 statistics_proxy_->OnAdaptationChanged(
798 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
799 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700800 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200801 statistics_proxy_->OnAdaptationChanged(
802 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
803 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700804 fake_clock_.AdvanceTimeMilliseconds(20000);
805
asapersson0944a802017-04-07 00:57:58 -0700806 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700807 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100808 EXPECT_METRIC_EQ(
809 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
810 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700811 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
812}
813
asapersson0944a802017-04-07 00:57:58 -0700814TEST_F(SendStatisticsProxyTest,
815 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
816 // First RTP packet sent.
817 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700818
asapersson0944a802017-04-07 00:57:58 -0700819 // Suspend and resume video.
820 statistics_proxy_->OnSuspendChange(true);
821 fake_clock_.AdvanceTimeMilliseconds(5000);
822 statistics_proxy_->OnSuspendChange(false);
823
824 // Min runtime has passed but scaling not enabled.
825 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
826 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100827 EXPECT_METRIC_EQ(
828 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
829 EXPECT_METRIC_EQ(
830 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700831}
832
833TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
834 // First RTP packet sent.
835 UpdateDataCounters(kFirstSsrc);
836
asapersson09f05612017-05-15 23:40:18 -0700837 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200838 SendStatisticsProxy::AdaptationSteps cpu_counts;
839 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700840 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200841 statistics_proxy_->OnAdaptationChanged(
842 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
843 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700844 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200845 statistics_proxy_->OnAdaptationChanged(
846 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
847 quality_counts);
848 statistics_proxy_->OnAdaptationChanged(
849 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
850 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700851
852 // Suspend and resume video.
853 statistics_proxy_->OnSuspendChange(true);
854 fake_clock_.AdvanceTimeMilliseconds(30000);
855 statistics_proxy_->OnSuspendChange(false);
856
857 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200858 statistics_proxy_->OnAdaptationChanged(
859 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
860 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700861 fake_clock_.AdvanceTimeMilliseconds(10000);
862
863 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
864 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100865 EXPECT_METRIC_EQ(
866 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
867 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700868 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
869}
870
871TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
872 // First RTP packet sent.
873 UpdateDataCounters(kFirstSsrc);
874
875 // Video not suspended.
876 statistics_proxy_->OnSuspendChange(false);
877 fake_clock_.AdvanceTimeMilliseconds(30000);
878
asapersson09f05612017-05-15 23:40:18 -0700879 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200880 SendStatisticsProxy::AdaptationSteps cpu_counts;
881 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700882 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200883 statistics_proxy_->OnAdaptationChanged(
884 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
885 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700886 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200887 statistics_proxy_->OnAdaptationChanged(
888 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
889 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700890
891 // Video not suspended, stats time already started.
892 statistics_proxy_->OnSuspendChange(false);
893 fake_clock_.AdvanceTimeMilliseconds(10000);
894
asapersson09f05612017-05-15 23:40:18 -0700895 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200896 cpu_counts.num_framerate_reductions = absl::nullopt;
897 cpu_counts.num_resolution_reductions = absl::nullopt;
898 statistics_proxy_->OnAdaptationChanged(
899 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
900 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700901 fake_clock_.AdvanceTimeMilliseconds(30000);
902
903 // Suspend and resume video, stats time not started when scaling not enabled.
904 statistics_proxy_->OnSuspendChange(true);
905 fake_clock_.AdvanceTimeMilliseconds(30000);
906 statistics_proxy_->OnSuspendChange(false);
907 fake_clock_.AdvanceTimeMilliseconds(30000);
908
asapersson09f05612017-05-15 23:40:18 -0700909 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700910 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200911 cpu_counts.num_framerate_reductions = 0;
912 cpu_counts.num_resolution_reductions = 0;
913 statistics_proxy_->OnAdaptationChanged(
914 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
915 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700916 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200917 statistics_proxy_->OnAdaptationChanged(
918 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
919 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700920
921 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
922 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100923 EXPECT_METRIC_EQ(
924 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
925 EXPECT_METRIC_EQ(
926 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700927}
928
929TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
930 // First RTP packet sent.
931 UpdateDataCounters(kFirstSsrc);
932
933 // Video suspended.
934 statistics_proxy_->OnSuspendChange(true);
935
asapersson09f05612017-05-15 23:40:18 -0700936 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200937 SendStatisticsProxy::AdaptationSteps cpu_counts;
938 SendStatisticsProxy::AdaptationSteps quality_counts;
939 statistics_proxy_->OnAdaptationChanged(
940 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
941 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700942 fake_clock_.AdvanceTimeMilliseconds(10000);
943
944 // Resume video, stats time started.
945 // Adapt changes: 1, elapsed time: 10 sec.
946 statistics_proxy_->OnSuspendChange(false);
947 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200948 statistics_proxy_->OnAdaptationChanged(
949 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
950 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700951
952 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
953 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100954 EXPECT_METRIC_EQ(
955 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
956 EXPECT_METRIC_EQ(
957 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -0700958}
959
960TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700961 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700962 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200963 SendStatisticsProxy::AdaptationSteps cpu_counts;
964 SendStatisticsProxy::AdaptationSteps quality_counts;
965 statistics_proxy_->OnAdaptationChanged(
966 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
967 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700968 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700969 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700970
asapersson0944a802017-04-07 00:57:58 -0700971 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700972 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200973 statistics_proxy_->OnAdaptationChanged(
974 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
975 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700976 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700977
asapersson0944a802017-04-07 00:57:58 -0700978 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700979 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100980 EXPECT_METRIC_EQ(
981 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
982 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700983 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
984}
985
986TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700987 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200988 SendStatisticsProxy::AdaptationSteps cpu_counts;
989 SendStatisticsProxy::AdaptationSteps quality_counts;
990 statistics_proxy_->OnAdaptationChanged(
991 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
992 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700993 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200994 cpu_counts.num_framerate_reductions = absl::nullopt;
995 cpu_counts.num_resolution_reductions = absl::nullopt;
996 statistics_proxy_->OnAdaptationChanged(
997 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
998 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700999
1000 // Send first packet, scaling disabled.
1001 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001002 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001003 fake_clock_.AdvanceTimeMilliseconds(60000);
1004
asapersson09f05612017-05-15 23:40:18 -07001005 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +02001006 cpu_counts.num_resolution_reductions = 0;
1007 statistics_proxy_->OnAdaptationChanged(
1008 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1009 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001010 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001011 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001012
asapersson0944a802017-04-07 00:57:58 -07001013 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001014 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001015 statistics_proxy_->OnAdaptationChanged(
1016 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1017 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001018
asapersson0944a802017-04-07 00:57:58 -07001019 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001020 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001021 EXPECT_METRIC_EQ(
1022 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1023 EXPECT_METRIC_EQ(
1024 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001025}
1026
1027TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001028 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001029 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001030 SendStatisticsProxy::AdaptationSteps cpu_counts;
1031 SendStatisticsProxy::AdaptationSteps quality_counts;
1032 quality_counts.num_framerate_reductions = absl::nullopt;
1033 quality_counts.num_resolution_reductions = absl::nullopt;
1034 statistics_proxy_->OnAdaptationChanged(
1035 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1036 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001037
asapersson0944a802017-04-07 00:57:58 -07001038 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001039 statistics_proxy_->OnAdaptationChanged(
1040 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1041 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001042 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +02001043 statistics_proxy_->OnAdaptationChanged(
1044 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1045 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001046 fake_clock_.AdvanceTimeMilliseconds(9000);
1047
1048 // Switch content type, real-time stats should be updated.
1049 VideoEncoderConfig config;
1050 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001051 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001052 EXPECT_METRIC_EQ(
1053 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1054 EXPECT_METRIC_EQ(
1055 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1056 EXPECT_METRIC_EQ(
1057 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001058
asapersson0944a802017-04-07 00:57:58 -07001059 // First RTP packet sent, scaling enabled.
1060 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001061 statistics_proxy_->OnAdaptationChanged(
1062 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1063 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001064
asapersson0944a802017-04-07 00:57:58 -07001065 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001066 statistics_proxy_->OnAdaptationChanged(
1067 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1068 quality_counts);
1069 statistics_proxy_->OnAdaptationChanged(
1070 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1071 quality_counts);
1072 statistics_proxy_->OnAdaptationChanged(
1073 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1074 quality_counts);
1075 statistics_proxy_->OnAdaptationChanged(
1076 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1077 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001078 fake_clock_.AdvanceTimeMilliseconds(120000);
1079
1080 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001081 EXPECT_METRIC_EQ(1,
1082 metrics::NumSamples(
1083 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1084 EXPECT_METRIC_EQ(
1085 1, metrics::NumEvents(
1086 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1087 EXPECT_METRIC_EQ(
1088 0, metrics::NumSamples(
1089 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001090}
1091
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001092TEST_F(SendStatisticsProxyTest,
1093 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
1094 SendStatisticsProxy::AdaptationSteps cpu_counts;
1095 SendStatisticsProxy::AdaptationSteps quality_counts;
1096
1097 cpu_counts.num_resolution_reductions = 1;
1098
1099 statistics_proxy_->OnAdaptationChanged(
1100 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1101 quality_counts);
1102
1103 EXPECT_EQ(QualityLimitationReason::kCpu,
1104 statistics_proxy_->GetStats().quality_limitation_reason);
1105}
1106
1107TEST_F(SendStatisticsProxyTest,
1108 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
1109 SendStatisticsProxy::AdaptationSteps cpu_counts;
1110 SendStatisticsProxy::AdaptationSteps quality_counts;
1111
1112 cpu_counts.num_framerate_reductions = 1;
1113
1114 statistics_proxy_->OnAdaptationChanged(
1115 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1116 quality_counts);
1117
1118 EXPECT_EQ(QualityLimitationReason::kCpu,
1119 statistics_proxy_->GetStats().quality_limitation_reason);
1120}
1121
1122TEST_F(SendStatisticsProxyTest,
1123 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
1124 SendStatisticsProxy::AdaptationSteps cpu_counts;
1125 SendStatisticsProxy::AdaptationSteps quality_counts;
1126
1127 quality_counts.num_resolution_reductions = 1;
1128
1129 statistics_proxy_->OnAdaptationChanged(
1130 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1131 quality_counts);
1132
1133 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1134 statistics_proxy_->GetStats().quality_limitation_reason);
1135}
1136
1137TEST_F(SendStatisticsProxyTest,
1138 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
1139 SendStatisticsProxy::AdaptationSteps cpu_counts;
1140 SendStatisticsProxy::AdaptationSteps quality_counts;
1141
1142 quality_counts.num_framerate_reductions = 1;
1143
1144 statistics_proxy_->OnAdaptationChanged(
1145 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1146 quality_counts);
1147
1148 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1149 statistics_proxy_->GetStats().quality_limitation_reason);
1150}
1151
1152TEST_F(SendStatisticsProxyTest,
1153 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
1154 SendStatisticsProxy::AdaptationSteps cpu_counts;
1155 SendStatisticsProxy::AdaptationSteps quality_counts;
1156
1157 cpu_counts.num_resolution_reductions = 1;
1158 quality_counts.num_resolution_reductions = 1;
1159
1160 // Even if the last adaptation reason is kCpu, if the counters indicate being
1161 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
1162 statistics_proxy_->OnAdaptationChanged(
1163 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1164 quality_counts);
1165
1166 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1167 statistics_proxy_->GetStats().quality_limitation_reason);
1168}
1169
1170TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
1171 SendStatisticsProxy::AdaptationSteps cpu_counts;
1172 SendStatisticsProxy::AdaptationSteps quality_counts;
1173
1174 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1175 // due to "none" being the default value.
1176 cpu_counts.num_resolution_reductions = 1;
1177 statistics_proxy_->OnAdaptationChanged(
1178 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1179 quality_counts);
1180 // Go back to not being limited.
1181 cpu_counts.num_resolution_reductions = 0;
1182 statistics_proxy_->OnAdaptationChanged(
1183 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1184 quality_counts);
1185
1186 EXPECT_EQ(QualityLimitationReason::kNone,
1187 statistics_proxy_->GetStats().quality_limitation_reason);
1188}
1189
1190TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
1191 SendStatisticsProxy::AdaptationSteps cpu_counts;
1192 SendStatisticsProxy::AdaptationSteps quality_counts;
1193
1194 // Not limited for 3000 ms
1195 fake_clock_.AdvanceTimeMilliseconds(3000);
1196 // CPU limited for 2000 ms
1197 cpu_counts.num_resolution_reductions = 1;
1198 statistics_proxy_->OnAdaptationChanged(
1199 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1200 quality_counts);
1201 fake_clock_.AdvanceTimeMilliseconds(2000);
1202 // Bandwidth limited for 1000 ms
1203 cpu_counts.num_resolution_reductions = 0;
1204 quality_counts.num_resolution_reductions = 1;
1205 statistics_proxy_->OnAdaptationChanged(
1206 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1207 quality_counts);
1208 fake_clock_.AdvanceTimeMilliseconds(1000);
1209 // CPU limited for another 2000 ms
1210 cpu_counts.num_resolution_reductions = 1;
1211 quality_counts.num_resolution_reductions = 0;
1212 statistics_proxy_->OnAdaptationChanged(
1213 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1214 quality_counts);
1215 fake_clock_.AdvanceTimeMilliseconds(2000);
1216
1217 auto quality_limitation_durations_ms =
1218 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1219
1220 EXPECT_EQ(3000,
1221 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1222 EXPECT_EQ(4000,
1223 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1224 EXPECT_EQ(
1225 1000,
1226 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1227 EXPECT_EQ(0,
1228 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1229}
1230
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001231TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1232 EXPECT_EQ(
1233 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1234}
1235
1236TEST_F(SendStatisticsProxyTest,
1237 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1238 VideoCodec codec;
1239 VideoBitrateAllocation allocation;
1240 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1241 EXPECT_EQ(
1242 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1243}
1244
1245TEST_F(SendStatisticsProxyTest,
1246 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1247 VideoCodec codec;
1248 codec.simulcastStream[0].active = true;
1249 codec.simulcastStream[1].active = true;
1250 codec.simulcastStream[2].active = true;
1251 VideoBitrateAllocation allocation;
1252 allocation.SetBitrate(0, 0, 100);
1253 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1254 EXPECT_EQ(
1255 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1256}
1257
1258TEST_F(SendStatisticsProxyTest,
1259 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1260 VideoCodec codec;
1261 codec.simulcastStream[0].active = true;
1262 codec.simulcastStream[1].active = true;
1263 codec.simulcastStream[2].active = true;
1264 VideoBitrateAllocation allocation;
1265 allocation.SetBitrate(0, 0, 100);
1266 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1267 allocation.SetBitrate(1, 0, 100);
1268 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1269 EXPECT_EQ(
1270 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1271}
1272
1273TEST_F(SendStatisticsProxyTest,
1274 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1275 VideoCodec codec;
1276 codec.simulcastStream[0].active = true;
1277 VideoBitrateAllocation allocation;
1278 allocation.SetBitrate(0, 0, 100);
1279 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1280 // Layer 0 got more bandwidth, but still only one layer on
1281 allocation.SetBitrate(0, 0, 200);
1282 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1283 EXPECT_EQ(
1284 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1285}
1286
1287TEST_F(SendStatisticsProxyTest,
1288 QualityLimitationResolutionChangesWithTogglingLayers) {
1289 VideoCodec codec;
1290 codec.simulcastStream[0].active = true;
1291 codec.simulcastStream[1].active = true;
1292 codec.simulcastStream[2].active = true;
1293 VideoBitrateAllocation allocation;
1294 allocation.SetBitrate(0, 0, 100);
1295 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1296 EXPECT_EQ(
1297 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1298 allocation.SetBitrate(1, 0, 300);
1299 allocation.SetBitrate(2, 0, 500);
1300 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1301 EXPECT_EQ(
1302 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1303 // Layer 2 off
1304 allocation.SetBitrate(2, 0, 0);
1305 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1306 EXPECT_EQ(
1307 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1308 // Layer 2 back on
1309 allocation.SetBitrate(2, 0, 500);
1310 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1311 EXPECT_EQ(
1312 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1313 allocation.SetBitrate(0, 0, 0);
1314 allocation.SetBitrate(1, 0, 0);
1315 allocation.SetBitrate(2, 0, 0);
1316 // All layers off
1317 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1318 EXPECT_EQ(
1319 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1320}
1321
1322TEST_F(SendStatisticsProxyTest,
1323 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1324 VideoCodec codec;
1325 // 3 layers
1326 codec.simulcastStream[0].active = true;
1327 codec.simulcastStream[1].active = true;
1328 codec.simulcastStream[2].active = true;
1329 VideoBitrateAllocation allocation;
1330 allocation.SetBitrate(0, 0, 500);
1331 allocation.SetBitrate(1, 0, 500);
1332 allocation.SetBitrate(2, 0, 500);
1333 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1334 EXPECT_EQ(
1335 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1336
1337 // Down to one layer now, triggered by a config change
1338 codec.numberOfSimulcastStreams = 1;
1339 codec.simulcastStream[1].active = false;
1340 codec.simulcastStream[2].active = false;
1341 allocation.SetBitrate(0, 0, 100);
1342 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1343 EXPECT_EQ(
1344 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1345
1346 // Up to 3 layers again.
1347 codec.numberOfSimulcastStreams = 3;
1348 codec.simulcastStream[1].active = true;
1349 codec.simulcastStream[2].active = true;
1350 allocation.SetBitrate(0, 0, 500);
1351 allocation.SetBitrate(1, 0, 500);
1352 allocation.SetBitrate(2, 0, 500);
1353 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1354 EXPECT_EQ(
1355 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1356}
1357
1358TEST_F(SendStatisticsProxyTest,
1359 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1360 VideoCodec codec;
1361 codec.simulcastStream[0].active = true;
1362 codec.spatialLayers[0].active = true;
1363 codec.spatialLayers[1].active = true;
1364 codec.spatialLayers[2].active = true;
1365 VideoBitrateAllocation allocation;
1366 allocation.SetBitrate(0, 0, 500);
1367 allocation.SetBitrate(1, 0, 500);
1368 allocation.SetBitrate(2, 0, 500);
1369 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1370 EXPECT_EQ(
1371 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1372
1373 // Down to one layer now, triggered by a config change
1374 codec.spatialLayers[1].active = false;
1375 codec.spatialLayers[2].active = false;
1376 allocation.SetBitrate(0, 0, 100);
1377 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1378 EXPECT_EQ(
1379 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1380
1381 // Up to 3 layers again.
1382 codec.spatialLayers[1].active = true;
1383 codec.spatialLayers[2].active = true;
1384 allocation.SetBitrate(0, 0, 500);
1385 allocation.SetBitrate(1, 0, 500);
1386 allocation.SetBitrate(2, 0, 500);
1387 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1388 EXPECT_EQ(
1389 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1390}
1391
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001392TEST_F(SendStatisticsProxyTest,
1393 QualityLimitationReasonsAreCorrectForContentType) {
1394 // Realtime case.
1395 // Configure two streams.
1396 VideoEncoderConfig config;
1397 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1398 config.number_of_streams = 2;
1399 VideoStream stream1;
1400 stream1.width = kWidth / 2;
1401 stream1.height = kHeight / 2;
1402 VideoStream stream2;
1403 stream2.width = kWidth;
1404 stream2.height = kHeight;
1405 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1406 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1407 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1408 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1409 QualityLimitationReason::kNone);
1410 // Bw disabled one layer.
1411 VideoCodec codec;
1412 codec.numberOfSimulcastStreams = 2;
1413 codec.simulcastStream[0].active = true;
1414 codec.simulcastStream[1].active = true;
1415 VideoBitrateAllocation allocation;
1416 // Some positive bitrate only on the first stream.
1417 allocation.SetBitrate(0, 0, 10000);
1418 allocation.SetBitrate(1, 0, 0);
1419 allocation.set_bw_limited(true);
1420 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1421 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1422 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1423 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1424 QualityLimitationReason::kBandwidth);
1425 // Bw enabled all layers.
1426 allocation.SetBitrate(1, 0, 10000);
1427 allocation.set_bw_limited(false);
1428 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1429 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1430 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1431 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1432 QualityLimitationReason::kNone);
1433
1434 // Screencast case
1435 // Configure two streams.
1436 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1437 config.number_of_streams = 2;
1438 stream1.width = kWidth;
1439 stream1.height = kHeight;
1440 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1441 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1442 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1443 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1444 QualityLimitationReason::kNone);
1445 // Bw disabled one layer.
1446 // Some positive bitrate only on the second stream.
1447 allocation.SetBitrate(0, 0, 10000);
1448 allocation.SetBitrate(1, 0, 0);
1449 allocation.set_bw_limited(true);
1450 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1451 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1452 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1453 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1454 QualityLimitationReason::kBandwidth);
1455 // Bw enabled all layers.
1456 allocation.SetBitrate(1, 0, 10000);
1457 allocation.set_bw_limited(false);
1458 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1459 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1460 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1461 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1462 QualityLimitationReason::kNone);
1463}
1464
asapersson59bac1a2016-01-07 23:36:00 -08001465TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001466 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001467 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1468
Pera48ddb72016-09-29 11:48:50 +02001469 // No switch, stats should not be updated.
1470 VideoEncoderConfig config;
1471 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001472 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001473 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001474
1475 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001476 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001477 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001478 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001479}
1480
asapersson320e45a2016-11-29 01:40:35 -08001481TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1482 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1483 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001484
asapersson320e45a2016-11-29 01:40:35 -08001485 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001486 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1487 EXPECT_METRIC_EQ(
1488 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1489 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1490 EXPECT_METRIC_EQ(
1491 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001492}
1493
1494TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001495 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001496 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001497 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1498 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1499 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001500 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001501
1502 // Not enough samples, stats should not be updated.
1503 for (int i = 0; i < kMinSamples - 1; ++i) {
1504 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001505 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001506 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1507 }
Åsa Persson0122e842017-10-16 12:19:23 +02001508 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001509 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1510 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001511
1512 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001513 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001514 for (int i = 0; i < kMinSamples; ++i) {
1515 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001516 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001517 encoded_image._encodedWidth = kWidth;
1518 encoded_image._encodedHeight = kHeight;
1519 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1520 encoded_image._encodedWidth = kWidth / 2;
1521 encoded_image._encodedHeight = kHeight / 2;
1522 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1523 }
1524
asapersson320e45a2016-11-29 01:40:35 -08001525 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001526 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1527 EXPECT_METRIC_EQ(
1528 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1529 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1530 EXPECT_METRIC_EQ(
1531 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001532}
1533
1534TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1535 const int kFps = 20;
1536 const int kMinPeriodicSamples = 6;
1537 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1538 for (int i = 0; i <= frames; ++i) {
1539 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1540 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1541 }
1542 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001543 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1544 EXPECT_METRIC_EQ(
1545 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001546}
1547
1548TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1549 EncodedImage encoded_image;
1550 const int kFps = 20;
1551 const int kMinPeriodicSamples = 6;
1552 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001553 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001554 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001555 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001556 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1557 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001558 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1559 }
1560 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001561 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1562 EXPECT_METRIC_EQ(
1563 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001564}
1565
1566TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1567 const int kFps = 20;
1568 const int kSuspendTimeMs = 10000;
1569 const int kMinPeriodicSamples = 6;
1570 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1571 for (int i = 0; i < frames; ++i) {
1572 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1573 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1574 }
1575 // Suspend.
1576 statistics_proxy_->OnSuspendChange(true);
1577 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1578
1579 for (int i = 0; i < frames; ++i) {
1580 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1581 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1582 }
1583 // Suspended time interval should not affect the framerate.
1584 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001585 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1586 EXPECT_METRIC_EQ(
1587 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001588}
1589
1590TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1591 EncodedImage encoded_image;
1592 const int kFps = 20;
1593 const int kSuspendTimeMs = 10000;
1594 const int kMinPeriodicSamples = 6;
1595 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001596 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001597 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001598 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001599 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1600 }
1601 // Suspend.
1602 statistics_proxy_->OnSuspendChange(true);
1603 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1604
Åsa Persson0122e842017-10-16 12:19:23 +02001605 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001606 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001607 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001608 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1609 }
1610 // Suspended time interval should not affect the framerate.
1611 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001612 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1613 EXPECT_METRIC_EQ(
1614 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001615}
1616
asaperssonf4e44af2017-04-19 02:01:06 -07001617TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001618 SendStatisticsProxy::AdaptationSteps cpu_counts;
1619 SendStatisticsProxy::AdaptationSteps quality_counts;
1620 cpu_counts.num_resolution_reductions = absl::nullopt;
1621 statistics_proxy_->OnAdaptationChanged(
1622 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1623 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001624
1625 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1626 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1627
1628 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001629 EXPECT_METRIC_EQ(
1630 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001631}
1632
1633TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001634 SendStatisticsProxy::AdaptationSteps cpu_counts;
1635 SendStatisticsProxy::AdaptationSteps quality_counts;
1636 cpu_counts.num_resolution_reductions = 0;
1637 statistics_proxy_->OnAdaptationChanged(
1638 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1639 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001640
perkj803d97f2016-11-01 11:45:46 -07001641 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1642 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1643
Niels Möller213618e2018-07-24 09:29:58 +02001644 cpu_counts.num_resolution_reductions = 1;
1645 statistics_proxy_->OnAdaptationChanged(
1646 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1647 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001648
1649 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1650 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1651
1652 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001653 EXPECT_METRIC_EQ(
1654 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1655 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001656 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1657}
1658
asapersson4374a092016-07-27 00:39:09 -07001659TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1660 const int64_t kTimeSec = 3;
1661 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1662 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001663 EXPECT_METRIC_EQ(
1664 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1665 EXPECT_METRIC_EQ(
1666 1,
1667 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001668}
1669
1670TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1671 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1672 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001673 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001674}
1675
asapersson66d4b372016-12-19 06:50:53 -08001676TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1677 // First RTP packet sent.
1678 UpdateDataCounters(kFirstSsrc);
1679
1680 // Min runtime has passed.
1681 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1682 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001683 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1684 EXPECT_METRIC_EQ(1,
1685 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001686}
1687
1688TEST_F(SendStatisticsProxyTest,
1689 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1690 // First RTP packet sent.
1691 UpdateDataCounters(kFirstSsrc);
1692
1693 // Min runtime has not passed.
1694 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1695 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001696 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1697 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001698}
1699
1700TEST_F(SendStatisticsProxyTest,
1701 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1702 // First RTP packet not sent.
1703 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1704 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001705 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001706}
1707
1708TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1709 // First RTP packet sent and min runtime passed.
1710 UpdateDataCounters(kFirstSsrc);
1711
1712 // No change. Video: 10000 ms, paused: 0 ms (0%).
1713 statistics_proxy_->OnSetEncoderTargetRate(50000);
1714 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1715 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1716
1717 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001718 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1719 EXPECT_METRIC_EQ(1,
1720 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1721 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1722 EXPECT_METRIC_EQ(1,
1723 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001724}
1725
1726TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1727 // First RTP packet sent and min runtime passed.
1728 UpdateDataCounters(kFirstSsrc);
1729
1730 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1731 statistics_proxy_->OnSetEncoderTargetRate(50000);
1732 fake_clock_.AdvanceTimeMilliseconds(7000);
1733 statistics_proxy_->OnSetEncoderTargetRate(0);
1734 fake_clock_.AdvanceTimeMilliseconds(3000);
1735 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1736
1737 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001738 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1739 EXPECT_METRIC_EQ(1,
1740 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1741 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1742 EXPECT_METRIC_EQ(1,
1743 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001744}
1745
1746TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1747 // First RTP packet sent.
1748 UpdateDataCounters(kFirstSsrc);
1749
1750 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1751 statistics_proxy_->OnSetEncoderTargetRate(0);
1752 fake_clock_.AdvanceTimeMilliseconds(1000);
1753 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1754 fake_clock_.AdvanceTimeMilliseconds(7000);
1755 statistics_proxy_->OnSetEncoderTargetRate(60000);
1756 fake_clock_.AdvanceTimeMilliseconds(3000);
1757 statistics_proxy_->OnSetEncoderTargetRate(0);
1758 fake_clock_.AdvanceTimeMilliseconds(250);
1759 statistics_proxy_->OnSetEncoderTargetRate(0);
1760 fake_clock_.AdvanceTimeMilliseconds(750);
1761 statistics_proxy_->OnSetEncoderTargetRate(60000);
1762 fake_clock_.AdvanceTimeMilliseconds(5000);
1763 statistics_proxy_->OnSetEncoderTargetRate(50000);
1764 fake_clock_.AdvanceTimeMilliseconds(4000);
1765 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1766
1767 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001768 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1769 EXPECT_METRIC_EQ(1,
1770 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1771 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1772 EXPECT_METRIC_EQ(1,
1773 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001774}
1775
1776TEST_F(SendStatisticsProxyTest,
1777 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1778 // First RTP packet sent.
1779 UpdateDataCounters(kFirstSsrc);
1780 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1781
1782 // Min runtime has not passed.
1783 statistics_proxy_->OnSetEncoderTargetRate(50000);
1784 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1785 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1786
1787 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001788 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001789}
1790
asapersson118ef002016-03-31 00:00:19 -07001791TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001792 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001793 CodecSpecificInfo codec_info;
1794 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001795
perkj803d97f2016-11-01 11:45:46 -07001796 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001797 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001798 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001799 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001800 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001801 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001802 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001803 }
1804 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001805 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1806 EXPECT_METRIC_EQ(
1807 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1808 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1809 EXPECT_METRIC_EQ(
1810 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001811}
1812
1813TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1814 VideoSendStream::Config config(nullptr);
1815 config.rtp.ssrcs.push_back(kFirstSsrc);
1816 statistics_proxy_.reset(new SendStatisticsProxy(
1817 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1818
asapersson118ef002016-03-31 00:00:19 -07001819 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001820 CodecSpecificInfo codec_info;
1821 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001822
perkj803d97f2016-11-01 11:45:46 -07001823 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001824 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001825 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001826 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001827 }
1828 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001829 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1830 EXPECT_METRIC_EQ(1,
1831 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001832}
1833
asapersson5265fed2016-04-18 02:58:47 -07001834TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001835 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001836 CodecSpecificInfo codec_info;
1837 codec_info.codecType = kVideoCodecVP9;
1838 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001839
perkj803d97f2016-11-01 11:45:46 -07001840 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001841 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001842 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001843 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001844 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001845 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001846 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001847 }
1848 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001849 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1850 EXPECT_METRIC_EQ(
1851 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1852 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1853 EXPECT_METRIC_EQ(
1854 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001855}
1856
1857TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1858 VideoSendStream::Config config(nullptr);
1859 config.rtp.ssrcs.push_back(kFirstSsrc);
1860 statistics_proxy_.reset(new SendStatisticsProxy(
1861 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1862
asapersson5265fed2016-04-18 02:58:47 -07001863 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001864 CodecSpecificInfo codec_info;
1865 codec_info.codecType = kVideoCodecVP9;
1866 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001867
perkj803d97f2016-11-01 11:45:46 -07001868 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001869 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001870 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001871 }
1872 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001873 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1874 EXPECT_METRIC_EQ(1,
1875 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001876}
1877
asapersson827cab32016-11-02 09:08:47 -07001878TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1879 EncodedImage encoded_image;
1880 CodecSpecificInfo codec_info;
1881 codec_info.codecType = kVideoCodecH264;
1882
1883 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001884 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001885 encoded_image.qp_ = kQpIdx0;
1886 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001887 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001888 encoded_image.qp_ = kQpIdx1;
1889 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001890 }
1891 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001892 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1893 EXPECT_METRIC_EQ(
1894 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1895 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1896 EXPECT_METRIC_EQ(
1897 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001898}
1899
asapersson4ee70462016-10-31 04:05:12 -07001900TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001901 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1902 // Configure one stream.
1903 VideoEncoderConfig config;
1904 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1905 VideoStream stream1;
1906 stream1.width = kWidth;
1907 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001908 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001909
1910 const int64_t kMaxEncodedFrameWindowMs = 800;
1911 const int kFps = 20;
1912 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1913 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1914 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1915
1916 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001917 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001918 encoded_image._encodedWidth = kWidth;
1919 encoded_image._encodedHeight = kHeight;
1920 for (int i = 0; i < kMinSamples; ++i) {
1921 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001922 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1923 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001924 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001925 }
asapersson4ee70462016-10-31 04:05:12 -07001926
1927 // Histograms are updated when the statistics_proxy_ is deleted.
1928 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001929 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1930 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1931 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1932 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001933}
1934
1935TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001936 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1937 // Configure two streams.
1938 VideoEncoderConfig config;
1939 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1940 VideoStream stream1;
1941 stream1.width = kWidth / 2;
1942 stream1.height = kHeight / 2;
1943 VideoStream stream2;
1944 stream2.width = kWidth;
1945 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001946 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001947
1948 const int64_t kMaxEncodedFrameWindowMs = 800;
1949 const int kFps = 20;
1950 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1951 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1952 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1953
1954 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001955 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001956 for (int i = 0; i < kMinSamples; ++i) {
1957 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001958 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1959 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001960 encoded_image._encodedWidth = kWidth;
1961 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001962 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001963 encoded_image._encodedWidth = kWidth / 2;
1964 encoded_image._encodedHeight = kHeight / 2;
1965 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1966 }
asapersson4ee70462016-10-31 04:05:12 -07001967
1968 // Histograms are updated when the statistics_proxy_ is deleted.
1969 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001970 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1971 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1972 EXPECT_METRIC_EQ(
1973 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
1974 0));
asapersson4ee70462016-10-31 04:05:12 -07001975 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01001976 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1977 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001978}
1979
1980TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001981 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1982 // Configure two streams.
1983 VideoEncoderConfig config;
1984 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1985 VideoStream stream1;
1986 stream1.width = kWidth / 2;
1987 stream1.height = kHeight / 2;
1988 VideoStream stream2;
1989 stream2.width = kWidth;
1990 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001991 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001992
1993 const int64_t kMaxEncodedFrameWindowMs = 800;
1994 const int kFps = 20;
1995 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1996 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1997 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1998
1999 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002000 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002001 encoded_image._encodedWidth = kWidth / 2;
2002 encoded_image._encodedHeight = kHeight / 2;
2003 for (int i = 0; i < kMinSamples; ++i) {
2004 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002005 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2006 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002007 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002008 }
asapersson4ee70462016-10-31 04:05:12 -07002009
2010 // Histograms are updated when the statistics_proxy_ is deleted.
2011 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002012 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2013 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2014 EXPECT_METRIC_EQ(
2015 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2016 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002017 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002018 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2019 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2020 EXPECT_METRIC_EQ(
2021 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2022 1));
asapersson4ee70462016-10-31 04:05:12 -07002023}
2024
2025TEST_F(SendStatisticsProxyTest,
2026 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02002027 SendStatisticsProxy::AdaptationSteps cpu_counts;
2028 SendStatisticsProxy::AdaptationSteps quality_counts;
2029 quality_counts.num_resolution_reductions = absl::nullopt;
2030 statistics_proxy_->OnAdaptationChanged(
2031 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2032 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002033 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002034 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002035 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002036 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002037
2038 // Histograms are updated when the statistics_proxy_ is deleted.
2039 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002040 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002041 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002042 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2043 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002044}
2045
2046TEST_F(SendStatisticsProxyTest,
2047 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02002048 SendStatisticsProxy::AdaptationSteps cpu_counts;
2049 SendStatisticsProxy::AdaptationSteps quality_counts;
2050 quality_counts.num_resolution_reductions = 0;
2051 statistics_proxy_->OnAdaptationChanged(
2052 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2053 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002054 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002055 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002056 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002057 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002058
2059 // Histograms are updated when the statistics_proxy_ is deleted.
2060 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002061 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002062 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002063 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2064 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002065 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002066 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2067 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002068}
2069
2070TEST_F(SendStatisticsProxyTest,
2071 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2072 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02002073 SendStatisticsProxy::AdaptationSteps cpu_counts;
2074 SendStatisticsProxy::AdaptationSteps quality_counts;
2075 quality_counts.num_resolution_reductions = kDownscales;
2076 statistics_proxy_->OnAdaptationChanged(
2077 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2078 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002079 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002080 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002081 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002082 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002083 // Histograms are updated when the statistics_proxy_ is deleted.
2084 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002085 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002086 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002087 EXPECT_METRIC_EQ(
2088 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2089 100));
asapersson4ee70462016-10-31 04:05:12 -07002090 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002091 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2092 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2093 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002094 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2095 kDownscales));
2096}
2097
2098TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2099 // Initially false.
2100 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002101
Åsa Perssonaa329e72017-12-15 15:54:44 +01002102 // Configure two streams.
2103 VideoEncoderConfig config;
2104 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002105 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002106 VideoStream stream1;
2107 stream1.width = kWidth / 2;
2108 stream1.height = kHeight / 2;
2109 VideoStream stream2;
2110 stream2.width = kWidth;
2111 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002112 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002113
Åsa Perssonaa329e72017-12-15 15:54:44 +01002114 // One stream encoded.
2115 EncodedImage encoded_image;
2116 encoded_image._encodedWidth = kWidth / 2;
2117 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002118
2119 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02002120 SendStatisticsProxy::AdaptationSteps cpu_counts;
2121 SendStatisticsProxy::AdaptationSteps quality_counts;
2122 quality_counts.num_resolution_reductions = 1;
2123 statistics_proxy_->OnAdaptationChanged(
2124 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2125 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002126 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2127 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002128
2129 // Adapt up.
2130 quality_counts.num_resolution_reductions = 0;
2131 statistics_proxy_->OnAdaptationChanged(
2132 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2133 quality_counts);
2134 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2135 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2136
2137 // Bw disabled one layer.
2138 VideoCodec codec;
2139 codec.numberOfSimulcastStreams = 2;
2140 codec.simulcastStream[0].active = true;
2141 codec.simulcastStream[1].active = true;
2142 VideoBitrateAllocation allocation;
2143 // Some positive bitrate only on the second stream.
2144 allocation.SetBitrate(1, 0, 10000);
2145 allocation.set_bw_limited(true);
2146 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2147 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002148}
2149
asapersson66d4b372016-12-19 06:50:53 -08002150TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2151 // Initially zero.
2152 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2153
2154 const int kBitrate = 100000;
2155 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2156 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2157
2158 statistics_proxy_->OnSetEncoderTargetRate(0);
2159 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2160}
2161
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002162TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002163 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002164 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2165 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002166 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002167 // From RtcpStatisticsCallback.
2168 RtcpStatistics rtcp_stats;
2169 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002170 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002171
2172 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002173 uint32_t total = 0;
2174 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002175 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002176 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002177
2178 // From FrameCountObserver.
2179 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002180 FrameCounts frame_counts;
2181 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002182 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002183
2184 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2185 EXPECT_TRUE(stats.substreams.empty());
2186}
2187
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002188TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2189 static const int kEncodedWidth = 123;
2190 static const int kEncodedHeight = 81;
2191 EncodedImage encoded_image;
2192 encoded_image._encodedWidth = kEncodedWidth;
2193 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002194 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002195
kjellander02b3d272016-04-20 05:05:54 -07002196 CodecSpecificInfo codec_info;
2197 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002198
kjellander02b3d272016-04-20 05:05:54 -07002199 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002200 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002201 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002202
2203 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002204 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2205 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2206 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2207 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002208
2209 // Forward almost to timeout, this should not have removed stats.
2210 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2211 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002212 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2213 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002214
2215 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2216 // resolution still times out (no global timeout for all stats).
2217 RtcpStatistics rtcp_statistics;
2218 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2219 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2220
2221 // Report stats for second SSRC to make sure it's not outdated along with the
2222 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002223 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002224
2225 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2226 // reported, but substream 1 should.
2227 fake_clock_.AdvanceTimeMilliseconds(1);
2228 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002229 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2230 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2231 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2232 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002233}
2234
Peter Boström20f3f942015-05-15 11:33:39 +02002235TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2236 static const int kEncodedWidth = 123;
2237 static const int kEncodedHeight = 81;
2238 EncodedImage encoded_image;
2239 encoded_image._encodedWidth = kEncodedWidth;
2240 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002241 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002242
kjellander02b3d272016-04-20 05:05:54 -07002243 CodecSpecificInfo codec_info;
2244 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002245
kjellander02b3d272016-04-20 05:05:54 -07002246 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002247 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002248 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002249
2250 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2251 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2252 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2253 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2254 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2255 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2256}
2257
2258TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002259 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002260 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2261 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2262 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2263
2264 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2265
2266 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002267 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002268 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002269 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002270 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2271 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2272 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2273}
2274
sprang07fb9be2016-02-24 07:55:00 -08002275TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2276 RtcpPacketTypeCounterObserver* proxy =
2277 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2278 RtcpPacketTypeCounter counters;
2279 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2280 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2281 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2282
2283 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2284
2285 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2286 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2287 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2288 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2289 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2290
2291 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2292 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2293
2294 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002295 VideoEncoderConfig config;
2296 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002297 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002298
Ying Wangef3998f2019-12-09 13:06:53 +01002299 EXPECT_METRIC_EQ(
2300 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2301 EXPECT_METRIC_EQ(
2302 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2303 EXPECT_METRIC_EQ(
2304 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2305 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2306 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002307
2308 const int kRate = 60 * 2; // Packets per minute with two streams.
2309
Ying Wangef3998f2019-12-09 13:06:53 +01002310 EXPECT_METRIC_EQ(
2311 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2312 1 * kRate));
2313 EXPECT_METRIC_EQ(
2314 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2315 2 * kRate));
2316 EXPECT_METRIC_EQ(
2317 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2318 3 * kRate));
2319 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002320 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2321 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002322
2323 // New start time but same counter values.
2324 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2325 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2326
2327 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2328
2329 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2330 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2331 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2332 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2333 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2334
2335 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2336 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2337
2338 SetUp(); // Reset stats proxy also causes histograms to be reported.
2339
Ying Wangef3998f2019-12-09 13:06:53 +01002340 EXPECT_METRIC_EQ(
2341 1, metrics::NumSamples(
2342 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2343 EXPECT_METRIC_EQ(1,
2344 metrics::NumSamples(
2345 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2346 EXPECT_METRIC_EQ(1,
2347 metrics::NumSamples(
2348 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2349 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002350 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002351 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2352
Ying Wangef3998f2019-12-09 13:06:53 +01002353 EXPECT_METRIC_EQ(
2354 1,
2355 metrics::NumEvents(
2356 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2357 EXPECT_METRIC_EQ(
2358 1,
2359 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2360 2 * kRate));
2361 EXPECT_METRIC_EQ(
2362 1,
2363 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2364 3 * kRate));
2365 EXPECT_METRIC_EQ(
2366 1, metrics::NumEvents(
2367 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2368 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002369}
2370
asaperssona6a699a2016-11-25 03:52:46 -08002371TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2372 statistics_proxy_.reset(
2373 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2374 VideoEncoderConfig::ContentType::kRealtimeVideo));
2375
2376 StreamDataCountersCallback* proxy =
2377 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2378 StreamDataCounters counters;
2379 proxy->DataCountersUpdated(counters, kFirstSsrc);
2380 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2381
2382 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
2383 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
2384}
2385
2386TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2387 statistics_proxy_.reset(
2388 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2389 VideoEncoderConfig::ContentType::kRealtimeVideo));
2390
2391 StreamDataCountersCallback* proxy =
2392 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002393 StreamDataCounters counters;
2394 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002395
asapersson93e1e232017-02-06 05:18:35 -08002396 const int kMinRequiredPeriodSamples = 8;
2397 const int kPeriodIntervalMs = 2000;
2398 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2399 counters.transmitted.packets += 20;
2400 counters.transmitted.header_bytes += 500;
2401 counters.transmitted.padding_bytes += 1000;
2402 counters.transmitted.payload_bytes += 2000;
2403 counters.retransmitted.packets += 2;
2404 counters.retransmitted.header_bytes += 25;
2405 counters.retransmitted.padding_bytes += 100;
2406 counters.retransmitted.payload_bytes += 250;
2407 counters.fec = counters.retransmitted;
2408 rtx_counters.transmitted = counters.transmitted;
2409 // Advance one interval and update counters.
2410 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2411 proxy->DataCountersUpdated(counters, kFirstSsrc);
2412 proxy->DataCountersUpdated(counters, kSecondSsrc);
2413 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2414 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2415 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2416 }
asaperssona6a699a2016-11-25 03:52:46 -08002417
asaperssona6a699a2016-11-25 03:52:46 -08002418 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002419 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002420 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2421 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002422 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002423 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2424 EXPECT_METRIC_EQ(1,
2425 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002426 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002427 EXPECT_METRIC_EQ(1,
2428 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2429 EXPECT_METRIC_EQ(
2430 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002431 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002432 EXPECT_METRIC_EQ(
2433 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2434 EXPECT_METRIC_EQ(
2435 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002436 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002437 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2438 EXPECT_METRIC_EQ(1,
2439 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002440 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002441 EXPECT_METRIC_EQ(
2442 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2443 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002444 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002445}
2446
Erik Språng22c2b482016-03-01 09:40:42 +01002447TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2448 StreamDataCountersCallback* proxy =
2449 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2450 StreamDataCounters counters;
2451 StreamDataCounters rtx_counters;
2452 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002453
asapersson93e1e232017-02-06 05:18:35 -08002454 const int kMinRequiredPeriodSamples = 8;
2455 const int kPeriodIntervalMs = 2000;
2456 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2457 counters.transmitted.packets += 20;
2458 counters.transmitted.header_bytes += 500;
2459 counters.transmitted.padding_bytes += 1000;
2460 counters.transmitted.payload_bytes += 2000;
2461 counters.retransmitted.packets += 2;
2462 counters.retransmitted.header_bytes += 25;
2463 counters.retransmitted.padding_bytes += 100;
2464 counters.retransmitted.payload_bytes += 250;
2465 counters.fec = counters.retransmitted;
2466 rtx_counters.transmitted = counters.transmitted;
2467 // Advance one interval and update counters.
2468 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2469 proxy->DataCountersUpdated(counters, kFirstSsrc);
2470 proxy->DataCountersUpdated(counters, kSecondSsrc);
2471 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2472 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2473 }
Erik Språng22c2b482016-03-01 09:40:42 +01002474
2475 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002476 VideoEncoderConfig config;
2477 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002478 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002479
asapersson93e1e232017-02-06 05:18:35 -08002480 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002481 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2482 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002483 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002484 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2485 EXPECT_METRIC_EQ(1,
2486 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002487 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002488 EXPECT_METRIC_EQ(1,
2489 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2490 EXPECT_METRIC_EQ(
2491 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002492 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002493 EXPECT_METRIC_EQ(
2494 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2495 EXPECT_METRIC_EQ(
2496 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002497 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002498 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2499 EXPECT_METRIC_EQ(1,
2500 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002501 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002502 EXPECT_METRIC_EQ(
2503 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2504 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002505 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002506
asapersson93e1e232017-02-06 05:18:35 -08002507 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002508 // Double counter values, this should result in the same counts as before but
2509 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002510 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2511 counters.transmitted.packets += 20;
2512 counters.transmitted.header_bytes += 500;
2513 counters.transmitted.padding_bytes += 1000;
2514 counters.transmitted.payload_bytes += 2000;
2515 counters.retransmitted.packets += 2;
2516 counters.retransmitted.header_bytes += 25;
2517 counters.retransmitted.padding_bytes += 100;
2518 counters.retransmitted.payload_bytes += 250;
2519 counters.fec = counters.retransmitted;
2520 rtx_counters.transmitted = counters.transmitted;
2521 // Advance one interval and update counters.
2522 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2523 proxy->DataCountersUpdated(counters, kFirstSsrc);
2524 proxy->DataCountersUpdated(counters, kSecondSsrc);
2525 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2526 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2527 }
Erik Språng22c2b482016-03-01 09:40:42 +01002528
asapersson93e1e232017-02-06 05:18:35 -08002529 // Reset stats proxy also causes histograms to be reported.
2530 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002531
asapersson93e1e232017-02-06 05:18:35 -08002532 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002533 EXPECT_METRIC_EQ(
2534 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2535 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002536 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2537 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002538 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002539 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002540 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2541 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002542 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002543 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2544 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2545 EXPECT_METRIC_EQ(
2546 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2547 12));
asapersson93e1e232017-02-06 05:18:35 -08002548 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002549 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2550 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2551 EXPECT_METRIC_EQ(
2552 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2553 16));
asapersson93e1e232017-02-06 05:18:35 -08002554 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002555 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002556 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002557 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2558 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002559 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002560 EXPECT_METRIC_EQ(
2561 1, metrics::NumSamples(
2562 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2563 EXPECT_METRIC_EQ(
2564 1, metrics::NumEvents(
2565 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002566}
Erik Språng22c2b482016-03-01 09:40:42 +01002567
asapersson93e1e232017-02-06 05:18:35 -08002568TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2569 StreamDataCountersCallback* proxy =
2570 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2571 StreamDataCounters counters;
2572 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002573
asapersson93e1e232017-02-06 05:18:35 -08002574 const int kMinRequiredPeriodSamples = 8;
2575 const int kPeriodIntervalMs = 2000;
2576 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2577 counters.transmitted.packets += 20;
2578 counters.transmitted.header_bytes += 500;
2579 counters.transmitted.payload_bytes += 2000;
2580 counters.fec = counters.retransmitted;
2581 // Advance one interval and update counters.
2582 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2583 proxy->DataCountersUpdated(counters, kFirstSsrc);
2584 }
2585
2586 // RTX enabled. No data sent over RTX.
2587 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002588 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2589 EXPECT_METRIC_EQ(1,
2590 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002591}
2592
2593TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2594 VideoSendStream::Config config(nullptr);
2595 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2596 statistics_proxy_.reset(new SendStatisticsProxy(
2597 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2598
2599 StreamDataCountersCallback* proxy =
2600 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2601 StreamDataCounters counters;
2602
2603 const int kMinRequiredPeriodSamples = 8;
2604 const int kPeriodIntervalMs = 2000;
2605 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2606 counters.transmitted.packets += 20;
2607 counters.transmitted.header_bytes += 500;
2608 counters.transmitted.payload_bytes += 2000;
2609 counters.fec = counters.retransmitted;
2610 // Advance one interval and update counters.
2611 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2612 proxy->DataCountersUpdated(counters, kFirstSsrc);
2613 }
2614
2615 // RTX not enabled.
2616 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002617 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002618}
2619
2620TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2621 StreamDataCountersCallback* proxy =
2622 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2623 StreamDataCounters counters;
2624 StreamDataCounters rtx_counters;
2625
2626 const int kMinRequiredPeriodSamples = 8;
2627 const int kPeriodIntervalMs = 2000;
2628 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2629 counters.transmitted.packets += 20;
2630 counters.transmitted.header_bytes += 500;
2631 counters.transmitted.payload_bytes += 2000;
2632 // Advance one interval and update counters.
2633 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2634 proxy->DataCountersUpdated(counters, kFirstSsrc);
2635 }
2636
2637 // FEC enabled. No FEC data sent.
2638 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002639 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2640 EXPECT_METRIC_EQ(1,
2641 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002642}
2643
2644TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2645 VideoSendStream::Config config(nullptr);
2646 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2647 statistics_proxy_.reset(new SendStatisticsProxy(
2648 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2649
2650 StreamDataCountersCallback* proxy =
2651 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2652 StreamDataCounters counters;
2653
2654 const int kMinRequiredPeriodSamples = 8;
2655 const int kPeriodIntervalMs = 2000;
2656 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2657 counters.transmitted.packets += 20;
2658 counters.transmitted.header_bytes += 500;
2659 counters.transmitted.payload_bytes += 2000;
2660 counters.fec = counters.retransmitted;
2661 // Advance one interval and update counters.
2662 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2663 proxy->DataCountersUpdated(counters, kFirstSsrc);
2664 }
2665
2666 // FEC not enabled.
2667 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002668 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002669}
2670
asapersson8d75ac72017-09-15 06:41:15 -07002671TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002672 const std::string kName = "encoderName";
2673 statistics_proxy_->OnEncoderImplementationChanged(kName);
2674 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002675}
2676
Sergey Silkinbb081a62018-09-04 18:34:22 +02002677TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2678 static const int kEncodedWidth = 123;
2679 static const int kEncodedHeight = 81;
2680 EncodedImage encoded_image;
2681 encoded_image._encodedWidth = kEncodedWidth;
2682 encoded_image._encodedHeight = kEncodedHeight;
2683 encoded_image.SetSpatialIndex(0);
2684
2685 CodecSpecificInfo codec_info;
2686 codec_info.codecType = kVideoCodecVP9;
2687
2688 // For first picture, it is expected that low layer updates resolution.
2689 codec_info.codecSpecific.VP9.end_of_picture = false;
2690 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2691 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2692 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2693 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2694
2695 // Top layer updates resolution.
2696 encoded_image._encodedWidth = kEncodedWidth * 2;
2697 encoded_image._encodedHeight = kEncodedHeight * 2;
2698 codec_info.codecSpecific.VP9.end_of_picture = true;
2699 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2700 stats = statistics_proxy_->GetStats();
2701 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2702 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2703
2704 // Low layer of next frame doesn't update resolution.
2705 encoded_image._encodedWidth = kEncodedWidth;
2706 encoded_image._encodedHeight = kEncodedHeight;
2707 codec_info.codecSpecific.VP9.end_of_picture = false;
2708 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2709 stats = statistics_proxy_->GetStats();
2710 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2711 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2712}
2713
asapersson8d75ac72017-09-15 06:41:15 -07002714class ForcedFallbackTest : public SendStatisticsProxyTest {
2715 public:
2716 explicit ForcedFallbackTest(const std::string& field_trials)
2717 : SendStatisticsProxyTest(field_trials) {
2718 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002719 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002720 encoded_image_._encodedWidth = kWidth;
2721 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002722 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002723 }
2724
2725 ~ForcedFallbackTest() override {}
2726
2727 protected:
2728 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002729 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2730
asapersson8d75ac72017-09-15 06:41:15 -07002731 // First frame is not updating stats, insert initial frame.
2732 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2733 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2734 }
2735 for (int i = 0; i < num_frames; ++i) {
2736 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2737 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2738 }
2739 // Add frame to include last time interval.
2740 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2741 }
2742
2743 EncodedImage encoded_image_;
2744 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002745 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002746 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2747 const int kFrameIntervalMs = 1000;
2748 const int kMinFrames = 20; // Min run time 20 sec.
2749};
2750
2751class ForcedFallbackDisabled : public ForcedFallbackTest {
2752 public:
2753 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002754 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2755 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002756};
2757
2758class ForcedFallbackEnabled : public ForcedFallbackTest {
2759 public:
2760 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002761 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2762 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002763};
2764
2765TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2766 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2767 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002768 EXPECT_METRIC_EQ(0,
2769 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2770 EXPECT_METRIC_EQ(
2771 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002772}
2773
2774TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2775 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002776 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002777 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002778 EXPECT_METRIC_EQ(1,
2779 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2780 EXPECT_METRIC_EQ(
2781 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2782 EXPECT_METRIC_EQ(
2783 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2784 EXPECT_METRIC_EQ(
2785 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002786}
2787
2788TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2789 codec_info_.codecType = kVideoCodecVP9;
2790 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2791 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002792 EXPECT_METRIC_EQ(0,
2793 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2794 EXPECT_METRIC_EQ(
2795 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002796}
2797
2798TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2799 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2800 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2801 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002802 EXPECT_METRIC_EQ(0,
2803 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2804 EXPECT_METRIC_EQ(
2805 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002806}
2807
2808TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002809 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002810 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2811 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002812 EXPECT_METRIC_EQ(0,
2813 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2814 EXPECT_METRIC_EQ(
2815 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002816}
2817
2818TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2819 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2820 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002821 EXPECT_METRIC_EQ(0,
2822 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2823 EXPECT_METRIC_EQ(
2824 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002825}
2826
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002827TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2828 InsertEncodedFrames(1, kFrameIntervalMs);
2829 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2830}
2831
2832TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2833 InsertEncodedFrames(1, kFrameIntervalMs);
2834 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2835}
2836
2837TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002838 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002839 InsertEncodedFrames(1, kFrameIntervalMs);
2840 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2841}
2842
2843TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2844 encoded_image_._encodedWidth = kWidth + 1;
2845 InsertEncodedFrames(1, kFrameIntervalMs);
2846 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2847}
2848
2849TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002850 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002851 InsertEncodedFrames(1, kFrameIntervalMs);
2852 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2853}
2854
2855TEST_F(ForcedFallbackDisabled,
2856 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2857 encoded_image_._encodedWidth = kWidth + 1;
2858 statistics_proxy_->OnMinPixelLimitReached();
2859 InsertEncodedFrames(1, kFrameIntervalMs);
2860 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2861}
2862
asapersson8d75ac72017-09-15 06:41:15 -07002863TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2864 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002865 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002866 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002867 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002868 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002869 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002870 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002871
2872 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002873 EXPECT_METRIC_EQ(1,
2874 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2875 EXPECT_METRIC_EQ(
2876 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2877 EXPECT_METRIC_EQ(
2878 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2879 EXPECT_METRIC_EQ(
2880 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002881}
2882
2883TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2884 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2885 const int kMaxFrameDiffMs = 2000;
2886
2887 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2888 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002889 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002890 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002891 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002892 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002893 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002894 InsertEncodedFrames(20, 1000);
2895 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2896 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002897 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002898 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002899 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002900 EXPECT_TRUE(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);
asapersson8d75ac72017-09-15 06:41:15 -07002904
2905 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002906 EXPECT_METRIC_EQ(1,
2907 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2908 EXPECT_METRIC_EQ(
2909 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2910 EXPECT_METRIC_EQ(
2911 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2912 EXPECT_METRIC_EQ(
2913 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002914}
2915
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002916TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2917 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002918 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002919 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2920
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002921 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002922 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002923 EXPECT_METRIC_EQ(0,
2924 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2925 EXPECT_METRIC_EQ(
2926 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002927}
2928
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002929TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2930 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002931 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002932 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2933
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002934 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002935 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002936 EXPECT_METRIC_EQ(1,
2937 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2938 EXPECT_METRIC_EQ(
2939 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002940}
2941
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002942} // namespace webrtc