blob: aad9b3d16b0555aceb28582e82fa5dcbd7ad4641 [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}();
Evan Shrubsoledff79252020-04-16 11:34:32 +020048
49const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
50 true);
51const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
52 true,
53 false);
54const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
55 false,
56 true);
57const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
asapersson5265fed2016-04-18 02:58:47 -070058} // namespace
sprang07fb9be2016-02-24 07:55:00 -080059
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000060class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000061 public:
asapersson8d75ac72017-09-15 06:41:15 -070062 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
63 explicit SendStatisticsProxyTest(const std::string& field_trials)
64 : override_field_trials_(field_trials),
65 fake_clock_(1234),
66 config_(GetTestConfig()),
67 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070068 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000069 virtual ~SendStatisticsProxyTest() {}
70
71 protected:
72 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070073 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080074 statistics_proxy_.reset(new SendStatisticsProxy(
75 &fake_clock_, GetTestConfig(),
76 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000077 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010078 for (const auto& ssrc : config_.rtp.ssrcs) {
79 expected_.substreams[ssrc].type =
80 VideoSendStream::StreamStats::StreamType::kMedia;
81 }
82 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
83 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
84 expected_.substreams[ssrc].type =
85 VideoSendStream::StreamStats::StreamType::kRtx;
86 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
87 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000088 }
89
90 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070091 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080092 config.rtp.ssrcs.push_back(kFirstSsrc);
93 config.rtp.ssrcs.push_back(kSecondSsrc);
94 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
95 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070096 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000097 return config;
98 }
99
asaperssona6a699a2016-11-25 03:52:46 -0800100 VideoSendStream::Config GetTestConfigWithFlexFec() {
101 VideoSendStream::Config config(nullptr);
102 config.rtp.ssrcs.push_back(kFirstSsrc);
103 config.rtp.ssrcs.push_back(kSecondSsrc);
104 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
105 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -0800106 config.rtp.flexfec.payload_type = 50;
107 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +0100108 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -0800109 return config;
110 }
111
112 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
113 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
114 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
115 stats.substreams.find(ssrc);
116 EXPECT_NE(it, stats.substreams.end());
117 return it->second;
118 }
119
asapersson66d4b372016-12-19 06:50:53 -0800120 void UpdateDataCounters(uint32_t ssrc) {
121 StreamDataCountersCallback* proxy =
122 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
123 StreamDataCounters counters;
124 proxy->DataCountersUpdated(counters, ssrc);
125 }
126
sprang@webrtc.org09315702014-02-07 12:06:29 +0000127 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000128 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
129 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000130 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000131 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
133 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000134 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000135 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000136 it != one.substreams.end(); ++it) {
137 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
138 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000139 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000140 const VideoSendStream::StreamStats& a = it->second;
141 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142
Henrik Boströmf45ca372020-03-24 13:30:50 +0100143 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000144 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
145 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000146 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000147 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
148 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000150 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
151 b.rtp_stats.transmitted.payload_bytes);
152 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
153 b.rtp_stats.transmitted.header_bytes);
154 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
155 b.rtp_stats.transmitted.padding_bytes);
156 EXPECT_EQ(a.rtp_stats.transmitted.packets,
157 b.rtp_stats.transmitted.packets);
158 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
159 b.rtp_stats.retransmitted.packets);
160 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000161
162 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700163 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
164 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
165 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000166 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
167 }
168 }
169
asapersson8d75ac72017-09-15 06:41:15 -0700170 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000171 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800172 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173 VideoSendStream::Config config_;
174 int avg_delay_ms_;
175 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000176 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000177 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
178 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000179};
180
181TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
182 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700183 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000184 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000185
186 // Add statistics with some arbitrary, but unique, numbers.
187 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700188 ssrc_stats.rtcp_stats.packets_lost = offset;
189 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000190 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
191 ssrc_stats.rtcp_stats.jitter = offset + 3;
192 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
193 }
asapersson35151f32016-05-02 23:44:01 -0700194 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000195 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000196
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000197 // Add statistics with some arbitrary, but unique, numbers.
198 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700199 ssrc_stats.rtcp_stats.packets_lost = offset;
200 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000201 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
202 ssrc_stats.rtcp_stats.jitter = offset + 3;
203 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
204 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000205 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000206 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000207}
208
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000209TEST_F(SendStatisticsProxyTest, Suspended) {
210 // Verify that the value is false by default.
211 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
212
213 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200214 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000215 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
216
217 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200218 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000219 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
220}
221
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000222TEST_F(SendStatisticsProxyTest, FrameCounts) {
223 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700224 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000225 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000226 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
227 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000228 FrameCounts frame_counts;
229 frame_counts.key_frames = offset;
230 frame_counts.delta_frames = offset + 1;
231 stats.frame_counts = frame_counts;
232 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000233 }
asapersson35151f32016-05-02 23:44:01 -0700234 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000235 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000236 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
237 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000238 FrameCounts frame_counts;
239 frame_counts.key_frames = offset;
240 frame_counts.delta_frames = offset + 1;
241 stats.frame_counts = frame_counts;
242 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000243 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000244
245 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000246 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000247}
248
249TEST_F(SendStatisticsProxyTest, DataCounters) {
250 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700251 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000252 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
253 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000254 size_t offset = ssrc * sizeof(StreamDataCounters);
255 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000256 counters.transmitted.payload_bytes = offset;
257 counters.transmitted.header_bytes = offset + 1;
258 counters.fec.packets = offset_uint32 + 2;
259 counters.transmitted.padding_bytes = offset + 3;
260 counters.retransmitted.packets = offset_uint32 + 4;
261 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000262 callback->DataCountersUpdated(counters, ssrc);
263 }
asapersson35151f32016-05-02 23:44:01 -0700264 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000265 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
266 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000267 size_t offset = ssrc * sizeof(StreamDataCounters);
268 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000269 counters.transmitted.payload_bytes = offset;
270 counters.transmitted.header_bytes = offset + 1;
271 counters.fec.packets = offset_uint32 + 2;
272 counters.transmitted.padding_bytes = offset + 3;
273 counters.retransmitted.packets = offset_uint32 + 4;
274 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000275 callback->DataCountersUpdated(counters, ssrc);
276 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000277
278 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000279 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000280}
281
282TEST_F(SendStatisticsProxyTest, Bitrate) {
283 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700284 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700285 uint32_t total;
286 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000287 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700288 total = ssrc;
289 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000290 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700291 expected_.substreams[ssrc].total_bitrate_bps = total;
292 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000293 }
asapersson35151f32016-05-02 23:44:01 -0700294 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700295 uint32_t total;
296 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000297 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700298 total = ssrc;
299 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000300 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700301 expected_.substreams[ssrc].total_bitrate_bps = total;
302 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000303 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000304
305 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000306 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000307}
308
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000309TEST_F(SendStatisticsProxyTest, SendSideDelay) {
310 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700311 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000312 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
313 // stream.
314 int avg_delay_ms = ssrc;
315 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200316 uint64_t total_packet_send_delay_ms = ssrc + 2;
317 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
318 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000319 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
320 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200321 expected_.substreams[ssrc].total_packet_send_delay_ms =
322 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000323 }
asapersson35151f32016-05-02 23:44:01 -0700324 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000325 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
326 // stream.
327 int avg_delay_ms = ssrc;
328 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200329 uint64_t total_packet_send_delay_ms = ssrc + 2;
330 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
331 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000332 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
333 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200334 expected_.substreams[ssrc].total_packet_send_delay_ms =
335 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000336 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000337 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000338 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000339}
340
Peter Boströme4499152016-02-05 11:13:28 +0100341TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800342 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200343 int encode_usage_percent = 80;
344 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
345 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800346
347 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
348 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200349 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800350}
351
Henrik Boström5684af52019-04-02 15:05:21 +0200352TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
353 const int kEncodeUsagePercent = 0; // Don't care for this test.
354 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
355 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
356 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
357 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
358 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
359}
360
sakal43536c32016-10-24 01:46:43 -0700361TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
362 EncodedImage encoded_image;
363 CodecSpecificInfo codec_info;
364 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
365 for (uint32_t i = 1; i <= 3; ++i) {
366 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
367 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
368 }
369}
370
sakal87da4042016-10-31 06:53:47 -0700371TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
372 EncodedImage encoded_image;
373 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200374 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700375 encoded_image.qp_ = 3;
376 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100377 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700378 encoded_image.qp_ = 127;
379 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100380 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700381}
382
383TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
384 EncodedImage encoded_image;
385 CodecSpecificInfo codec_info;
386 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200387 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700388 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200389 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700390}
391
Henrik Boström23aff9b2019-05-20 15:15:38 +0200392TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
393 const uint32_t kTargetBytesPerSecond = 100000;
394 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
395 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
396
397 EncodedImage encoded_image;
398 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
399 // On the first frame we don't know the frame rate yet, calculation yields
400 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
401 // increment by a full |kTargetBytesPerSecond|.
402 EXPECT_EQ(kTargetBytesPerSecond,
403 statistics_proxy_->GetStats().total_encoded_bytes_target);
404}
405
406TEST_F(SendStatisticsProxyTest,
407 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
408 const uint32_t kTargetBytesPerSecond = 100000;
409 const int kInterframeDelayMs = 100;
410
411 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
412 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
413 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
414 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
415 // this test can stop relying on rtc::ScopedFakeClock.
416 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100417 fake_global_clock.SetTime(
418 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200419
420 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
421 EncodedImage encoded_image;
422
423 // First frame
424 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
425 uint64_t first_total_encoded_bytes_target =
426 statistics_proxy_->GetStats().total_encoded_bytes_target;
427 // Second frame
428 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100429 fake_global_clock.SetTime(
430 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200431 encoded_image.SetTimestamp(encoded_image.Timestamp() +
432 90 * kInterframeDelayMs);
433 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
434
435 auto stats = statistics_proxy_->GetStats();
436 // By the time the second frame arrives, one frame has previously arrived
437 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
438 // the second frame's arrival should be 10 FPS.
439 uint64_t delta_encoded_bytes_target =
440 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
441 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
442}
443
asapersson09f05612017-05-15 23:40:18 -0700444TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200445 VideoAdaptationCounters cpu_counts;
446 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700447 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700448 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200449 cpu_counts.fps_adaptations = 1;
450 cpu_counts.resolution_adaptations = 0;
451 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Niels Möller213618e2018-07-24 09:29:58 +0200452 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200453 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200454 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700455 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700456 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200457 cpu_counts.fps_adaptations = 0;
458 cpu_counts.resolution_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +0200459 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200460 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200461 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700462 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700463 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200464 cpu_counts.fps_adaptations = 1;
465 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
466 kResolutionScalingDisabled);
Niels Möller213618e2018-07-24 09:29:58 +0200467 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200468 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200469 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700470 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700471 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200472 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
473 kScalingDisabled);
Niels Möller213618e2018-07-24 09:29:58 +0200474 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200475 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200476 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700477 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
478 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
479}
480
481TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200482 VideoAdaptationCounters cpu_counts;
483 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700484 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
485 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200486 quality_counts.fps_adaptations = 1;
487 quality_counts.resolution_adaptations = 0;
488 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Niels Möller213618e2018-07-24 09:29:58 +0200489 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200490 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200491 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700492 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
493 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200494 quality_counts.fps_adaptations = 0;
495 quality_counts.resolution_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +0200496 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200497 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200498 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700499 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
500 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200501 quality_counts.fps_adaptations = 1;
502 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
503 kResolutionScalingDisabled);
Niels Möller213618e2018-07-24 09:29:58 +0200504 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200505 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200506 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700507 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
508 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200509 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
510 kScalingDisabled);
Niels Möller213618e2018-07-24 09:29:58 +0200511 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +0200512 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +0200513 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700514 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
515 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
516}
517
518TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200519 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
520 VideoAdaptationCounters cpu_counts;
521 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700522 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
523
Evan Shrubsoledff79252020-04-16 11:34:32 +0200524 cpu_counts.resolution_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +0200525 statistics_proxy_->OnAdaptationChanged(
526 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
527 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700528 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700529 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
530 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
531
Evan Shrubsoledff79252020-04-16 11:34:32 +0200532 cpu_counts.resolution_adaptations = 2;
Niels Möller213618e2018-07-24 09:29:58 +0200533 statistics_proxy_->OnAdaptationChanged(
534 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
535 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700536 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
537 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700538 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700539 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700540}
541
asapersson09f05612017-05-15 23:40:18 -0700542TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200543 VideoAdaptationCounters cpu_counts;
544 VideoAdaptationCounters quality_counts;
545 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700546 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
547
Evan Shrubsoledff79252020-04-16 11:34:32 +0200548 quality_counts.fps_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +0200549 statistics_proxy_->OnAdaptationChanged(
550 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
551 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700552 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
553 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700554 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
555
Evan Shrubsoledff79252020-04-16 11:34:32 +0200556 quality_counts.fps_adaptations = 0;
Niels Möller213618e2018-07-24 09:29:58 +0200557 statistics_proxy_->OnAdaptationChanged(
558 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
559 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700560 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700561 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700562 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
563 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700564}
565
Evan Shrubsoledff79252020-04-16 11:34:32 +0200566TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
567 VideoAdaptationCounters cpu_counts;
568 VideoAdaptationCounters quality_counts;
569 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
570 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
571 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
572
573 quality_counts.resolution_adaptations = 1;
574 statistics_proxy_->OnAdaptationChanged(
575 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
576 quality_counts);
577 quality_counts.fps_adaptations = 1;
578 statistics_proxy_->OnAdaptationChanged(
579 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
580 quality_counts);
581 cpu_counts.resolution_adaptations = 1;
582 statistics_proxy_->OnAdaptationChanged(
583 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
584 quality_counts);
585 cpu_counts.fps_adaptations = 1;
586 statistics_proxy_->OnAdaptationChanged(
587 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
588 quality_counts);
589 // We have 1 fps and resolution reduction for both cpu and quality
590 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
591 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
592 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
593 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
594 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
595 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
596
597 // Disable quality scaling. Expect quality scaling not limited.
598 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
599 kScalingDisabled);
600 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
601 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
602 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
603 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
604 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
605 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
606
607 // Disable framerate scaling.
608 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
609 kFramerateScalingDisabled);
610 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
611 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
612 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
613 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
614 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
615 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
616
617 // Disable resolution scaling.
618 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
619 kResolutionScalingDisabled);
620 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
621 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
622 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
623 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
624 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
625 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
626
627 // Enable all
628 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
629 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
630 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
631 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
632 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
633 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
634 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
635}
636
asapersson09f05612017-05-15 23:40:18 -0700637TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700638 // First RTP packet sent.
639 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700640 // Min runtime has passed.
641 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
642 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100643 EXPECT_METRIC_EQ(
644 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
645 EXPECT_METRIC_EQ(
646 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700647}
648
649TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700650 // First RTP packet sent.
651 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700652 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200653 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700654 // Min runtime has not passed.
655 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
656 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100657 EXPECT_METRIC_EQ(
658 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
659 EXPECT_METRIC_EQ(
660 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700661}
662
asapersson09f05612017-05-15 23:40:18 -0700663TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700664 // First RTP packet sent.
665 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700666 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200667 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700668 // Min runtime has passed.
669 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
670 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100671 EXPECT_METRIC_EQ(
672 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
673 EXPECT_METRIC_EQ(
674 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
675 EXPECT_METRIC_EQ(
676 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
677 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700678 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
679}
680
681TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700682 // First RTP packet sent.
683 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700684 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200685 VideoAdaptationCounters cpu_counts;
686 VideoAdaptationCounters quality_counts;
687 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700688 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200689 statistics_proxy_->OnAdaptationChanged(
690 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
691 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700692 fake_clock_.AdvanceTimeMilliseconds(10000);
693 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100694 EXPECT_METRIC_EQ(
695 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
696 EXPECT_METRIC_EQ(
697 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700698}
699
Åsa Persson875841d2018-01-08 08:49:53 +0100700TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
701 // First RTP packet sent.
702 UpdateDataCounters(kFirstSsrc);
703 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200704 VideoAdaptationCounters cpu_counts;
705 VideoAdaptationCounters quality_counts;
706 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100707 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200708 statistics_proxy_->OnAdaptationChanged(
709 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
710 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100711 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
712 fake_clock_.AdvanceTimeMilliseconds(10000);
713 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100714 EXPECT_METRIC_EQ(
715 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
716 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100717 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
718}
719
720TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
721 // First RTP packet sent.
722 UpdateDataCounters(kFirstSsrc);
723 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200724 VideoAdaptationCounters cpu_counts;
725 VideoAdaptationCounters quality_counts;
726 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100727 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200728 quality_counts.resolution_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +0200729 statistics_proxy_->OnAdaptationChanged(
730 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
731 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100732 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200733 quality_counts.resolution_adaptations = 2;
Niels Möller213618e2018-07-24 09:29:58 +0200734 statistics_proxy_->OnAdaptationChanged(
735 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
736 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100737 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200738 quality_counts.resolution_adaptations = 3;
Niels Möller213618e2018-07-24 09:29:58 +0200739 statistics_proxy_->OnAdaptationChanged(
740 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
741 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100742 fake_clock_.AdvanceTimeMilliseconds(10000);
743 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100744 EXPECT_METRIC_EQ(
745 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
746 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100747 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
748}
749
750TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
751 // First RTP packet sent.
752 UpdateDataCounters(kFirstSsrc);
753 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200754 VideoAdaptationCounters cpu_counts;
755 VideoAdaptationCounters quality_counts;
756 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100757 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200758 statistics_proxy_->OnAdaptationChanged(
759 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
760 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100761 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
762 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
763 fake_clock_.AdvanceTimeMilliseconds(10000);
764 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100765 EXPECT_METRIC_EQ(
766 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
767 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100768 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
769}
770
771TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
772 // First RTP packet sent.
773 UpdateDataCounters(kFirstSsrc);
774 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200775 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
776 VideoAdaptationCounters cpu_counts;
777 VideoAdaptationCounters quality_counts;
778 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100779 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200780 quality_counts.resolution_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +0200781 statistics_proxy_->OnAdaptationChanged(
782 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
783 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100784 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200785 quality_counts.resolution_adaptations = 2;
Niels Möller213618e2018-07-24 09:29:58 +0200786 statistics_proxy_->OnAdaptationChanged(
787 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
788 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100789 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200790 quality_counts.resolution_adaptations = 3;
Niels Möller213618e2018-07-24 09:29:58 +0200791 statistics_proxy_->OnAdaptationChanged(
792 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
793 quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200794 quality_counts.fps_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +0200795 statistics_proxy_->OnAdaptationChanged(
796 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
797 quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200798 quality_counts.fps_adaptations = 0;
Niels Möller213618e2018-07-24 09:29:58 +0200799 statistics_proxy_->OnAdaptationChanged(
800 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
801 quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200802 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Niels Möller213618e2018-07-24 09:29:58 +0200803 statistics_proxy_->OnAdaptationChanged(
804 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
805 quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200806 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Niels Möller213618e2018-07-24 09:29:58 +0200807 statistics_proxy_->OnAdaptationChanged(
808 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
809 quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200810 quality_counts.resolution_adaptations = 0;
Niels Möller213618e2018-07-24 09:29:58 +0200811 statistics_proxy_->OnAdaptationChanged(
812 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
813 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100814
815 fake_clock_.AdvanceTimeMilliseconds(10000);
816 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100817 EXPECT_METRIC_EQ(
818 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
819 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100820 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
821}
822
asapersson6eca98b2017-04-04 23:40:50 -0700823TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700824 // First RTP packet sent.
825 UpdateDataCounters(kFirstSsrc);
826
asapersson09f05612017-05-15 23:40:18 -0700827 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200828 VideoAdaptationCounters cpu_counts;
829 VideoAdaptationCounters quality_counts;
830 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
831 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700832 fake_clock_.AdvanceTimeMilliseconds(10000);
833
asapersson09f05612017-05-15 23:40:18 -0700834 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700835 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200836 quality_counts.fps_adaptations = 0;
837 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
838 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700839 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200840 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
841 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700842 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200843 statistics_proxy_->OnAdaptationChanged(
844 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
845 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700846 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200847 statistics_proxy_->OnAdaptationChanged(
848 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
849 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700850
asapersson09f05612017-05-15 23:40:18 -0700851 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200852 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
853 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700854 fake_clock_.AdvanceTimeMilliseconds(30000);
855
asapersson09f05612017-05-15 23:40:18 -0700856 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700857 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200858 quality_counts.resolution_adaptations = 0;
859 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
860 kFramerateScalingDisabled);
Niels Möller213618e2018-07-24 09:29:58 +0200861 statistics_proxy_->OnAdaptationChanged(
862 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
863 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700864 fake_clock_.AdvanceTimeMilliseconds(10000);
865
asapersson09f05612017-05-15 23:40:18 -0700866 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200867 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
868 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700869 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200870 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
871 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700872 fake_clock_.AdvanceTimeMilliseconds(20000);
873
asapersson0944a802017-04-07 00:57:58 -0700874 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700875 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100876 EXPECT_METRIC_EQ(
877 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
878 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700879 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
880}
881
asapersson0944a802017-04-07 00:57:58 -0700882TEST_F(SendStatisticsProxyTest,
883 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
884 // First RTP packet sent.
885 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700886
asapersson0944a802017-04-07 00:57:58 -0700887 // Suspend and resume video.
888 statistics_proxy_->OnSuspendChange(true);
889 fake_clock_.AdvanceTimeMilliseconds(5000);
890 statistics_proxy_->OnSuspendChange(false);
891
892 // Min runtime has passed but scaling not enabled.
893 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
894 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100895 EXPECT_METRIC_EQ(
896 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
897 EXPECT_METRIC_EQ(
898 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700899}
900
901TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
902 // First RTP packet sent.
903 UpdateDataCounters(kFirstSsrc);
904
asapersson09f05612017-05-15 23:40:18 -0700905 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200906 VideoAdaptationCounters cpu_counts;
907 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700908 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200909 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700910 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200911 statistics_proxy_->OnAdaptationChanged(
912 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
913 quality_counts);
914 statistics_proxy_->OnAdaptationChanged(
915 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
916 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700917
918 // Suspend and resume video.
919 statistics_proxy_->OnSuspendChange(true);
920 fake_clock_.AdvanceTimeMilliseconds(30000);
921 statistics_proxy_->OnSuspendChange(false);
922
923 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200924 statistics_proxy_->OnAdaptationChanged(
925 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
926 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700927 fake_clock_.AdvanceTimeMilliseconds(10000);
928
929 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
930 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100931 EXPECT_METRIC_EQ(
932 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
933 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700934 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
935}
936
937TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
938 // First RTP packet sent.
939 UpdateDataCounters(kFirstSsrc);
940
941 // Video not suspended.
942 statistics_proxy_->OnSuspendChange(false);
943 fake_clock_.AdvanceTimeMilliseconds(30000);
944
asapersson09f05612017-05-15 23:40:18 -0700945 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200946 VideoAdaptationCounters cpu_counts;
947 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700948 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200949 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700950 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200951 statistics_proxy_->OnAdaptationChanged(
952 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
953 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700954
955 // Video not suspended, stats time already started.
956 statistics_proxy_->OnSuspendChange(false);
957 fake_clock_.AdvanceTimeMilliseconds(10000);
958
asapersson09f05612017-05-15 23:40:18 -0700959 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200960 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
961 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -0700962 fake_clock_.AdvanceTimeMilliseconds(30000);
963
964 // Suspend and resume video, stats time not started when scaling not enabled.
965 statistics_proxy_->OnSuspendChange(true);
966 fake_clock_.AdvanceTimeMilliseconds(30000);
967 statistics_proxy_->OnSuspendChange(false);
968 fake_clock_.AdvanceTimeMilliseconds(30000);
969
asapersson09f05612017-05-15 23:40:18 -0700970 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700971 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200972 cpu_counts.fps_adaptations = 0;
973 cpu_counts.resolution_adaptations = 0;
974 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700975 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200976 statistics_proxy_->OnAdaptationChanged(
977 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
978 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700979
980 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
981 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100982 EXPECT_METRIC_EQ(
983 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
984 EXPECT_METRIC_EQ(
985 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700986}
987
988TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
989 // First RTP packet sent.
990 UpdateDataCounters(kFirstSsrc);
991
992 // Video suspended.
993 statistics_proxy_->OnSuspendChange(true);
994
asapersson09f05612017-05-15 23:40:18 -0700995 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200996 VideoAdaptationCounters cpu_counts;
997 VideoAdaptationCounters quality_counts;
998 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700999 fake_clock_.AdvanceTimeMilliseconds(10000);
1000
1001 // Resume video, stats time started.
1002 // Adapt changes: 1, elapsed time: 10 sec.
1003 statistics_proxy_->OnSuspendChange(false);
1004 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001005 statistics_proxy_->OnAdaptationChanged(
1006 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1007 quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001008
1009 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1010 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001011 EXPECT_METRIC_EQ(
1012 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1013 EXPECT_METRIC_EQ(
1014 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001015}
1016
1017TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001018 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001019 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001020 VideoAdaptationCounters cpu_counts;
1021 VideoAdaptationCounters quality_counts;
1022 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001023 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001024 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001025
asapersson0944a802017-04-07 00:57:58 -07001026 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001027 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001028 statistics_proxy_->OnAdaptationChanged(
1029 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1030 quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001031 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001032
asapersson0944a802017-04-07 00:57:58 -07001033 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001034 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001035 EXPECT_METRIC_EQ(
1036 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1037 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001038 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1039}
1040
1041TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001042 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001043 VideoAdaptationCounters cpu_counts;
1044 VideoAdaptationCounters quality_counts;
1045 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001046 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001047 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1048 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001049
1050 // Send first packet, scaling disabled.
1051 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001052 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001053 fake_clock_.AdvanceTimeMilliseconds(60000);
1054
asapersson09f05612017-05-15 23:40:18 -07001055 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001056 cpu_counts.resolution_adaptations = 0;
1057 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1058 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001059 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001060 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001061
asapersson0944a802017-04-07 00:57:58 -07001062 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001063 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001064 statistics_proxy_->OnAdaptationChanged(
1065 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1066 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001067
asapersson0944a802017-04-07 00:57:58 -07001068 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001069 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001070 EXPECT_METRIC_EQ(
1071 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1072 EXPECT_METRIC_EQ(
1073 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001074}
1075
1076TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001077 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001078 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001079 VideoAdaptationCounters cpu_counts;
1080 VideoAdaptationCounters quality_counts;
1081 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1082 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001083
asapersson0944a802017-04-07 00:57:58 -07001084 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001085 statistics_proxy_->OnAdaptationChanged(
1086 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1087 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001088 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +02001089 statistics_proxy_->OnAdaptationChanged(
1090 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1091 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001092 fake_clock_.AdvanceTimeMilliseconds(9000);
1093
1094 // Switch content type, real-time stats should be updated.
1095 VideoEncoderConfig config;
1096 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001097 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001098 EXPECT_METRIC_EQ(
1099 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1100 EXPECT_METRIC_EQ(
1101 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1102 EXPECT_METRIC_EQ(
1103 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001104
asapersson0944a802017-04-07 00:57:58 -07001105 // First RTP packet sent, scaling enabled.
1106 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001107 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1108 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001109
asapersson0944a802017-04-07 00:57:58 -07001110 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001111 statistics_proxy_->OnAdaptationChanged(
1112 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1113 quality_counts);
1114 statistics_proxy_->OnAdaptationChanged(
1115 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1116 quality_counts);
1117 statistics_proxy_->OnAdaptationChanged(
1118 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1119 quality_counts);
1120 statistics_proxy_->OnAdaptationChanged(
1121 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1122 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001123 fake_clock_.AdvanceTimeMilliseconds(120000);
1124
1125 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001126 EXPECT_METRIC_EQ(1,
1127 metrics::NumSamples(
1128 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1129 EXPECT_METRIC_EQ(
1130 1, metrics::NumEvents(
1131 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1132 EXPECT_METRIC_EQ(
1133 0, metrics::NumSamples(
1134 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001135}
1136
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001137TEST_F(SendStatisticsProxyTest,
1138 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001139 VideoAdaptationCounters cpu_counts;
1140 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001141
Evan Shrubsoledff79252020-04-16 11:34:32 +02001142 cpu_counts.resolution_adaptations = 1;
1143 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001144 statistics_proxy_->OnAdaptationChanged(
1145 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1146 quality_counts);
1147
1148 EXPECT_EQ(QualityLimitationReason::kCpu,
1149 statistics_proxy_->GetStats().quality_limitation_reason);
1150}
1151
1152TEST_F(SendStatisticsProxyTest,
1153 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001154 VideoAdaptationCounters cpu_counts;
1155 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001156
Evan Shrubsoledff79252020-04-16 11:34:32 +02001157 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001158
Evan Shrubsoledff79252020-04-16 11:34:32 +02001159 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001160 statistics_proxy_->OnAdaptationChanged(
1161 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1162 quality_counts);
1163
1164 EXPECT_EQ(QualityLimitationReason::kCpu,
1165 statistics_proxy_->GetStats().quality_limitation_reason);
1166}
1167
1168TEST_F(SendStatisticsProxyTest,
1169 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001170 VideoAdaptationCounters cpu_counts;
1171 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001172
Evan Shrubsoledff79252020-04-16 11:34:32 +02001173 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001174
Evan Shrubsoledff79252020-04-16 11:34:32 +02001175 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001176 statistics_proxy_->OnAdaptationChanged(
1177 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1178 quality_counts);
1179
1180 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1181 statistics_proxy_->GetStats().quality_limitation_reason);
1182}
1183
1184TEST_F(SendStatisticsProxyTest,
1185 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001186 VideoAdaptationCounters cpu_counts;
1187 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001188
Evan Shrubsoledff79252020-04-16 11:34:32 +02001189 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001190
Evan Shrubsoledff79252020-04-16 11:34:32 +02001191 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001192 statistics_proxy_->OnAdaptationChanged(
1193 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1194 quality_counts);
1195
1196 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1197 statistics_proxy_->GetStats().quality_limitation_reason);
1198}
1199
1200TEST_F(SendStatisticsProxyTest,
1201 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001202 VideoAdaptationCounters cpu_counts;
1203 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001204
Evan Shrubsoledff79252020-04-16 11:34:32 +02001205 cpu_counts.resolution_adaptations = 1;
1206 quality_counts.resolution_adaptations = 1;
1207 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001208
1209 // Even if the last adaptation reason is kCpu, if the counters indicate being
1210 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
1211 statistics_proxy_->OnAdaptationChanged(
1212 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1213 quality_counts);
1214
1215 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1216 statistics_proxy_->GetStats().quality_limitation_reason);
1217}
1218
1219TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001220 VideoAdaptationCounters cpu_counts;
1221 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001222
1223 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1224 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001225 cpu_counts.resolution_adaptations = 1;
1226 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001227 statistics_proxy_->OnAdaptationChanged(
1228 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1229 quality_counts);
1230 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001231 cpu_counts.resolution_adaptations = 0;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001232 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +02001233 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001234 quality_counts);
1235
1236 EXPECT_EQ(QualityLimitationReason::kNone,
1237 statistics_proxy_->GetStats().quality_limitation_reason);
1238}
1239
1240TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001241 VideoAdaptationCounters cpu_counts;
1242 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001243
Evan Shrubsoledff79252020-04-16 11:34:32 +02001244 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001245 // Not limited for 3000 ms
1246 fake_clock_.AdvanceTimeMilliseconds(3000);
1247 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001248 cpu_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001249 statistics_proxy_->OnAdaptationChanged(
1250 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1251 quality_counts);
1252 fake_clock_.AdvanceTimeMilliseconds(2000);
1253 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001254 cpu_counts.resolution_adaptations = 0;
1255 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001256 statistics_proxy_->OnAdaptationChanged(
1257 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1258 quality_counts);
1259 fake_clock_.AdvanceTimeMilliseconds(1000);
1260 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001261 cpu_counts.resolution_adaptations = 1;
1262 quality_counts.resolution_adaptations = 0;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001263 statistics_proxy_->OnAdaptationChanged(
1264 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1265 quality_counts);
1266 fake_clock_.AdvanceTimeMilliseconds(2000);
1267
1268 auto quality_limitation_durations_ms =
1269 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1270
1271 EXPECT_EQ(3000,
1272 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1273 EXPECT_EQ(4000,
1274 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1275 EXPECT_EQ(
1276 1000,
1277 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1278 EXPECT_EQ(0,
1279 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1280}
1281
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001282TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1283 EXPECT_EQ(
1284 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1285}
1286
1287TEST_F(SendStatisticsProxyTest,
1288 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1289 VideoCodec codec;
1290 VideoBitrateAllocation allocation;
1291 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1292 EXPECT_EQ(
1293 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1294}
1295
1296TEST_F(SendStatisticsProxyTest,
1297 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1298 VideoCodec codec;
1299 codec.simulcastStream[0].active = true;
1300 codec.simulcastStream[1].active = true;
1301 codec.simulcastStream[2].active = true;
1302 VideoBitrateAllocation allocation;
1303 allocation.SetBitrate(0, 0, 100);
1304 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1305 EXPECT_EQ(
1306 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1307}
1308
1309TEST_F(SendStatisticsProxyTest,
1310 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1311 VideoCodec codec;
1312 codec.simulcastStream[0].active = true;
1313 codec.simulcastStream[1].active = true;
1314 codec.simulcastStream[2].active = true;
1315 VideoBitrateAllocation allocation;
1316 allocation.SetBitrate(0, 0, 100);
1317 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1318 allocation.SetBitrate(1, 0, 100);
1319 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1320 EXPECT_EQ(
1321 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1322}
1323
1324TEST_F(SendStatisticsProxyTest,
1325 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1326 VideoCodec codec;
1327 codec.simulcastStream[0].active = true;
1328 VideoBitrateAllocation allocation;
1329 allocation.SetBitrate(0, 0, 100);
1330 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1331 // Layer 0 got more bandwidth, but still only one layer on
1332 allocation.SetBitrate(0, 0, 200);
1333 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1334 EXPECT_EQ(
1335 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1336}
1337
1338TEST_F(SendStatisticsProxyTest,
1339 QualityLimitationResolutionChangesWithTogglingLayers) {
1340 VideoCodec codec;
1341 codec.simulcastStream[0].active = true;
1342 codec.simulcastStream[1].active = true;
1343 codec.simulcastStream[2].active = true;
1344 VideoBitrateAllocation allocation;
1345 allocation.SetBitrate(0, 0, 100);
1346 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1347 EXPECT_EQ(
1348 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1349 allocation.SetBitrate(1, 0, 300);
1350 allocation.SetBitrate(2, 0, 500);
1351 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1352 EXPECT_EQ(
1353 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1354 // Layer 2 off
1355 allocation.SetBitrate(2, 0, 0);
1356 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1357 EXPECT_EQ(
1358 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1359 // Layer 2 back on
1360 allocation.SetBitrate(2, 0, 500);
1361 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1362 EXPECT_EQ(
1363 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1364 allocation.SetBitrate(0, 0, 0);
1365 allocation.SetBitrate(1, 0, 0);
1366 allocation.SetBitrate(2, 0, 0);
1367 // All layers off
1368 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1369 EXPECT_EQ(
1370 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1371}
1372
1373TEST_F(SendStatisticsProxyTest,
1374 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1375 VideoCodec codec;
1376 // 3 layers
1377 codec.simulcastStream[0].active = true;
1378 codec.simulcastStream[1].active = true;
1379 codec.simulcastStream[2].active = true;
1380 VideoBitrateAllocation allocation;
1381 allocation.SetBitrate(0, 0, 500);
1382 allocation.SetBitrate(1, 0, 500);
1383 allocation.SetBitrate(2, 0, 500);
1384 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1385 EXPECT_EQ(
1386 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1387
1388 // Down to one layer now, triggered by a config change
1389 codec.numberOfSimulcastStreams = 1;
1390 codec.simulcastStream[1].active = false;
1391 codec.simulcastStream[2].active = false;
1392 allocation.SetBitrate(0, 0, 100);
1393 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1394 EXPECT_EQ(
1395 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1396
1397 // Up to 3 layers again.
1398 codec.numberOfSimulcastStreams = 3;
1399 codec.simulcastStream[1].active = true;
1400 codec.simulcastStream[2].active = true;
1401 allocation.SetBitrate(0, 0, 500);
1402 allocation.SetBitrate(1, 0, 500);
1403 allocation.SetBitrate(2, 0, 500);
1404 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1405 EXPECT_EQ(
1406 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1407}
1408
1409TEST_F(SendStatisticsProxyTest,
1410 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1411 VideoCodec codec;
1412 codec.simulcastStream[0].active = true;
1413 codec.spatialLayers[0].active = true;
1414 codec.spatialLayers[1].active = true;
1415 codec.spatialLayers[2].active = true;
1416 VideoBitrateAllocation allocation;
1417 allocation.SetBitrate(0, 0, 500);
1418 allocation.SetBitrate(1, 0, 500);
1419 allocation.SetBitrate(2, 0, 500);
1420 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1421 EXPECT_EQ(
1422 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1423
1424 // Down to one layer now, triggered by a config change
1425 codec.spatialLayers[1].active = false;
1426 codec.spatialLayers[2].active = false;
1427 allocation.SetBitrate(0, 0, 100);
1428 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1429 EXPECT_EQ(
1430 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1431
1432 // Up to 3 layers again.
1433 codec.spatialLayers[1].active = true;
1434 codec.spatialLayers[2].active = true;
1435 allocation.SetBitrate(0, 0, 500);
1436 allocation.SetBitrate(1, 0, 500);
1437 allocation.SetBitrate(2, 0, 500);
1438 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1439 EXPECT_EQ(
1440 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1441}
1442
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001443TEST_F(SendStatisticsProxyTest,
1444 QualityLimitationReasonsAreCorrectForContentType) {
1445 // Realtime case.
1446 // Configure two streams.
1447 VideoEncoderConfig config;
1448 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1449 config.number_of_streams = 2;
1450 VideoStream stream1;
1451 stream1.width = kWidth / 2;
1452 stream1.height = kHeight / 2;
1453 VideoStream stream2;
1454 stream2.width = kWidth;
1455 stream2.height = kHeight;
1456 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1457 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1458 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1459 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1460 QualityLimitationReason::kNone);
1461 // Bw disabled one layer.
1462 VideoCodec codec;
1463 codec.numberOfSimulcastStreams = 2;
1464 codec.simulcastStream[0].active = true;
1465 codec.simulcastStream[1].active = true;
1466 VideoBitrateAllocation allocation;
1467 // Some positive bitrate only on the first stream.
1468 allocation.SetBitrate(0, 0, 10000);
1469 allocation.SetBitrate(1, 0, 0);
1470 allocation.set_bw_limited(true);
1471 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1472 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1473 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1474 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1475 QualityLimitationReason::kBandwidth);
1476 // Bw enabled all layers.
1477 allocation.SetBitrate(1, 0, 10000);
1478 allocation.set_bw_limited(false);
1479 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1480 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1481 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1482 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1483 QualityLimitationReason::kNone);
1484
1485 // Screencast case
1486 // Configure two streams.
1487 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1488 config.number_of_streams = 2;
1489 stream1.width = kWidth;
1490 stream1.height = kHeight;
1491 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1492 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1493 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1494 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1495 QualityLimitationReason::kNone);
1496 // Bw disabled one layer.
1497 // Some positive bitrate only on the second stream.
1498 allocation.SetBitrate(0, 0, 10000);
1499 allocation.SetBitrate(1, 0, 0);
1500 allocation.set_bw_limited(true);
1501 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1502 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1503 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1504 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1505 QualityLimitationReason::kBandwidth);
1506 // Bw enabled all layers.
1507 allocation.SetBitrate(1, 0, 10000);
1508 allocation.set_bw_limited(false);
1509 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1510 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1511 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1512 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1513 QualityLimitationReason::kNone);
1514}
1515
asapersson59bac1a2016-01-07 23:36:00 -08001516TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001517 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001518 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1519
Pera48ddb72016-09-29 11:48:50 +02001520 // No switch, stats should not be updated.
1521 VideoEncoderConfig config;
1522 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001523 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001524 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001525
1526 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001527 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001528 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001529 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001530}
1531
asapersson320e45a2016-11-29 01:40:35 -08001532TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1533 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1534 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001535
asapersson320e45a2016-11-29 01:40:35 -08001536 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001537 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1538 EXPECT_METRIC_EQ(
1539 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1540 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1541 EXPECT_METRIC_EQ(
1542 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001543}
1544
1545TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001546 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001547 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001548 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1549 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1550 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001551 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001552
1553 // Not enough samples, stats should not be updated.
1554 for (int i = 0; i < kMinSamples - 1; ++i) {
1555 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001556 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001557 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1558 }
Åsa Persson0122e842017-10-16 12:19:23 +02001559 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001560 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1561 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001562
1563 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001564 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001565 for (int i = 0; i < kMinSamples; ++i) {
1566 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001567 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001568 encoded_image._encodedWidth = kWidth;
1569 encoded_image._encodedHeight = kHeight;
1570 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1571 encoded_image._encodedWidth = kWidth / 2;
1572 encoded_image._encodedHeight = kHeight / 2;
1573 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1574 }
1575
asapersson320e45a2016-11-29 01:40:35 -08001576 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001577 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1578 EXPECT_METRIC_EQ(
1579 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1580 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1581 EXPECT_METRIC_EQ(
1582 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001583}
1584
1585TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1586 const int kFps = 20;
1587 const int kMinPeriodicSamples = 6;
1588 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1589 for (int i = 0; i <= frames; ++i) {
1590 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1591 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1592 }
1593 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001594 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1595 EXPECT_METRIC_EQ(
1596 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001597}
1598
1599TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1600 EncodedImage encoded_image;
1601 const int kFps = 20;
1602 const int kMinPeriodicSamples = 6;
1603 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001604 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001605 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001606 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001607 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1608 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001609 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1610 }
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
1617TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1618 const int kFps = 20;
1619 const int kSuspendTimeMs = 10000;
1620 const int kMinPeriodicSamples = 6;
1621 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1622 for (int i = 0; i < frames; ++i) {
1623 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1624 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1625 }
1626 // Suspend.
1627 statistics_proxy_->OnSuspendChange(true);
1628 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1629
1630 for (int i = 0; i < frames; ++i) {
1631 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1632 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1633 }
1634 // Suspended time interval should not affect the framerate.
1635 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001636 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1637 EXPECT_METRIC_EQ(
1638 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001639}
1640
1641TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1642 EncodedImage encoded_image;
1643 const int kFps = 20;
1644 const int kSuspendTimeMs = 10000;
1645 const int kMinPeriodicSamples = 6;
1646 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001647 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001648 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001649 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001650 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1651 }
1652 // Suspend.
1653 statistics_proxy_->OnSuspendChange(true);
1654 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1655
Åsa Persson0122e842017-10-16 12:19:23 +02001656 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001657 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001658 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001659 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1660 }
1661 // Suspended time interval should not affect the framerate.
1662 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001663 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1664 EXPECT_METRIC_EQ(
1665 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001666}
1667
asaperssonf4e44af2017-04-19 02:01:06 -07001668TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001669 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1670 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001671
1672 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1673 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1674
1675 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001676 EXPECT_METRIC_EQ(
1677 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001678}
1679
1680TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001681 VideoAdaptationCounters cpu_counts;
1682 VideoAdaptationCounters quality_counts;
1683 cpu_counts.resolution_adaptations = 0;
1684 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001685
perkj803d97f2016-11-01 11:45:46 -07001686 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1687 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1688
Evan Shrubsoledff79252020-04-16 11:34:32 +02001689 cpu_counts.resolution_adaptations = 1;
Niels Möller213618e2018-07-24 09:29:58 +02001690 statistics_proxy_->OnAdaptationChanged(
1691 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1692 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001693
1694 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1695 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1696
1697 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001698 EXPECT_METRIC_EQ(
1699 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1700 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001701 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1702}
1703
asapersson4374a092016-07-27 00:39:09 -07001704TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1705 const int64_t kTimeSec = 3;
1706 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1707 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001708 EXPECT_METRIC_EQ(
1709 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1710 EXPECT_METRIC_EQ(
1711 1,
1712 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001713}
1714
1715TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1716 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1717 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001718 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001719}
1720
asapersson66d4b372016-12-19 06:50:53 -08001721TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1722 // First RTP packet sent.
1723 UpdateDataCounters(kFirstSsrc);
1724
1725 // Min runtime has passed.
1726 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1727 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001728 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1729 EXPECT_METRIC_EQ(1,
1730 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001731}
1732
1733TEST_F(SendStatisticsProxyTest,
1734 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1735 // First RTP packet sent.
1736 UpdateDataCounters(kFirstSsrc);
1737
1738 // Min runtime has not passed.
1739 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1740 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001741 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1742 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001743}
1744
1745TEST_F(SendStatisticsProxyTest,
1746 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1747 // First RTP packet not sent.
1748 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1749 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001750 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001751}
1752
1753TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1754 // First RTP packet sent and min runtime passed.
1755 UpdateDataCounters(kFirstSsrc);
1756
1757 // No change. Video: 10000 ms, paused: 0 ms (0%).
1758 statistics_proxy_->OnSetEncoderTargetRate(50000);
1759 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1760 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1761
1762 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001763 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1764 EXPECT_METRIC_EQ(1,
1765 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1766 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1767 EXPECT_METRIC_EQ(1,
1768 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001769}
1770
1771TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1772 // First RTP packet sent and min runtime passed.
1773 UpdateDataCounters(kFirstSsrc);
1774
1775 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1776 statistics_proxy_->OnSetEncoderTargetRate(50000);
1777 fake_clock_.AdvanceTimeMilliseconds(7000);
1778 statistics_proxy_->OnSetEncoderTargetRate(0);
1779 fake_clock_.AdvanceTimeMilliseconds(3000);
1780 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1781
1782 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001783 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1784 EXPECT_METRIC_EQ(1,
1785 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1786 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1787 EXPECT_METRIC_EQ(1,
1788 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001789}
1790
1791TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1792 // First RTP packet sent.
1793 UpdateDataCounters(kFirstSsrc);
1794
1795 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1796 statistics_proxy_->OnSetEncoderTargetRate(0);
1797 fake_clock_.AdvanceTimeMilliseconds(1000);
1798 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1799 fake_clock_.AdvanceTimeMilliseconds(7000);
1800 statistics_proxy_->OnSetEncoderTargetRate(60000);
1801 fake_clock_.AdvanceTimeMilliseconds(3000);
1802 statistics_proxy_->OnSetEncoderTargetRate(0);
1803 fake_clock_.AdvanceTimeMilliseconds(250);
1804 statistics_proxy_->OnSetEncoderTargetRate(0);
1805 fake_clock_.AdvanceTimeMilliseconds(750);
1806 statistics_proxy_->OnSetEncoderTargetRate(60000);
1807 fake_clock_.AdvanceTimeMilliseconds(5000);
1808 statistics_proxy_->OnSetEncoderTargetRate(50000);
1809 fake_clock_.AdvanceTimeMilliseconds(4000);
1810 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1811
1812 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001813 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1814 EXPECT_METRIC_EQ(1,
1815 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1816 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1817 EXPECT_METRIC_EQ(1,
1818 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001819}
1820
1821TEST_F(SendStatisticsProxyTest,
1822 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1823 // First RTP packet sent.
1824 UpdateDataCounters(kFirstSsrc);
1825 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1826
1827 // Min runtime has not passed.
1828 statistics_proxy_->OnSetEncoderTargetRate(50000);
1829 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1830 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1831
1832 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001833 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001834}
1835
asapersson118ef002016-03-31 00:00:19 -07001836TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001837 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001838 CodecSpecificInfo codec_info;
1839 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001840
perkj803d97f2016-11-01 11:45:46 -07001841 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001842 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001843 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001844 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001845 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001846 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001847 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001848 }
1849 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001850 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1851 EXPECT_METRIC_EQ(
1852 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1853 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1854 EXPECT_METRIC_EQ(
1855 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001856}
1857
1858TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1859 VideoSendStream::Config config(nullptr);
1860 config.rtp.ssrcs.push_back(kFirstSsrc);
1861 statistics_proxy_.reset(new SendStatisticsProxy(
1862 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1863
asapersson118ef002016-03-31 00:00:19 -07001864 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001865 CodecSpecificInfo codec_info;
1866 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001867
perkj803d97f2016-11-01 11:45:46 -07001868 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001869 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001870 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001871 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001872 }
1873 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001874 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1875 EXPECT_METRIC_EQ(1,
1876 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001877}
1878
asapersson5265fed2016-04-18 02:58:47 -07001879TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001880 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001881 CodecSpecificInfo codec_info;
1882 codec_info.codecType = kVideoCodecVP9;
1883 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001884
perkj803d97f2016-11-01 11:45:46 -07001885 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001886 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001887 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001888 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001889 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001890 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001891 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001892 }
1893 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001894 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1895 EXPECT_METRIC_EQ(
1896 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1897 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1898 EXPECT_METRIC_EQ(
1899 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001900}
1901
1902TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1903 VideoSendStream::Config config(nullptr);
1904 config.rtp.ssrcs.push_back(kFirstSsrc);
1905 statistics_proxy_.reset(new SendStatisticsProxy(
1906 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1907
asapersson5265fed2016-04-18 02:58:47 -07001908 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001909 CodecSpecificInfo codec_info;
1910 codec_info.codecType = kVideoCodecVP9;
1911 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001912
perkj803d97f2016-11-01 11:45:46 -07001913 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001914 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001915 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001916 }
1917 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001918 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1919 EXPECT_METRIC_EQ(1,
1920 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001921}
1922
asapersson827cab32016-11-02 09:08:47 -07001923TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1924 EncodedImage encoded_image;
1925 CodecSpecificInfo codec_info;
1926 codec_info.codecType = kVideoCodecH264;
1927
1928 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001929 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001930 encoded_image.qp_ = kQpIdx0;
1931 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001932 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001933 encoded_image.qp_ = kQpIdx1;
1934 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001935 }
1936 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001937 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1938 EXPECT_METRIC_EQ(
1939 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1940 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1941 EXPECT_METRIC_EQ(
1942 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001943}
1944
asapersson4ee70462016-10-31 04:05:12 -07001945TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001946 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1947 // Configure one stream.
1948 VideoEncoderConfig config;
1949 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1950 VideoStream stream1;
1951 stream1.width = kWidth;
1952 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001953 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001954
1955 const int64_t kMaxEncodedFrameWindowMs = 800;
1956 const int kFps = 20;
1957 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1958 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1959 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1960
1961 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001962 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001963 encoded_image._encodedWidth = kWidth;
1964 encoded_image._encodedHeight = kHeight;
1965 for (int i = 0; i < kMinSamples; ++i) {
1966 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001967 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1968 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001969 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001970 }
asapersson4ee70462016-10-31 04:05:12 -07001971
1972 // Histograms are updated when the statistics_proxy_ is deleted.
1973 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001974 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1975 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1976 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_NoResolutionDisabled) {
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 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07002000 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002001 for (int i = 0; i < kMinSamples; ++i) {
2002 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002003 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2004 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002005 encoded_image._encodedWidth = kWidth;
2006 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07002007 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002008 encoded_image._encodedWidth = kWidth / 2;
2009 encoded_image._encodedHeight = kHeight / 2;
2010 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2011 }
asapersson4ee70462016-10-31 04:05:12 -07002012
2013 // Histograms are updated when the statistics_proxy_ is deleted.
2014 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002015 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2016 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2017 EXPECT_METRIC_EQ(
2018 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2019 0));
asapersson4ee70462016-10-31 04:05:12 -07002020 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002021 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2022 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002023}
2024
2025TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002026 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2027 // Configure two streams.
2028 VideoEncoderConfig config;
2029 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2030 VideoStream stream1;
2031 stream1.width = kWidth / 2;
2032 stream1.height = kHeight / 2;
2033 VideoStream stream2;
2034 stream2.width = kWidth;
2035 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002036 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002037
2038 const int64_t kMaxEncodedFrameWindowMs = 800;
2039 const int kFps = 20;
2040 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2041 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2042 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2043
2044 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002045 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002046 encoded_image._encodedWidth = kWidth / 2;
2047 encoded_image._encodedHeight = kHeight / 2;
2048 for (int i = 0; i < kMinSamples; ++i) {
2049 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002050 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2051 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002052 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002053 }
asapersson4ee70462016-10-31 04:05:12 -07002054
2055 // Histograms are updated when the statistics_proxy_ is deleted.
2056 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002057 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2058 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2059 EXPECT_METRIC_EQ(
2060 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2061 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002062 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002063 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2064 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2065 EXPECT_METRIC_EQ(
2066 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2067 1));
asapersson4ee70462016-10-31 04:05:12 -07002068}
2069
2070TEST_F(SendStatisticsProxyTest,
2071 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002072 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2073 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002074 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002075 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002076 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002077 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002078
2079 // Histograms are updated when the statistics_proxy_ is deleted.
2080 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002081 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002082 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002083 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2084 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002085}
2086
2087TEST_F(SendStatisticsProxyTest,
2088 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002089 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002090 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002091 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002092 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002093 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002094
2095 // Histograms are updated when the statistics_proxy_ is deleted.
2096 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002097 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002098 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002099 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2100 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002101 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002102 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2103 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002104}
2105
2106TEST_F(SendStatisticsProxyTest,
2107 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2108 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002109 VideoAdaptationCounters cpu_counts;
2110 VideoAdaptationCounters quality_counts;
2111 quality_counts.resolution_adaptations = kDownscales;
2112 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Niels Möller213618e2018-07-24 09:29:58 +02002113 statistics_proxy_->OnAdaptationChanged(
Evan Shrubsoledff79252020-04-16 11:34:32 +02002114 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
Niels Möller213618e2018-07-24 09:29:58 +02002115 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002116 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002117 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002118 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002119 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002120 // Histograms are updated when the statistics_proxy_ is deleted.
2121 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002122 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002123 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002124 EXPECT_METRIC_EQ(
2125 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2126 100));
asapersson4ee70462016-10-31 04:05:12 -07002127 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002128 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2129 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2130 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002131 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2132 kDownscales));
2133}
2134
2135TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2136 // Initially false.
2137 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002138
Åsa Perssonaa329e72017-12-15 15:54:44 +01002139 // Configure two streams.
2140 VideoEncoderConfig config;
2141 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002142 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002143 VideoStream stream1;
2144 stream1.width = kWidth / 2;
2145 stream1.height = kHeight / 2;
2146 VideoStream stream2;
2147 stream2.width = kWidth;
2148 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002149 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002150
Åsa Perssonaa329e72017-12-15 15:54:44 +01002151 // One stream encoded.
2152 EncodedImage encoded_image;
2153 encoded_image._encodedWidth = kWidth / 2;
2154 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002155
2156 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002157 VideoAdaptationCounters cpu_counts;
2158 VideoAdaptationCounters quality_counts;
2159 quality_counts.resolution_adaptations = 1;
2160 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2161 kFramerateScalingDisabled);
Niels Möller213618e2018-07-24 09:29:58 +02002162 statistics_proxy_->OnAdaptationChanged(
2163 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2164 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002165 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2166 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002167
2168 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002169 quality_counts.resolution_adaptations = 0;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002170 statistics_proxy_->OnAdaptationChanged(
2171 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2172 quality_counts);
2173 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2174 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2175
2176 // Bw disabled one layer.
2177 VideoCodec codec;
2178 codec.numberOfSimulcastStreams = 2;
2179 codec.simulcastStream[0].active = true;
2180 codec.simulcastStream[1].active = true;
2181 VideoBitrateAllocation allocation;
2182 // Some positive bitrate only on the second stream.
2183 allocation.SetBitrate(1, 0, 10000);
2184 allocation.set_bw_limited(true);
2185 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2186 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002187
2188 // Revert for the next test.
2189 allocation.set_bw_limited(false);
2190 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2191 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2192
2193 // Internal encoder scaler reduced resolution.
2194 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2195 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002196}
2197
asapersson66d4b372016-12-19 06:50:53 -08002198TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2199 // Initially zero.
2200 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2201
2202 const int kBitrate = 100000;
2203 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2204 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2205
2206 statistics_proxy_->OnSetEncoderTargetRate(0);
2207 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2208}
2209
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002210TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002211 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002212 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2213 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002214 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002215 // From RtcpStatisticsCallback.
2216 RtcpStatistics rtcp_stats;
2217 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002218 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002219
2220 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002221 uint32_t total = 0;
2222 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002223 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002224 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002225
2226 // From FrameCountObserver.
2227 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002228 FrameCounts frame_counts;
2229 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002230 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002231
2232 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2233 EXPECT_TRUE(stats.substreams.empty());
2234}
2235
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002236TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2237 static const int kEncodedWidth = 123;
2238 static const int kEncodedHeight = 81;
2239 EncodedImage encoded_image;
2240 encoded_image._encodedWidth = kEncodedWidth;
2241 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002242 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002243
kjellander02b3d272016-04-20 05:05:54 -07002244 CodecSpecificInfo codec_info;
2245 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002246
kjellander02b3d272016-04-20 05:05:54 -07002247 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002248 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002249 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002250
2251 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002252 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2253 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2254 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2255 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002256
2257 // Forward almost to timeout, this should not have removed stats.
2258 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2259 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002260 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2261 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002262
2263 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2264 // resolution still times out (no global timeout for all stats).
2265 RtcpStatistics rtcp_statistics;
2266 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2267 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2268
2269 // Report stats for second SSRC to make sure it's not outdated along with the
2270 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002271 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002272
2273 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2274 // reported, but substream 1 should.
2275 fake_clock_.AdvanceTimeMilliseconds(1);
2276 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002277 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2278 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2279 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2280 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002281}
2282
Peter Boström20f3f942015-05-15 11:33:39 +02002283TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2284 static const int kEncodedWidth = 123;
2285 static const int kEncodedHeight = 81;
2286 EncodedImage encoded_image;
2287 encoded_image._encodedWidth = kEncodedWidth;
2288 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002289 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002290
kjellander02b3d272016-04-20 05:05:54 -07002291 CodecSpecificInfo codec_info;
2292 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002293
kjellander02b3d272016-04-20 05:05:54 -07002294 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002295 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002296 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002297
2298 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2299 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2300 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2301 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2302 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2303 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2304}
2305
2306TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002307 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002308 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2309 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2310 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2311
2312 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2313
2314 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002315 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002316 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002317 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002318 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2319 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2320 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2321}
2322
sprang07fb9be2016-02-24 07:55:00 -08002323TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2324 RtcpPacketTypeCounterObserver* proxy =
2325 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2326 RtcpPacketTypeCounter counters;
2327 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2328 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2329 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2330
2331 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2332
2333 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2334 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2335 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2336 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2337 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2338
2339 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2340 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2341
2342 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002343 VideoEncoderConfig config;
2344 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002345 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002346
Ying Wangef3998f2019-12-09 13:06:53 +01002347 EXPECT_METRIC_EQ(
2348 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2349 EXPECT_METRIC_EQ(
2350 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2351 EXPECT_METRIC_EQ(
2352 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2353 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2354 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002355
2356 const int kRate = 60 * 2; // Packets per minute with two streams.
2357
Ying Wangef3998f2019-12-09 13:06:53 +01002358 EXPECT_METRIC_EQ(
2359 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2360 1 * kRate));
2361 EXPECT_METRIC_EQ(
2362 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2363 2 * kRate));
2364 EXPECT_METRIC_EQ(
2365 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2366 3 * kRate));
2367 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002368 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2369 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002370
2371 // New start time but same counter values.
2372 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2373 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2374
2375 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2376
2377 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2378 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2379 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2380 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2381 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2382
2383 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2384 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2385
2386 SetUp(); // Reset stats proxy also causes histograms to be reported.
2387
Ying Wangef3998f2019-12-09 13:06:53 +01002388 EXPECT_METRIC_EQ(
2389 1, metrics::NumSamples(
2390 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2391 EXPECT_METRIC_EQ(1,
2392 metrics::NumSamples(
2393 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2394 EXPECT_METRIC_EQ(1,
2395 metrics::NumSamples(
2396 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2397 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002398 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002399 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2400
Ying Wangef3998f2019-12-09 13:06:53 +01002401 EXPECT_METRIC_EQ(
2402 1,
2403 metrics::NumEvents(
2404 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2405 EXPECT_METRIC_EQ(
2406 1,
2407 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2408 2 * kRate));
2409 EXPECT_METRIC_EQ(
2410 1,
2411 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2412 3 * kRate));
2413 EXPECT_METRIC_EQ(
2414 1, metrics::NumEvents(
2415 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2416 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002417}
2418
Henrik Boströmf45ca372020-03-24 13:30:50 +01002419TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2420 StreamDataCountersCallback* proxy =
2421 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2422 StreamDataCounters counters;
2423 proxy->DataCountersUpdated(counters, kFirstSsrc);
2424 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2425
2426 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2427 VideoSendStream::StreamStats::StreamType::kRtx);
2428 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2429 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2430 VideoSendStream::StreamStats::StreamType::kRtx);
2431 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2432}
2433
asaperssona6a699a2016-11-25 03:52:46 -08002434TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2435 statistics_proxy_.reset(
2436 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2437 VideoEncoderConfig::ContentType::kRealtimeVideo));
2438
2439 StreamDataCountersCallback* proxy =
2440 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2441 StreamDataCounters counters;
2442 proxy->DataCountersUpdated(counters, kFirstSsrc);
2443 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2444
Henrik Boströmf45ca372020-03-24 13:30:50 +01002445 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2446 VideoSendStream::StreamStats::StreamType::kFlexfec);
2447 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2448 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2449 VideoSendStream::StreamStats::StreamType::kFlexfec);
2450 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002451}
2452
2453TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2454 statistics_proxy_.reset(
2455 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2456 VideoEncoderConfig::ContentType::kRealtimeVideo));
2457
2458 StreamDataCountersCallback* proxy =
2459 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002460 StreamDataCounters counters;
2461 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002462
asapersson93e1e232017-02-06 05:18:35 -08002463 const int kMinRequiredPeriodSamples = 8;
2464 const int kPeriodIntervalMs = 2000;
2465 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2466 counters.transmitted.packets += 20;
2467 counters.transmitted.header_bytes += 500;
2468 counters.transmitted.padding_bytes += 1000;
2469 counters.transmitted.payload_bytes += 2000;
2470 counters.retransmitted.packets += 2;
2471 counters.retransmitted.header_bytes += 25;
2472 counters.retransmitted.padding_bytes += 100;
2473 counters.retransmitted.payload_bytes += 250;
2474 counters.fec = counters.retransmitted;
2475 rtx_counters.transmitted = counters.transmitted;
2476 // Advance one interval and update counters.
2477 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2478 proxy->DataCountersUpdated(counters, kFirstSsrc);
2479 proxy->DataCountersUpdated(counters, kSecondSsrc);
2480 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2481 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2482 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2483 }
asaperssona6a699a2016-11-25 03:52:46 -08002484
asaperssona6a699a2016-11-25 03:52:46 -08002485 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002486 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002487 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2488 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002489 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002490 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2491 EXPECT_METRIC_EQ(1,
2492 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002493 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002494 EXPECT_METRIC_EQ(1,
2495 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2496 EXPECT_METRIC_EQ(
2497 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002498 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002499 EXPECT_METRIC_EQ(
2500 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2501 EXPECT_METRIC_EQ(
2502 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002503 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002504 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2505 EXPECT_METRIC_EQ(1,
2506 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002507 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002508 EXPECT_METRIC_EQ(
2509 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2510 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002511 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002512}
2513
Erik Språng22c2b482016-03-01 09:40:42 +01002514TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2515 StreamDataCountersCallback* proxy =
2516 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2517 StreamDataCounters counters;
2518 StreamDataCounters rtx_counters;
2519 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002520
asapersson93e1e232017-02-06 05:18:35 -08002521 const int kMinRequiredPeriodSamples = 8;
2522 const int kPeriodIntervalMs = 2000;
2523 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2524 counters.transmitted.packets += 20;
2525 counters.transmitted.header_bytes += 500;
2526 counters.transmitted.padding_bytes += 1000;
2527 counters.transmitted.payload_bytes += 2000;
2528 counters.retransmitted.packets += 2;
2529 counters.retransmitted.header_bytes += 25;
2530 counters.retransmitted.padding_bytes += 100;
2531 counters.retransmitted.payload_bytes += 250;
2532 counters.fec = counters.retransmitted;
2533 rtx_counters.transmitted = counters.transmitted;
2534 // Advance one interval and update counters.
2535 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2536 proxy->DataCountersUpdated(counters, kFirstSsrc);
2537 proxy->DataCountersUpdated(counters, kSecondSsrc);
2538 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2539 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2540 }
Erik Språng22c2b482016-03-01 09:40:42 +01002541
2542 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002543 VideoEncoderConfig config;
2544 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002545 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002546
asapersson93e1e232017-02-06 05:18:35 -08002547 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002548 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2549 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002550 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002551 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2552 EXPECT_METRIC_EQ(1,
2553 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002554 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002555 EXPECT_METRIC_EQ(1,
2556 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2557 EXPECT_METRIC_EQ(
2558 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002559 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002560 EXPECT_METRIC_EQ(
2561 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2562 EXPECT_METRIC_EQ(
2563 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002564 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002565 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2566 EXPECT_METRIC_EQ(1,
2567 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002568 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002569 EXPECT_METRIC_EQ(
2570 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2571 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002572 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002573
asapersson93e1e232017-02-06 05:18:35 -08002574 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002575 // Double counter values, this should result in the same counts as before but
2576 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002577 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2578 counters.transmitted.packets += 20;
2579 counters.transmitted.header_bytes += 500;
2580 counters.transmitted.padding_bytes += 1000;
2581 counters.transmitted.payload_bytes += 2000;
2582 counters.retransmitted.packets += 2;
2583 counters.retransmitted.header_bytes += 25;
2584 counters.retransmitted.padding_bytes += 100;
2585 counters.retransmitted.payload_bytes += 250;
2586 counters.fec = counters.retransmitted;
2587 rtx_counters.transmitted = counters.transmitted;
2588 // Advance one interval and update counters.
2589 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2590 proxy->DataCountersUpdated(counters, kFirstSsrc);
2591 proxy->DataCountersUpdated(counters, kSecondSsrc);
2592 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2593 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2594 }
Erik Språng22c2b482016-03-01 09:40:42 +01002595
asapersson93e1e232017-02-06 05:18:35 -08002596 // Reset stats proxy also causes histograms to be reported.
2597 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002598
asapersson93e1e232017-02-06 05:18:35 -08002599 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002600 EXPECT_METRIC_EQ(
2601 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2602 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002603 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2604 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002605 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002606 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002607 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2608 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002609 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002610 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2611 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2612 EXPECT_METRIC_EQ(
2613 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2614 12));
asapersson93e1e232017-02-06 05:18:35 -08002615 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002616 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2617 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2618 EXPECT_METRIC_EQ(
2619 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2620 16));
asapersson93e1e232017-02-06 05:18:35 -08002621 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002622 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002623 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002624 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2625 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002626 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002627 EXPECT_METRIC_EQ(
2628 1, metrics::NumSamples(
2629 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2630 EXPECT_METRIC_EQ(
2631 1, metrics::NumEvents(
2632 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002633}
Erik Språng22c2b482016-03-01 09:40:42 +01002634
asapersson93e1e232017-02-06 05:18:35 -08002635TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2636 StreamDataCountersCallback* proxy =
2637 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2638 StreamDataCounters counters;
2639 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002640
asapersson93e1e232017-02-06 05:18:35 -08002641 const int kMinRequiredPeriodSamples = 8;
2642 const int kPeriodIntervalMs = 2000;
2643 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2644 counters.transmitted.packets += 20;
2645 counters.transmitted.header_bytes += 500;
2646 counters.transmitted.payload_bytes += 2000;
2647 counters.fec = counters.retransmitted;
2648 // Advance one interval and update counters.
2649 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2650 proxy->DataCountersUpdated(counters, kFirstSsrc);
2651 }
2652
2653 // RTX enabled. No data sent over RTX.
2654 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002655 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2656 EXPECT_METRIC_EQ(1,
2657 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002658}
2659
2660TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2661 VideoSendStream::Config config(nullptr);
2662 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2663 statistics_proxy_.reset(new SendStatisticsProxy(
2664 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2665
2666 StreamDataCountersCallback* proxy =
2667 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2668 StreamDataCounters counters;
2669
2670 const int kMinRequiredPeriodSamples = 8;
2671 const int kPeriodIntervalMs = 2000;
2672 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2673 counters.transmitted.packets += 20;
2674 counters.transmitted.header_bytes += 500;
2675 counters.transmitted.payload_bytes += 2000;
2676 counters.fec = counters.retransmitted;
2677 // Advance one interval and update counters.
2678 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2679 proxy->DataCountersUpdated(counters, kFirstSsrc);
2680 }
2681
2682 // RTX not enabled.
2683 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002684 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002685}
2686
2687TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2688 StreamDataCountersCallback* proxy =
2689 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2690 StreamDataCounters counters;
2691 StreamDataCounters rtx_counters;
2692
2693 const int kMinRequiredPeriodSamples = 8;
2694 const int kPeriodIntervalMs = 2000;
2695 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2696 counters.transmitted.packets += 20;
2697 counters.transmitted.header_bytes += 500;
2698 counters.transmitted.payload_bytes += 2000;
2699 // Advance one interval and update counters.
2700 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2701 proxy->DataCountersUpdated(counters, kFirstSsrc);
2702 }
2703
2704 // FEC enabled. No FEC data sent.
2705 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002706 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2707 EXPECT_METRIC_EQ(1,
2708 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002709}
2710
2711TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2712 VideoSendStream::Config config(nullptr);
2713 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2714 statistics_proxy_.reset(new SendStatisticsProxy(
2715 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2716
2717 StreamDataCountersCallback* proxy =
2718 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2719 StreamDataCounters counters;
2720
2721 const int kMinRequiredPeriodSamples = 8;
2722 const int kPeriodIntervalMs = 2000;
2723 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2724 counters.transmitted.packets += 20;
2725 counters.transmitted.header_bytes += 500;
2726 counters.transmitted.payload_bytes += 2000;
2727 counters.fec = counters.retransmitted;
2728 // Advance one interval and update counters.
2729 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2730 proxy->DataCountersUpdated(counters, kFirstSsrc);
2731 }
2732
2733 // FEC not enabled.
2734 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002735 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002736}
2737
asapersson8d75ac72017-09-15 06:41:15 -07002738TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002739 const std::string kName = "encoderName";
2740 statistics_proxy_->OnEncoderImplementationChanged(kName);
2741 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002742}
2743
Sergey Silkinbb081a62018-09-04 18:34:22 +02002744TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2745 static const int kEncodedWidth = 123;
2746 static const int kEncodedHeight = 81;
2747 EncodedImage encoded_image;
2748 encoded_image._encodedWidth = kEncodedWidth;
2749 encoded_image._encodedHeight = kEncodedHeight;
2750 encoded_image.SetSpatialIndex(0);
2751
2752 CodecSpecificInfo codec_info;
2753 codec_info.codecType = kVideoCodecVP9;
2754
2755 // For first picture, it is expected that low layer updates resolution.
2756 codec_info.codecSpecific.VP9.end_of_picture = false;
2757 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2758 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2759 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2760 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2761
2762 // Top layer updates resolution.
2763 encoded_image._encodedWidth = kEncodedWidth * 2;
2764 encoded_image._encodedHeight = kEncodedHeight * 2;
2765 codec_info.codecSpecific.VP9.end_of_picture = true;
2766 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2767 stats = statistics_proxy_->GetStats();
2768 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2769 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2770
2771 // Low layer of next frame doesn't update resolution.
2772 encoded_image._encodedWidth = kEncodedWidth;
2773 encoded_image._encodedHeight = kEncodedHeight;
2774 codec_info.codecSpecific.VP9.end_of_picture = false;
2775 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2776 stats = statistics_proxy_->GetStats();
2777 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2778 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2779}
2780
asapersson8d75ac72017-09-15 06:41:15 -07002781class ForcedFallbackTest : public SendStatisticsProxyTest {
2782 public:
2783 explicit ForcedFallbackTest(const std::string& field_trials)
2784 : SendStatisticsProxyTest(field_trials) {
2785 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002786 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002787 encoded_image_._encodedWidth = kWidth;
2788 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002789 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002790 }
2791
2792 ~ForcedFallbackTest() override {}
2793
2794 protected:
2795 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002796 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2797
asapersson8d75ac72017-09-15 06:41:15 -07002798 // First frame is not updating stats, insert initial frame.
2799 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2800 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2801 }
2802 for (int i = 0; i < num_frames; ++i) {
2803 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2804 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2805 }
2806 // Add frame to include last time interval.
2807 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2808 }
2809
2810 EncodedImage encoded_image_;
2811 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002812 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002813 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2814 const int kFrameIntervalMs = 1000;
2815 const int kMinFrames = 20; // Min run time 20 sec.
2816};
2817
2818class ForcedFallbackDisabled : public ForcedFallbackTest {
2819 public:
2820 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002821 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2822 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002823};
2824
2825class ForcedFallbackEnabled : public ForcedFallbackTest {
2826 public:
2827 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002828 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2829 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002830};
2831
2832TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2833 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2834 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002835 EXPECT_METRIC_EQ(0,
2836 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2837 EXPECT_METRIC_EQ(
2838 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002839}
2840
2841TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2842 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002843 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002844 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002845 EXPECT_METRIC_EQ(1,
2846 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2847 EXPECT_METRIC_EQ(
2848 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2849 EXPECT_METRIC_EQ(
2850 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2851 EXPECT_METRIC_EQ(
2852 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002853}
2854
2855TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2856 codec_info_.codecType = kVideoCodecVP9;
2857 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2858 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002859 EXPECT_METRIC_EQ(0,
2860 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2861 EXPECT_METRIC_EQ(
2862 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002863}
2864
2865TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2866 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2867 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2868 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002869 EXPECT_METRIC_EQ(0,
2870 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2871 EXPECT_METRIC_EQ(
2872 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002873}
2874
2875TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002876 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002877 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2878 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002879 EXPECT_METRIC_EQ(0,
2880 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2881 EXPECT_METRIC_EQ(
2882 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002883}
2884
2885TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2886 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2887 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002888 EXPECT_METRIC_EQ(0,
2889 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2890 EXPECT_METRIC_EQ(
2891 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002892}
2893
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002894TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2895 InsertEncodedFrames(1, kFrameIntervalMs);
2896 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2897}
2898
2899TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2900 InsertEncodedFrames(1, kFrameIntervalMs);
2901 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2902}
2903
2904TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002905 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002906 InsertEncodedFrames(1, kFrameIntervalMs);
2907 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2908}
2909
2910TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2911 encoded_image_._encodedWidth = kWidth + 1;
2912 InsertEncodedFrames(1, kFrameIntervalMs);
2913 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2914}
2915
2916TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002917 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002918 InsertEncodedFrames(1, kFrameIntervalMs);
2919 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2920}
2921
2922TEST_F(ForcedFallbackDisabled,
2923 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2924 encoded_image_._encodedWidth = kWidth + 1;
2925 statistics_proxy_->OnMinPixelLimitReached();
2926 InsertEncodedFrames(1, kFrameIntervalMs);
2927 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2928}
2929
asapersson8d75ac72017-09-15 06:41:15 -07002930TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2931 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002932 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002933 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002934 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002935 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002936 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002937 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002938
2939 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002940 EXPECT_METRIC_EQ(1,
2941 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2942 EXPECT_METRIC_EQ(
2943 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2944 EXPECT_METRIC_EQ(
2945 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2946 EXPECT_METRIC_EQ(
2947 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002948}
2949
2950TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2951 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2952 const int kMaxFrameDiffMs = 2000;
2953
2954 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2955 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002956 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002957 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002958 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002959 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002960 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002961 InsertEncodedFrames(20, 1000);
2962 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2963 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002964 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002965 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002966 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002967 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002968 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002969 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002970 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002971
2972 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002973 EXPECT_METRIC_EQ(1,
2974 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2975 EXPECT_METRIC_EQ(
2976 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2977 EXPECT_METRIC_EQ(
2978 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2979 EXPECT_METRIC_EQ(
2980 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002981}
2982
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002983TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2984 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002985 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002986 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2987
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002988 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002989 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002990 EXPECT_METRIC_EQ(0,
2991 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2992 EXPECT_METRIC_EQ(
2993 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002994}
2995
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002996TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2997 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002998 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002999 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3000
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003001 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003002 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003003 EXPECT_METRIC_EQ(1,
3004 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3005 EXPECT_METRIC_EQ(
3006 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003007}
3008
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00003009} // namespace webrtc