blob: 5a7c356f2e2a9e572b8c2d14b1acea6b27678770 [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 Shrubsolece0a11d2020-04-16 11:36:55 +020021#include "api/video/video_adaptation_reason.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020022#include "api/video/video_bitrate_allocation.h"
23#include "api/video/video_codec_type.h"
24#include "api/video_codecs/video_codec.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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 12:52:48 +010028#include "test/scoped_key_value_config.h"
Jonas Oreland6c2dae22022-09-29 10:28:24 +020029#include "video/config/video_encoder_config.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000030
31namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070032namespace {
33const uint32_t kFirstSsrc = 17;
34const uint32_t kSecondSsrc = 42;
35const uint32_t kFirstRtxSsrc = 18;
36const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080037const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080038const int kFpsPeriodicIntervalMs = 2000;
39const int kWidth = 640;
40const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070041const int kQpIdx0 = 21;
42const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010043const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080044const CodecSpecificInfo kDefaultCodecInfo = []() {
45 CodecSpecificInfo codec_info;
46 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080047 return codec_info;
48}();
Evan Shrubsoledff79252020-04-16 11:34:32 +020049
50const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
51 true);
52const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
53 true,
54 false);
55const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
56 false,
57 true);
58const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
asapersson5265fed2016-04-18 02:58:47 -070059} // namespace
sprang07fb9be2016-02-24 07:55:00 -080060
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000061class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000062 public:
asapersson8d75ac72017-09-15 06:41:15 -070063 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
64 explicit SendStatisticsProxyTest(const std::string& field_trials)
65 : override_field_trials_(field_trials),
66 fake_clock_(1234),
Åsa Persson90719572021-04-08 19:05:30 +020067 config_(GetTestConfig()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000068 virtual ~SendStatisticsProxyTest() {}
69
70 protected:
71 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070072 metrics::Reset();
Jonas Oreland8ca06132022-03-14 12:52:48 +010073 statistics_proxy_.reset(
74 new SendStatisticsProxy(&fake_clock_, GetTestConfig(),
75 VideoEncoderConfig::ContentType::kRealtimeVideo,
76 override_field_trials_));
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) {
Di Wu668dbf62021-02-27 00:29:15 -0800128 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000129 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
130 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000131 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000132 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000133
134 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000135 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000136 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000137 it != one.substreams.end(); ++it) {
138 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
139 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000140 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000141 const VideoSendStream::StreamStats& a = it->second;
142 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000143
Henrik Boströmf45ca372020-03-24 13:30:50 +0100144 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000145 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
146 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000147 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000148 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
149 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000150
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000151 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
152 b.rtp_stats.transmitted.payload_bytes);
153 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
154 b.rtp_stats.transmitted.header_bytes);
155 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
156 b.rtp_stats.transmitted.padding_bytes);
157 EXPECT_EQ(a.rtp_stats.transmitted.packets,
158 b.rtp_stats.transmitted.packets);
159 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
160 b.rtp_stats.retransmitted.packets);
161 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000162
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200163 EXPECT_EQ(a.report_block_data.has_value(),
164 b.report_block_data.has_value());
165 if (a.report_block_data.has_value()) {
166 const RTCPReportBlock& a_rtcp_stats =
167 a.report_block_data->report_block();
168 const RTCPReportBlock& b_rtcp_stats =
169 b.report_block_data->report_block();
170 EXPECT_EQ(a_rtcp_stats.fraction_lost, b_rtcp_stats.fraction_lost);
171 EXPECT_EQ(a_rtcp_stats.packets_lost, b_rtcp_stats.packets_lost);
172 EXPECT_EQ(a_rtcp_stats.extended_highest_sequence_number,
173 b_rtcp_stats.extended_highest_sequence_number);
174 EXPECT_EQ(a_rtcp_stats.jitter, b_rtcp_stats.jitter);
175 }
sprang@webrtc.org09315702014-02-07 12:06:29 +0000176 }
177 }
178
Jonas Oreland8ca06132022-03-14 12:52:48 +0100179 test::ScopedKeyValueConfig override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000180 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800181 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000183 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184};
185
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200186TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
187 ReportBlockDataObserver* callback = statistics_proxy_.get();
188 for (uint32_t ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000189 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200190 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200191 RTCPReportBlock report_block;
192 report_block.source_ssrc = ssrc;
193 report_block.packets_lost = offset;
194 report_block.extended_highest_sequence_number = offset + 1;
195 report_block.fraction_lost = offset + 2;
196 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200197 ReportBlockData data;
198 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200199 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200200
201 callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000202 }
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200203 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000204 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200205 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200206 RTCPReportBlock report_block;
207 report_block.source_ssrc = ssrc;
208 report_block.packets_lost = offset;
209 report_block.extended_highest_sequence_number = offset + 1;
210 report_block.fraction_lost = offset + 2;
211 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200212 ReportBlockData data;
213 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200214 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200215
216 callback->OnReportBlockDataUpdated(data);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000217 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000218 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000219 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000220}
221
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000222TEST_F(SendStatisticsProxyTest, Suspended) {
223 // Verify that the value is false by default.
224 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
225
226 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200227 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000228 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
229
230 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200231 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000232 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
233}
234
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000235TEST_F(SendStatisticsProxyTest, FrameCounts) {
236 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700237 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000238 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000239 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
240 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000241 FrameCounts frame_counts;
242 frame_counts.key_frames = offset;
243 frame_counts.delta_frames = offset + 1;
244 stats.frame_counts = frame_counts;
245 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000246 }
asapersson35151f32016-05-02 23:44:01 -0700247 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000248 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000249 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
250 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000251 FrameCounts frame_counts;
252 frame_counts.key_frames = offset;
253 frame_counts.delta_frames = offset + 1;
254 stats.frame_counts = frame_counts;
255 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000256 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000257
258 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000259 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000260}
261
262TEST_F(SendStatisticsProxyTest, DataCounters) {
263 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700264 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +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;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000275 callback->DataCountersUpdated(counters, ssrc);
276 }
asapersson35151f32016-05-02 23:44:01 -0700277 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000278 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
279 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000280 size_t offset = ssrc * sizeof(StreamDataCounters);
281 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000282 counters.transmitted.payload_bytes = offset;
283 counters.transmitted.header_bytes = offset + 1;
284 counters.fec.packets = offset_uint32 + 2;
285 counters.transmitted.padding_bytes = offset + 3;
286 counters.retransmitted.packets = offset_uint32 + 4;
287 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000288 callback->DataCountersUpdated(counters, ssrc);
289 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000290
291 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000292 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000293}
294
295TEST_F(SendStatisticsProxyTest, Bitrate) {
296 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700297 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000298 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200299 uint32_t total = ssrc;
300 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000301 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700302 expected_.substreams[ssrc].total_bitrate_bps = total;
303 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000304 }
asapersson35151f32016-05-02 23:44:01 -0700305 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000306 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200307 uint32_t total = ssrc;
308 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000309 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700310 expected_.substreams[ssrc].total_bitrate_bps = total;
311 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000312 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000313
314 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000315 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000316}
317
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000318TEST_F(SendStatisticsProxyTest, SendSideDelay) {
319 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700320 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000321 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
322 // stream.
323 int avg_delay_ms = ssrc;
324 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200325 uint64_t total_packet_send_delay_ms = ssrc + 2;
326 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
327 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000328 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
329 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200330 expected_.substreams[ssrc].total_packet_send_delay_ms =
331 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000332 }
asapersson35151f32016-05-02 23:44:01 -0700333 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000334 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
335 // stream.
336 int avg_delay_ms = ssrc;
337 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200338 uint64_t total_packet_send_delay_ms = ssrc + 2;
339 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
340 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000341 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
342 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200343 expected_.substreams[ssrc].total_packet_send_delay_ms =
344 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000345 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000346 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000347 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000348}
349
Peter Boströme4499152016-02-05 11:13:28 +0100350TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800351 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200352 int encode_usage_percent = 80;
353 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
354 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800355
356 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
357 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200358 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800359}
360
Henrik Boström5684af52019-04-02 15:05:21 +0200361TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
362 const int kEncodeUsagePercent = 0; // Don't care for this test.
363 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
364 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
365 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
366 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
367 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
368}
369
sakal43536c32016-10-24 01:46:43 -0700370TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
371 EncodedImage encoded_image;
372 CodecSpecificInfo codec_info;
373 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
374 for (uint32_t i = 1; i <= 3; ++i) {
375 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
376 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
377 }
378}
379
sakal87da4042016-10-31 06:53:47 -0700380TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
381 EncodedImage encoded_image;
382 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200383 auto ssrc = config_.rtp.ssrcs[0];
384 EXPECT_EQ(absl::nullopt,
385 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700386 encoded_image.qp_ = 3;
387 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200388 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700389 encoded_image.qp_ = 127;
390 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200391 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700392}
393
394TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
395 EncodedImage encoded_image;
396 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200397 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700398 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200399 EXPECT_EQ(absl::nullopt,
400 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700401 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200402 EXPECT_EQ(absl::nullopt,
403 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700404}
405
Henrik Boström23aff9b2019-05-20 15:15:38 +0200406TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
407 const uint32_t kTargetBytesPerSecond = 100000;
408 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
409 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
410
411 EncodedImage encoded_image;
412 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
413 // On the first frame we don't know the frame rate yet, calculation yields
414 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
Artem Titovab30d722021-07-27 16:22:11 +0200415 // increment by a full `kTargetBytesPerSecond`.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200416 EXPECT_EQ(kTargetBytesPerSecond,
417 statistics_proxy_->GetStats().total_encoded_bytes_target);
418}
419
420TEST_F(SendStatisticsProxyTest,
421 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
422 const uint32_t kTargetBytesPerSecond = 100000;
423 const int kInterframeDelayMs = 100;
424
425 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
Artem Titovab30d722021-07-27 16:22:11 +0200426 // `fake_clock_` for testing, but the RateTracker relies on a global clock.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200427 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
428 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
429 // this test can stop relying on rtc::ScopedFakeClock.
430 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100431 fake_global_clock.SetTime(
432 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200433
434 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
435 EncodedImage encoded_image;
436
437 // First frame
438 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
439 uint64_t first_total_encoded_bytes_target =
440 statistics_proxy_->GetStats().total_encoded_bytes_target;
441 // Second frame
442 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100443 fake_global_clock.SetTime(
444 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200445 encoded_image.SetTimestamp(encoded_image.Timestamp() +
446 90 * kInterframeDelayMs);
447 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
448
449 auto stats = statistics_proxy_->GetStats();
450 // By the time the second frame arrives, one frame has previously arrived
Artem Titovab30d722021-07-27 16:22:11 +0200451 // during a `kInterframeDelayMs` interval. The estimated encode frame rate at
Henrik Boström23aff9b2019-05-20 15:15:38 +0200452 // the second frame's arrival should be 10 FPS.
453 uint64_t delta_encoded_bytes_target =
454 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
455 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
456}
457
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200458TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
459 const int kInterframeDelayMs = 100;
Åsa Persson603e6e32021-08-10 08:56:36 +0200460 const auto ssrc = config_.rtp.ssrcs[0];
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200461 rtc::ScopedFakeClock fake_global_clock;
462 fake_global_clock.SetTime(
463 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
464
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200465 // First frame
Åsa Persson603e6e32021-08-10 08:56:36 +0200466 EncodedImage encoded_image;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200467 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200468 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
469 fake_global_clock.SetTime(
470 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson603e6e32021-08-10 08:56:36 +0200471 // Second frame
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200472 encoded_image.SetTimestamp(encoded_image.Timestamp() +
473 90 * kInterframeDelayMs);
474 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson603e6e32021-08-10 08:56:36 +0200475 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
476 fake_global_clock.SetTime(
477 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200478
479 auto stats = statistics_proxy_->GetStats();
480 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
481}
482
Åsa Persson8d564722021-08-03 14:43:01 +0200483TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp8Simulcast) {
484 const int kInterframeDelayMs = 100;
485 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200486 fake_global_clock.SetTime(
487 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200488 EncodedImage encoded_image;
489 CodecSpecificInfo codec_info;
490 codec_info.codecType = kVideoCodecVP8;
491
492 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200493 encoded_image.SetTimestamp(encoded_image.Timestamp() +
494 90 * kInterframeDelayMs);
495 encoded_image.SetSpatialIndex(0);
496 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
497 encoded_image.SetSpatialIndex(1);
498 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200499 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
500 fake_global_clock.SetTime(
501 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200502 }
503
504 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
505 EXPECT_EQ(2u, stats.substreams.size());
506 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
507 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson603e6e32021-08-10 08:56:36 +0200508
509 // Stop encoding second stream, expect framerate to be zero.
510 for (int i = 0; i < 10; ++i) {
511 encoded_image.SetTimestamp(encoded_image.Timestamp() +
512 90 * kInterframeDelayMs);
513 encoded_image.SetSpatialIndex(0);
514 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
515 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
516 fake_global_clock.SetTime(
517 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
518 }
519
520 stats = statistics_proxy_->GetStats();
521 EXPECT_EQ(2u, stats.substreams.size());
522 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
523 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 0);
524
525 // Start encoding second stream.
526 for (int i = 0; i < 10; ++i) {
527 encoded_image.SetTimestamp(encoded_image.Timestamp() +
528 90 * kInterframeDelayMs);
529 encoded_image.SetSpatialIndex(0);
530 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
531 encoded_image.SetSpatialIndex(1);
532 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
533 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
534 fake_global_clock.SetTime(
535 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
536 }
537
538 stats = statistics_proxy_->GetStats();
539 EXPECT_EQ(2u, stats.substreams.size());
540 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
541 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson8d564722021-08-03 14:43:01 +0200542}
543
544TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp9Svc) {
545 const int kInterframeDelayMs = 100;
546 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200547 fake_global_clock.SetTime(
548 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200549 EncodedImage encoded_image;
550 CodecSpecificInfo codec_info;
551 codec_info.codecType = kVideoCodecVP9;
552
553 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200554 encoded_image.SetTimestamp(encoded_image.Timestamp() +
555 90 * kInterframeDelayMs);
556 encoded_image.SetSpatialIndex(0);
557 codec_info.end_of_picture = false;
558 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
559 encoded_image.SetSpatialIndex(1);
560 codec_info.end_of_picture = true;
561 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200562 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
563 fake_global_clock.SetTime(
564 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200565 }
566
567 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
568 EXPECT_EQ(1u, stats.substreams.size());
569 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
570}
571
asapersson09f05612017-05-15 23:40:18 -0700572TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200573 VideoAdaptationCounters cpu_counts;
574 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700575 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700576 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200577 cpu_counts.fps_adaptations = 1;
578 cpu_counts.resolution_adaptations = 0;
579 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200580 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
581 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700582 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700583 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200584 cpu_counts.fps_adaptations = 0;
585 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200586 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
587 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700588 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700589 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200590 cpu_counts.fps_adaptations = 1;
591 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
592 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200593 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
594 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700595 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700596 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200597 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
598 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200599 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
600 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700601 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
602 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
603}
604
605TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200606 VideoAdaptationCounters cpu_counts;
607 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700608 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
609 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200610 quality_counts.fps_adaptations = 1;
611 quality_counts.resolution_adaptations = 0;
612 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200613 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
614 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700615 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
616 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200617 quality_counts.fps_adaptations = 0;
618 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200619 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
620 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700621 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
622 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200623 quality_counts.fps_adaptations = 1;
624 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
625 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200626 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
627 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700628 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
629 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200630 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
631 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200632 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
633 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700634 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
635 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
636}
637
638TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200639 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
640 VideoAdaptationCounters cpu_counts;
641 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700642 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
643
Evan Shrubsoledff79252020-04-16 11:34:32 +0200644 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200645 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
646 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700647 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700648 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
649 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
650
Evan Shrubsoledff79252020-04-16 11:34:32 +0200651 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200652 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
653 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700654 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
655 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700656 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700657 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700658}
659
asapersson09f05612017-05-15 23:40:18 -0700660TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200661 VideoAdaptationCounters cpu_counts;
662 VideoAdaptationCounters quality_counts;
663 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700664 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
665
Evan Shrubsoledff79252020-04-16 11:34:32 +0200666 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200667 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
668 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700669 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
670 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700671 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
672
Evan Shrubsoledff79252020-04-16 11:34:32 +0200673 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200674 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
675 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700676 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700677 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700678 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
679 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700680}
681
Evan Shrubsoledff79252020-04-16 11:34:32 +0200682TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
683 VideoAdaptationCounters cpu_counts;
684 VideoAdaptationCounters quality_counts;
685 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
686 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
687 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
688
689 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200690 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
691 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200692 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200693 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
694 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200695 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200696 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
697 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200698 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200699 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
700 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200701 // We have 1 fps and resolution reduction for both cpu and quality
702 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
703 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
704 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
705 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
706 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
707 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
708
709 // Disable quality scaling. Expect quality scaling not limited.
710 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
711 kScalingDisabled);
712 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
713 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
714 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
715 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
716 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
717 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
718
719 // Disable framerate scaling.
720 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
721 kFramerateScalingDisabled);
722 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
723 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
724 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
725 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
726 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
727 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
728
729 // Disable resolution scaling.
730 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
731 kResolutionScalingDisabled);
732 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
733 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
734 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
735 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
736 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
737 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
738
739 // Enable all
740 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
741 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
742 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
743 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
744 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
745 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
746 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
747}
748
asapersson09f05612017-05-15 23:40:18 -0700749TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700750 // First RTP packet sent.
751 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700752 // Min runtime has passed.
753 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
754 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100755 EXPECT_METRIC_EQ(
756 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
757 EXPECT_METRIC_EQ(
758 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700759}
760
761TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700762 // First RTP packet sent.
763 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700764 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200765 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700766 // Min runtime has not passed.
767 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
768 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100769 EXPECT_METRIC_EQ(
770 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
771 EXPECT_METRIC_EQ(
772 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700773}
774
asapersson09f05612017-05-15 23:40:18 -0700775TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700776 // First RTP packet sent.
777 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700778 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200779 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700780 // Min runtime has passed.
781 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
782 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100783 EXPECT_METRIC_EQ(
784 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
785 EXPECT_METRIC_EQ(
786 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
787 EXPECT_METRIC_EQ(
788 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
789 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700790 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
791}
792
793TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700794 // First RTP packet sent.
795 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700796 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200797 VideoAdaptationCounters cpu_counts;
798 VideoAdaptationCounters quality_counts;
799 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700800 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200801 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
802 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700803 fake_clock_.AdvanceTimeMilliseconds(10000);
804 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100805 EXPECT_METRIC_EQ(
806 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
807 EXPECT_METRIC_EQ(
808 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700809}
810
Åsa Persson875841d2018-01-08 08:49:53 +0100811TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
812 // First RTP packet sent.
813 UpdateDataCounters(kFirstSsrc);
814 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200815 VideoAdaptationCounters cpu_counts;
816 VideoAdaptationCounters quality_counts;
817 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100818 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200819 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
820 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100821 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
822 fake_clock_.AdvanceTimeMilliseconds(10000);
823 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100824 EXPECT_METRIC_EQ(
825 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
826 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100827 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
828}
829
830TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
831 // First RTP packet sent.
832 UpdateDataCounters(kFirstSsrc);
833 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200834 VideoAdaptationCounters cpu_counts;
835 VideoAdaptationCounters quality_counts;
836 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100837 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200838 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200839 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
840 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100841 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200842 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200843 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
844 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100845 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200846 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200847 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
848 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100849 fake_clock_.AdvanceTimeMilliseconds(10000);
850 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100851 EXPECT_METRIC_EQ(
852 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
853 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100854 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
855}
856
857TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
858 // First RTP packet sent.
859 UpdateDataCounters(kFirstSsrc);
860 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200861 VideoAdaptationCounters cpu_counts;
862 VideoAdaptationCounters quality_counts;
863 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100864 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200865 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
866 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100867 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
868 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
869 fake_clock_.AdvanceTimeMilliseconds(10000);
870 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100871 EXPECT_METRIC_EQ(
872 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
873 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100874 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
875}
876
877TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
878 // First RTP packet sent.
879 UpdateDataCounters(kFirstSsrc);
880 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200881 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
882 VideoAdaptationCounters cpu_counts;
883 VideoAdaptationCounters quality_counts;
884 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100885 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200886 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200887 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
888 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100889 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200890 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200891 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
892 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100893 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200894 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200895 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
896 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200897 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200898 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
899 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200900 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200901 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
902 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200903 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200904 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
905 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200906 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200907 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
908 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200909 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200910 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
911 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100912
913 fake_clock_.AdvanceTimeMilliseconds(10000);
914 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100915 EXPECT_METRIC_EQ(
916 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
917 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100918 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
919}
920
asapersson6eca98b2017-04-04 23:40:50 -0700921TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700922 // First RTP packet sent.
923 UpdateDataCounters(kFirstSsrc);
924
asapersson09f05612017-05-15 23:40:18 -0700925 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200926 VideoAdaptationCounters cpu_counts;
927 VideoAdaptationCounters quality_counts;
928 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
929 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700930 fake_clock_.AdvanceTimeMilliseconds(10000);
931
asapersson09f05612017-05-15 23:40:18 -0700932 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700933 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200934 quality_counts.fps_adaptations = 0;
935 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
936 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700937 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200938 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
939 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700940 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200941 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
942 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700943 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200944 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
945 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700946
asapersson09f05612017-05-15 23:40:18 -0700947 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200948 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
949 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700950 fake_clock_.AdvanceTimeMilliseconds(30000);
951
asapersson09f05612017-05-15 23:40:18 -0700952 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700953 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200954 quality_counts.resolution_adaptations = 0;
955 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
956 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200957 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
958 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700959 fake_clock_.AdvanceTimeMilliseconds(10000);
960
asapersson09f05612017-05-15 23:40:18 -0700961 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200962 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
963 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700964 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200965 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
966 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700967 fake_clock_.AdvanceTimeMilliseconds(20000);
968
asapersson0944a802017-04-07 00:57:58 -0700969 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700970 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100971 EXPECT_METRIC_EQ(
972 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
973 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700974 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
975}
976
asapersson0944a802017-04-07 00:57:58 -0700977TEST_F(SendStatisticsProxyTest,
978 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
979 // First RTP packet sent.
980 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700981
asapersson0944a802017-04-07 00:57:58 -0700982 // Suspend and resume video.
983 statistics_proxy_->OnSuspendChange(true);
984 fake_clock_.AdvanceTimeMilliseconds(5000);
985 statistics_proxy_->OnSuspendChange(false);
986
987 // Min runtime has passed but scaling not enabled.
988 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
989 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100990 EXPECT_METRIC_EQ(
991 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
992 EXPECT_METRIC_EQ(
993 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700994}
995
996TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
997 // First RTP packet sent.
998 UpdateDataCounters(kFirstSsrc);
999
asapersson09f05612017-05-15 23:40:18 -07001000 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001001 VideoAdaptationCounters cpu_counts;
1002 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -07001003 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001004 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001005 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001006 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1007 cpu_counts, quality_counts);
1008 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1009 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001010
1011 // Suspend and resume video.
1012 statistics_proxy_->OnSuspendChange(true);
1013 fake_clock_.AdvanceTimeMilliseconds(30000);
1014 statistics_proxy_->OnSuspendChange(false);
1015
1016 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001017 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1018 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001019 fake_clock_.AdvanceTimeMilliseconds(10000);
1020
1021 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
1022 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001023 EXPECT_METRIC_EQ(
1024 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1025 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -07001026 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1027}
1028
1029TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
1030 // First RTP packet sent.
1031 UpdateDataCounters(kFirstSsrc);
1032
1033 // Video not suspended.
1034 statistics_proxy_->OnSuspendChange(false);
1035 fake_clock_.AdvanceTimeMilliseconds(30000);
1036
asapersson09f05612017-05-15 23:40:18 -07001037 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001038 VideoAdaptationCounters cpu_counts;
1039 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -07001040 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001041 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001042 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001043 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1044 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001045
1046 // Video not suspended, stats time already started.
1047 statistics_proxy_->OnSuspendChange(false);
1048 fake_clock_.AdvanceTimeMilliseconds(10000);
1049
asapersson09f05612017-05-15 23:40:18 -07001050 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001051 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1052 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -07001053 fake_clock_.AdvanceTimeMilliseconds(30000);
1054
1055 // Suspend and resume video, stats time not started when scaling not enabled.
1056 statistics_proxy_->OnSuspendChange(true);
1057 fake_clock_.AdvanceTimeMilliseconds(30000);
1058 statistics_proxy_->OnSuspendChange(false);
1059 fake_clock_.AdvanceTimeMilliseconds(30000);
1060
asapersson09f05612017-05-15 23:40:18 -07001061 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -07001062 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001063 cpu_counts.fps_adaptations = 0;
1064 cpu_counts.resolution_adaptations = 0;
1065 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001066 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001067 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1068 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001069
1070 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
1071 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001072 EXPECT_METRIC_EQ(
1073 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1074 EXPECT_METRIC_EQ(
1075 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -07001076}
1077
1078TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
1079 // First RTP packet sent.
1080 UpdateDataCounters(kFirstSsrc);
1081
1082 // Video suspended.
1083 statistics_proxy_->OnSuspendChange(true);
1084
asapersson09f05612017-05-15 23:40:18 -07001085 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001086 VideoAdaptationCounters cpu_counts;
1087 VideoAdaptationCounters quality_counts;
1088 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001089 fake_clock_.AdvanceTimeMilliseconds(10000);
1090
1091 // Resume video, stats time started.
1092 // Adapt changes: 1, elapsed time: 10 sec.
1093 statistics_proxy_->OnSuspendChange(false);
1094 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001095 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1096 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001097
1098 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1099 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001100 EXPECT_METRIC_EQ(
1101 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1102 EXPECT_METRIC_EQ(
1103 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001104}
1105
1106TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001107 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001108 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001109 VideoAdaptationCounters cpu_counts;
1110 VideoAdaptationCounters quality_counts;
1111 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001112 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001113 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001114
asapersson0944a802017-04-07 00:57:58 -07001115 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001116 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001117 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1118 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001119 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001120
asapersson0944a802017-04-07 00:57:58 -07001121 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001122 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001123 EXPECT_METRIC_EQ(
1124 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1125 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001126 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1127}
1128
1129TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001130 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001131 VideoAdaptationCounters cpu_counts;
1132 VideoAdaptationCounters quality_counts;
1133 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001134 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001135 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1136 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001137
1138 // Send first packet, scaling disabled.
1139 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001140 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001141 fake_clock_.AdvanceTimeMilliseconds(60000);
1142
asapersson09f05612017-05-15 23:40:18 -07001143 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001144 cpu_counts.resolution_adaptations = 0;
1145 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1146 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001147 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001148 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001149
asapersson0944a802017-04-07 00:57:58 -07001150 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001151 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001152 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1153 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001154
asapersson0944a802017-04-07 00:57:58 -07001155 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001156 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001157 EXPECT_METRIC_EQ(
1158 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1159 EXPECT_METRIC_EQ(
1160 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001161}
1162
1163TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001164 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001165 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001166 VideoAdaptationCounters cpu_counts;
1167 VideoAdaptationCounters quality_counts;
1168 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1169 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001170
asapersson0944a802017-04-07 00:57:58 -07001171 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001172 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1173 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001174 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001175 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1176 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001177 fake_clock_.AdvanceTimeMilliseconds(9000);
1178
1179 // Switch content type, real-time stats should be updated.
1180 VideoEncoderConfig config;
1181 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001182 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001183 EXPECT_METRIC_EQ(
1184 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1185 EXPECT_METRIC_EQ(
1186 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1187 EXPECT_METRIC_EQ(
1188 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001189
asapersson0944a802017-04-07 00:57:58 -07001190 // First RTP packet sent, scaling enabled.
1191 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001192 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1193 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001194
asapersson0944a802017-04-07 00:57:58 -07001195 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001196 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1197 cpu_counts, quality_counts);
1198 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1199 cpu_counts, quality_counts);
1200 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1201 cpu_counts, quality_counts);
1202 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1203 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001204 fake_clock_.AdvanceTimeMilliseconds(120000);
1205
1206 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001207 EXPECT_METRIC_EQ(1,
1208 metrics::NumSamples(
1209 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1210 EXPECT_METRIC_EQ(
1211 1, metrics::NumEvents(
1212 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1213 EXPECT_METRIC_EQ(
1214 0, metrics::NumSamples(
1215 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001216}
1217
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001218TEST_F(SendStatisticsProxyTest,
1219 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001220 VideoAdaptationCounters cpu_counts;
1221 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001222
Evan Shrubsoledff79252020-04-16 11:34:32 +02001223 cpu_counts.resolution_adaptations = 1;
1224 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001225 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1226 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001227
1228 EXPECT_EQ(QualityLimitationReason::kCpu,
1229 statistics_proxy_->GetStats().quality_limitation_reason);
1230}
1231
1232TEST_F(SendStatisticsProxyTest,
1233 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001234 VideoAdaptationCounters cpu_counts;
1235 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001236
Evan Shrubsoledff79252020-04-16 11:34:32 +02001237 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001238
Evan Shrubsoledff79252020-04-16 11:34:32 +02001239 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001240 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1241 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001242
1243 EXPECT_EQ(QualityLimitationReason::kCpu,
1244 statistics_proxy_->GetStats().quality_limitation_reason);
1245}
1246
1247TEST_F(SendStatisticsProxyTest,
1248 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001249 VideoAdaptationCounters cpu_counts;
1250 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001251
Evan Shrubsoledff79252020-04-16 11:34:32 +02001252 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001253
Evan Shrubsoledff79252020-04-16 11:34:32 +02001254 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001255 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1256 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001257
1258 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1259 statistics_proxy_->GetStats().quality_limitation_reason);
1260}
1261
1262TEST_F(SendStatisticsProxyTest,
1263 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001264 VideoAdaptationCounters cpu_counts;
1265 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001266
Evan Shrubsoledff79252020-04-16 11:34:32 +02001267 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001268
Evan Shrubsoledff79252020-04-16 11:34:32 +02001269 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001270 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1271 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001272
1273 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1274 statistics_proxy_->GetStats().quality_limitation_reason);
1275}
1276
1277TEST_F(SendStatisticsProxyTest,
1278 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001279 VideoAdaptationCounters cpu_counts;
1280 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001281
Evan Shrubsoledff79252020-04-16 11:34:32 +02001282 cpu_counts.resolution_adaptations = 1;
1283 quality_counts.resolution_adaptations = 1;
1284 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001285
1286 // Even if the last adaptation reason is kCpu, if the counters indicate being
1287 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001288 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1289 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001290
1291 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1292 statistics_proxy_->GetStats().quality_limitation_reason);
1293}
1294
1295TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001296 VideoAdaptationCounters cpu_counts;
1297 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001298
1299 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1300 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001301 cpu_counts.resolution_adaptations = 1;
1302 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001303 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1304 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001305 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001306 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001307 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1308 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001309
1310 EXPECT_EQ(QualityLimitationReason::kNone,
1311 statistics_proxy_->GetStats().quality_limitation_reason);
1312}
1313
1314TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001315 VideoAdaptationCounters cpu_counts;
1316 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001317
Evan Shrubsoledff79252020-04-16 11:34:32 +02001318 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001319 // Not limited for 3000 ms
1320 fake_clock_.AdvanceTimeMilliseconds(3000);
1321 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001322 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001323 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1324 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001325 fake_clock_.AdvanceTimeMilliseconds(2000);
1326 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001327 cpu_counts.resolution_adaptations = 0;
1328 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001329 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1330 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001331 fake_clock_.AdvanceTimeMilliseconds(1000);
1332 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001333 cpu_counts.resolution_adaptations = 1;
1334 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001335 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1336 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001337 fake_clock_.AdvanceTimeMilliseconds(2000);
1338
1339 auto quality_limitation_durations_ms =
1340 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1341
1342 EXPECT_EQ(3000,
1343 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1344 EXPECT_EQ(4000,
1345 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1346 EXPECT_EQ(
1347 1000,
1348 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1349 EXPECT_EQ(0,
1350 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1351}
1352
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001353TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1354 EXPECT_EQ(
1355 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1356}
1357
1358TEST_F(SendStatisticsProxyTest,
1359 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1360 VideoCodec codec;
1361 VideoBitrateAllocation allocation;
1362 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1363 EXPECT_EQ(
1364 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1365}
1366
1367TEST_F(SendStatisticsProxyTest,
1368 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1369 VideoCodec codec;
1370 codec.simulcastStream[0].active = true;
1371 codec.simulcastStream[1].active = true;
1372 codec.simulcastStream[2].active = true;
1373 VideoBitrateAllocation allocation;
1374 allocation.SetBitrate(0, 0, 100);
1375 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1376 EXPECT_EQ(
1377 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1378}
1379
1380TEST_F(SendStatisticsProxyTest,
1381 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1382 VideoCodec codec;
1383 codec.simulcastStream[0].active = true;
1384 codec.simulcastStream[1].active = true;
1385 codec.simulcastStream[2].active = true;
1386 VideoBitrateAllocation allocation;
1387 allocation.SetBitrate(0, 0, 100);
1388 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1389 allocation.SetBitrate(1, 0, 100);
1390 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1391 EXPECT_EQ(
1392 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1393}
1394
1395TEST_F(SendStatisticsProxyTest,
1396 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1397 VideoCodec codec;
1398 codec.simulcastStream[0].active = true;
1399 VideoBitrateAllocation allocation;
1400 allocation.SetBitrate(0, 0, 100);
1401 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1402 // Layer 0 got more bandwidth, but still only one layer on
1403 allocation.SetBitrate(0, 0, 200);
1404 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1405 EXPECT_EQ(
1406 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1407}
1408
1409TEST_F(SendStatisticsProxyTest,
1410 QualityLimitationResolutionChangesWithTogglingLayers) {
1411 VideoCodec codec;
1412 codec.simulcastStream[0].active = true;
1413 codec.simulcastStream[1].active = true;
1414 codec.simulcastStream[2].active = true;
1415 VideoBitrateAllocation allocation;
1416 allocation.SetBitrate(0, 0, 100);
1417 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1418 EXPECT_EQ(
1419 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1420 allocation.SetBitrate(1, 0, 300);
1421 allocation.SetBitrate(2, 0, 500);
1422 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1423 EXPECT_EQ(
1424 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1425 // Layer 2 off
1426 allocation.SetBitrate(2, 0, 0);
1427 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1428 EXPECT_EQ(
1429 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1430 // Layer 2 back on
1431 allocation.SetBitrate(2, 0, 500);
1432 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1433 EXPECT_EQ(
1434 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1435 allocation.SetBitrate(0, 0, 0);
1436 allocation.SetBitrate(1, 0, 0);
1437 allocation.SetBitrate(2, 0, 0);
1438 // All layers off
1439 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1440 EXPECT_EQ(
1441 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1442}
1443
1444TEST_F(SendStatisticsProxyTest,
1445 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1446 VideoCodec codec;
1447 // 3 layers
1448 codec.simulcastStream[0].active = true;
1449 codec.simulcastStream[1].active = true;
1450 codec.simulcastStream[2].active = true;
1451 VideoBitrateAllocation allocation;
1452 allocation.SetBitrate(0, 0, 500);
1453 allocation.SetBitrate(1, 0, 500);
1454 allocation.SetBitrate(2, 0, 500);
1455 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1456 EXPECT_EQ(
1457 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1458
1459 // Down to one layer now, triggered by a config change
1460 codec.numberOfSimulcastStreams = 1;
1461 codec.simulcastStream[1].active = false;
1462 codec.simulcastStream[2].active = false;
1463 allocation.SetBitrate(0, 0, 100);
1464 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1465 EXPECT_EQ(
1466 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1467
1468 // Up to 3 layers again.
1469 codec.numberOfSimulcastStreams = 3;
1470 codec.simulcastStream[1].active = true;
1471 codec.simulcastStream[2].active = true;
1472 allocation.SetBitrate(0, 0, 500);
1473 allocation.SetBitrate(1, 0, 500);
1474 allocation.SetBitrate(2, 0, 500);
1475 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1476 EXPECT_EQ(
1477 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1478}
1479
1480TEST_F(SendStatisticsProxyTest,
1481 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1482 VideoCodec codec;
1483 codec.simulcastStream[0].active = true;
1484 codec.spatialLayers[0].active = true;
1485 codec.spatialLayers[1].active = true;
1486 codec.spatialLayers[2].active = true;
1487 VideoBitrateAllocation allocation;
1488 allocation.SetBitrate(0, 0, 500);
1489 allocation.SetBitrate(1, 0, 500);
1490 allocation.SetBitrate(2, 0, 500);
1491 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1492 EXPECT_EQ(
1493 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1494
1495 // Down to one layer now, triggered by a config change
1496 codec.spatialLayers[1].active = false;
1497 codec.spatialLayers[2].active = false;
1498 allocation.SetBitrate(0, 0, 100);
1499 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1500 EXPECT_EQ(
1501 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1502
1503 // Up to 3 layers again.
1504 codec.spatialLayers[1].active = true;
1505 codec.spatialLayers[2].active = true;
1506 allocation.SetBitrate(0, 0, 500);
1507 allocation.SetBitrate(1, 0, 500);
1508 allocation.SetBitrate(2, 0, 500);
1509 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1510 EXPECT_EQ(
1511 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1512}
1513
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001514TEST_F(SendStatisticsProxyTest,
1515 QualityLimitationReasonsAreCorrectForContentType) {
1516 // Realtime case.
1517 // Configure two streams.
1518 VideoEncoderConfig config;
1519 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1520 config.number_of_streams = 2;
1521 VideoStream stream1;
1522 stream1.width = kWidth / 2;
1523 stream1.height = kHeight / 2;
1524 VideoStream stream2;
1525 stream2.width = kWidth;
1526 stream2.height = kHeight;
1527 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1528 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1529 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1530 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1531 QualityLimitationReason::kNone);
1532 // Bw disabled one layer.
1533 VideoCodec codec;
1534 codec.numberOfSimulcastStreams = 2;
1535 codec.simulcastStream[0].active = true;
1536 codec.simulcastStream[1].active = true;
1537 VideoBitrateAllocation allocation;
1538 // Some positive bitrate only on the first stream.
1539 allocation.SetBitrate(0, 0, 10000);
1540 allocation.SetBitrate(1, 0, 0);
1541 allocation.set_bw_limited(true);
1542 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1543 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1544 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1545 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1546 QualityLimitationReason::kBandwidth);
1547 // Bw enabled all layers.
1548 allocation.SetBitrate(1, 0, 10000);
1549 allocation.set_bw_limited(false);
1550 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1551 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1552 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1553 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1554 QualityLimitationReason::kNone);
1555
1556 // Screencast case
1557 // Configure two streams.
1558 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1559 config.number_of_streams = 2;
1560 stream1.width = kWidth;
1561 stream1.height = kHeight;
1562 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1563 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1564 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1565 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1566 QualityLimitationReason::kNone);
1567 // Bw disabled one layer.
1568 // Some positive bitrate only on the second stream.
1569 allocation.SetBitrate(0, 0, 10000);
1570 allocation.SetBitrate(1, 0, 0);
1571 allocation.set_bw_limited(true);
1572 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1573 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1574 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1575 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1576 QualityLimitationReason::kBandwidth);
1577 // Bw enabled all layers.
1578 allocation.SetBitrate(1, 0, 10000);
1579 allocation.set_bw_limited(false);
1580 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1581 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1582 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1583 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1584 QualityLimitationReason::kNone);
1585}
1586
asapersson59bac1a2016-01-07 23:36:00 -08001587TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001588 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001589 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1590
Pera48ddb72016-09-29 11:48:50 +02001591 // No switch, stats should not be updated.
1592 VideoEncoderConfig config;
1593 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001594 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001595 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001596
1597 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001598 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001599 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001600 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001601}
1602
asapersson320e45a2016-11-29 01:40:35 -08001603TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1604 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1605 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001606
asapersson320e45a2016-11-29 01:40:35 -08001607 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001608 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1609 EXPECT_METRIC_EQ(
1610 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1611 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1612 EXPECT_METRIC_EQ(
1613 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001614}
1615
1616TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001617 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001618 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001619 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1620 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1621 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001622 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001623
1624 // Not enough samples, stats should not be updated.
1625 for (int i = 0; i < kMinSamples - 1; ++i) {
1626 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001627 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001628 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1629 }
Åsa Persson0122e842017-10-16 12:19:23 +02001630 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001631 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1632 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001633
1634 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001635 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001636 for (int i = 0; i < kMinSamples; ++i) {
1637 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001638 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001639 encoded_image._encodedWidth = kWidth;
1640 encoded_image._encodedHeight = kHeight;
1641 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1642 encoded_image._encodedWidth = kWidth / 2;
1643 encoded_image._encodedHeight = kHeight / 2;
1644 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1645 }
1646
asapersson320e45a2016-11-29 01:40:35 -08001647 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001648 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1649 EXPECT_METRIC_EQ(
1650 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1651 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1652 EXPECT_METRIC_EQ(
1653 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001654}
1655
1656TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1657 const int kFps = 20;
1658 const int kMinPeriodicSamples = 6;
1659 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1660 for (int i = 0; i <= frames; ++i) {
1661 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1662 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1663 }
1664 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001665 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1666 EXPECT_METRIC_EQ(
1667 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001668}
1669
1670TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1671 EncodedImage encoded_image;
1672 const int kFps = 20;
1673 const int kMinPeriodicSamples = 6;
1674 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001675 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001676 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001677 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001678 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1679 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001680 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1681 }
1682 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001683 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1684 EXPECT_METRIC_EQ(
1685 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001686}
1687
1688TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1689 const int kFps = 20;
1690 const int kSuspendTimeMs = 10000;
1691 const int kMinPeriodicSamples = 6;
1692 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1693 for (int i = 0; i < frames; ++i) {
1694 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1695 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1696 }
1697 // Suspend.
1698 statistics_proxy_->OnSuspendChange(true);
1699 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1700
1701 for (int i = 0; i < frames; ++i) {
1702 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1703 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1704 }
1705 // Suspended time interval should not affect the framerate.
1706 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001707 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1708 EXPECT_METRIC_EQ(
1709 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001710}
1711
1712TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1713 EncodedImage encoded_image;
1714 const int kFps = 20;
1715 const int kSuspendTimeMs = 10000;
1716 const int kMinPeriodicSamples = 6;
1717 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001718 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001719 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001720 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001721 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1722 }
1723 // Suspend.
1724 statistics_proxy_->OnSuspendChange(true);
1725 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1726
Åsa Persson0122e842017-10-16 12:19:23 +02001727 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001728 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001729 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001730 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1731 }
1732 // Suspended time interval should not affect the framerate.
1733 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001734 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1735 EXPECT_METRIC_EQ(
1736 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001737}
1738
asaperssonf4e44af2017-04-19 02:01:06 -07001739TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001740 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1741 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001742
1743 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1744 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1745
1746 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001747 EXPECT_METRIC_EQ(
1748 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001749}
1750
1751TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001752 VideoAdaptationCounters cpu_counts;
1753 VideoAdaptationCounters quality_counts;
1754 cpu_counts.resolution_adaptations = 0;
1755 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001756
perkj803d97f2016-11-01 11:45:46 -07001757 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1758 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1759
Evan Shrubsoledff79252020-04-16 11:34:32 +02001760 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001761 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1762 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001763
1764 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1765 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1766
1767 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001768 EXPECT_METRIC_EQ(
1769 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1770 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001771 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1772}
1773
asapersson4374a092016-07-27 00:39:09 -07001774TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1775 const int64_t kTimeSec = 3;
1776 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1777 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001778 EXPECT_METRIC_EQ(
1779 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1780 EXPECT_METRIC_EQ(
1781 1,
1782 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001783}
1784
1785TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1786 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1787 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001788 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001789}
1790
asapersson66d4b372016-12-19 06:50:53 -08001791TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1792 // First RTP packet sent.
1793 UpdateDataCounters(kFirstSsrc);
1794
1795 // Min runtime has passed.
1796 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1797 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001798 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1799 EXPECT_METRIC_EQ(1,
1800 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001801}
1802
1803TEST_F(SendStatisticsProxyTest,
1804 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1805 // First RTP packet sent.
1806 UpdateDataCounters(kFirstSsrc);
1807
1808 // Min runtime has not passed.
1809 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1810 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001811 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1812 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001813}
1814
1815TEST_F(SendStatisticsProxyTest,
1816 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1817 // First RTP packet not sent.
1818 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1819 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001820 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001821}
1822
1823TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1824 // First RTP packet sent and min runtime passed.
1825 UpdateDataCounters(kFirstSsrc);
1826
1827 // No change. Video: 10000 ms, paused: 0 ms (0%).
1828 statistics_proxy_->OnSetEncoderTargetRate(50000);
1829 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1830 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1831
1832 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001833 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1834 EXPECT_METRIC_EQ(1,
1835 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1836 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1837 EXPECT_METRIC_EQ(1,
1838 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001839}
1840
1841TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1842 // First RTP packet sent and min runtime passed.
1843 UpdateDataCounters(kFirstSsrc);
1844
1845 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1846 statistics_proxy_->OnSetEncoderTargetRate(50000);
1847 fake_clock_.AdvanceTimeMilliseconds(7000);
1848 statistics_proxy_->OnSetEncoderTargetRate(0);
1849 fake_clock_.AdvanceTimeMilliseconds(3000);
1850 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1851
1852 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001853 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1854 EXPECT_METRIC_EQ(1,
1855 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1856 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1857 EXPECT_METRIC_EQ(1,
1858 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001859}
1860
1861TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1862 // First RTP packet sent.
1863 UpdateDataCounters(kFirstSsrc);
1864
1865 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1866 statistics_proxy_->OnSetEncoderTargetRate(0);
1867 fake_clock_.AdvanceTimeMilliseconds(1000);
1868 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1869 fake_clock_.AdvanceTimeMilliseconds(7000);
1870 statistics_proxy_->OnSetEncoderTargetRate(60000);
1871 fake_clock_.AdvanceTimeMilliseconds(3000);
1872 statistics_proxy_->OnSetEncoderTargetRate(0);
1873 fake_clock_.AdvanceTimeMilliseconds(250);
1874 statistics_proxy_->OnSetEncoderTargetRate(0);
1875 fake_clock_.AdvanceTimeMilliseconds(750);
1876 statistics_proxy_->OnSetEncoderTargetRate(60000);
1877 fake_clock_.AdvanceTimeMilliseconds(5000);
1878 statistics_proxy_->OnSetEncoderTargetRate(50000);
1879 fake_clock_.AdvanceTimeMilliseconds(4000);
1880 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1881
1882 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001883 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1884 EXPECT_METRIC_EQ(1,
1885 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1886 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1887 EXPECT_METRIC_EQ(1,
1888 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001889}
1890
1891TEST_F(SendStatisticsProxyTest,
1892 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1893 // First RTP packet sent.
1894 UpdateDataCounters(kFirstSsrc);
1895 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1896
1897 // Min runtime has not passed.
1898 statistics_proxy_->OnSetEncoderTargetRate(50000);
1899 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1900 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1901
1902 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001903 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001904}
1905
asapersson118ef002016-03-31 00:00:19 -07001906TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001907 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001908 CodecSpecificInfo codec_info;
1909 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001910
perkj803d97f2016-11-01 11:45:46 -07001911 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001912 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001913 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001914 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001915 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001916 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001917 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001918 }
1919 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001920 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1921 EXPECT_METRIC_EQ(
1922 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1923 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1924 EXPECT_METRIC_EQ(
1925 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001926}
1927
1928TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01001929 test::ScopedKeyValueConfig field_trials;
asapersson118ef002016-03-31 00:00:19 -07001930 VideoSendStream::Config config(nullptr);
1931 config.rtp.ssrcs.push_back(kFirstSsrc);
1932 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01001933 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1934 field_trials));
asapersson118ef002016-03-31 00:00:19 -07001935
asapersson118ef002016-03-31 00:00:19 -07001936 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001937 CodecSpecificInfo codec_info;
1938 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001939
perkj803d97f2016-11-01 11:45:46 -07001940 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001941 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001942 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001943 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001944 }
1945 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001946 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1947 EXPECT_METRIC_EQ(1,
1948 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001949}
1950
asapersson5265fed2016-04-18 02:58:47 -07001951TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001952 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001953 CodecSpecificInfo codec_info;
1954 codec_info.codecType = kVideoCodecVP9;
1955 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001956
perkj803d97f2016-11-01 11:45:46 -07001957 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001958 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001959 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001960 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001961 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001962 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001963 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001964 }
1965 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001966 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1967 EXPECT_METRIC_EQ(
1968 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1969 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1970 EXPECT_METRIC_EQ(
1971 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001972}
1973
1974TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01001975 test::ScopedKeyValueConfig field_trials;
asapersson5265fed2016-04-18 02:58:47 -07001976 VideoSendStream::Config config(nullptr);
1977 config.rtp.ssrcs.push_back(kFirstSsrc);
1978 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01001979 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1980 field_trials));
asapersson5265fed2016-04-18 02:58:47 -07001981
asapersson5265fed2016-04-18 02:58:47 -07001982 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001983 CodecSpecificInfo codec_info;
1984 codec_info.codecType = kVideoCodecVP9;
1985 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001986
perkj803d97f2016-11-01 11:45:46 -07001987 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001988 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001989 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001990 }
1991 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001992 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1993 EXPECT_METRIC_EQ(1,
1994 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001995}
1996
asapersson827cab32016-11-02 09:08:47 -07001997TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1998 EncodedImage encoded_image;
1999 CodecSpecificInfo codec_info;
2000 codec_info.codecType = kVideoCodecH264;
2001
2002 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002003 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07002004 encoded_image.qp_ = kQpIdx0;
2005 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002006 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02002007 encoded_image.qp_ = kQpIdx1;
2008 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07002009 }
2010 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002011 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
2012 EXPECT_METRIC_EQ(
2013 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
2014 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
2015 EXPECT_METRIC_EQ(
2016 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07002017}
2018
asapersson4ee70462016-10-31 04:05:12 -07002019TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002020 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
2021 // Configure one stream.
2022 VideoEncoderConfig config;
2023 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2024 VideoStream stream1;
2025 stream1.width = kWidth;
2026 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002027 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002028
2029 const int64_t kMaxEncodedFrameWindowMs = 800;
2030 const int kFps = 20;
2031 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2032 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2033 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2034
2035 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002036 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002037 encoded_image._encodedWidth = kWidth;
2038 encoded_image._encodedHeight = kHeight;
2039 for (int i = 0; i < kMinSamples; ++i) {
2040 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002041 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2042 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002043 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002044 }
asapersson4ee70462016-10-31 04:05:12 -07002045
2046 // Histograms are updated when the statistics_proxy_ is deleted.
2047 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002048 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2049 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2050 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2051 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002052}
2053
2054TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002055 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
2056 // Configure two streams.
2057 VideoEncoderConfig config;
2058 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2059 VideoStream stream1;
2060 stream1.width = kWidth / 2;
2061 stream1.height = kHeight / 2;
2062 VideoStream stream2;
2063 stream2.width = kWidth;
2064 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002065 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002066
2067 const int64_t kMaxEncodedFrameWindowMs = 800;
2068 const int kFps = 20;
2069 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2070 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2071 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2072
2073 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07002074 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002075 for (int i = 0; i < kMinSamples; ++i) {
2076 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002077 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2078 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002079 encoded_image._encodedWidth = kWidth;
2080 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07002081 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002082 encoded_image._encodedWidth = kWidth / 2;
2083 encoded_image._encodedHeight = kHeight / 2;
2084 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2085 }
asapersson4ee70462016-10-31 04:05:12 -07002086
2087 // Histograms are updated when the statistics_proxy_ is deleted.
2088 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002089 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2090 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2091 EXPECT_METRIC_EQ(
2092 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2093 0));
asapersson4ee70462016-10-31 04:05:12 -07002094 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002095 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2096 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002097}
2098
2099TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002100 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2101 // Configure two streams.
2102 VideoEncoderConfig config;
2103 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2104 VideoStream stream1;
2105 stream1.width = kWidth / 2;
2106 stream1.height = kHeight / 2;
2107 VideoStream stream2;
2108 stream2.width = kWidth;
2109 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002110 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002111
2112 const int64_t kMaxEncodedFrameWindowMs = 800;
2113 const int kFps = 20;
2114 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2115 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2116 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2117
2118 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002119 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002120 encoded_image._encodedWidth = kWidth / 2;
2121 encoded_image._encodedHeight = kHeight / 2;
2122 for (int i = 0; i < kMinSamples; ++i) {
2123 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002124 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2125 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002126 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002127 }
asapersson4ee70462016-10-31 04:05:12 -07002128
2129 // Histograms are updated when the statistics_proxy_ is deleted.
2130 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002131 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2132 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2133 EXPECT_METRIC_EQ(
2134 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2135 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002136 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002137 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2138 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2139 EXPECT_METRIC_EQ(
2140 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2141 1));
asapersson4ee70462016-10-31 04:05:12 -07002142}
2143
2144TEST_F(SendStatisticsProxyTest,
2145 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002146 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2147 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002148 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002149 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002150 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002151 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002152
2153 // Histograms are updated when the statistics_proxy_ is deleted.
2154 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002155 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002156 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002157 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2158 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002159}
2160
2161TEST_F(SendStatisticsProxyTest,
2162 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002163 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002164 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002165 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002166 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002167 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002168
2169 // Histograms are updated when the statistics_proxy_ is deleted.
2170 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002171 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002172 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002173 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2174 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002175 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002176 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2177 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002178}
2179
2180TEST_F(SendStatisticsProxyTest,
2181 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2182 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002183 VideoAdaptationCounters cpu_counts;
2184 VideoAdaptationCounters quality_counts;
2185 quality_counts.resolution_adaptations = kDownscales;
2186 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002187 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2188 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002189 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002190 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002191 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002192 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002193 // Histograms are updated when the statistics_proxy_ is deleted.
2194 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002195 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002196 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002197 EXPECT_METRIC_EQ(
2198 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2199 100));
asapersson4ee70462016-10-31 04:05:12 -07002200 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002201 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2202 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2203 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002204 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2205 kDownscales));
2206}
2207
2208TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2209 // Initially false.
2210 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002211
Åsa Perssonaa329e72017-12-15 15:54:44 +01002212 // Configure two streams.
2213 VideoEncoderConfig config;
2214 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002215 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002216 VideoStream stream1;
2217 stream1.width = kWidth / 2;
2218 stream1.height = kHeight / 2;
2219 VideoStream stream2;
2220 stream2.width = kWidth;
2221 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002222 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002223
Åsa Perssonaa329e72017-12-15 15:54:44 +01002224 // One stream encoded.
2225 EncodedImage encoded_image;
2226 encoded_image._encodedWidth = kWidth / 2;
2227 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002228
2229 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002230 VideoAdaptationCounters cpu_counts;
2231 VideoAdaptationCounters quality_counts;
2232 quality_counts.resolution_adaptations = 1;
2233 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2234 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002235 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2236 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002237 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2238 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002239
2240 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002241 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002242 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2243 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002244 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2245 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2246
2247 // Bw disabled one layer.
2248 VideoCodec codec;
2249 codec.numberOfSimulcastStreams = 2;
2250 codec.simulcastStream[0].active = true;
2251 codec.simulcastStream[1].active = true;
2252 VideoBitrateAllocation allocation;
2253 // Some positive bitrate only on the second stream.
2254 allocation.SetBitrate(1, 0, 10000);
2255 allocation.set_bw_limited(true);
2256 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2257 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002258
2259 // Revert for the next test.
2260 allocation.set_bw_limited(false);
2261 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2262 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2263
2264 // Internal encoder scaler reduced resolution.
2265 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2266 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002267}
2268
asapersson66d4b372016-12-19 06:50:53 -08002269TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2270 // Initially zero.
2271 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2272
2273 const int kBitrate = 100000;
2274 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2275 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2276
2277 statistics_proxy_->OnSetEncoderTargetRate(0);
2278 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2279}
2280
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002281TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002282 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002283 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2284 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002285 1;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002286 // From ReportBlockDataObserver.
2287 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2288 RTCPReportBlock report_block;
2289 report_block.source_ssrc = excluded_ssrc;
2290 ReportBlockData data;
2291 data.SetReportBlock(report_block, 0);
2292 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002293
2294 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002295 uint32_t total = 0;
2296 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002297 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002298 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002299
2300 // From FrameCountObserver.
2301 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002302 FrameCounts frame_counts;
2303 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002304 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002305
2306 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2307 EXPECT_TRUE(stats.substreams.empty());
2308}
2309
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002310TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2311 static const int kEncodedWidth = 123;
2312 static const int kEncodedHeight = 81;
2313 EncodedImage encoded_image;
2314 encoded_image._encodedWidth = kEncodedWidth;
2315 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002316 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002317
kjellander02b3d272016-04-20 05:05:54 -07002318 CodecSpecificInfo codec_info;
2319 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002320
kjellander02b3d272016-04-20 05:05:54 -07002321 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002322 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002323 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002324
2325 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002326 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2327 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2328 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2329 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002330
2331 // Forward almost to timeout, this should not have removed stats.
2332 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2333 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002334 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2335 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002336
2337 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2338 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002339 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2340 RTCPReportBlock report_block;
2341 report_block.source_ssrc = config_.rtp.ssrcs[0];
2342 ReportBlockData data;
2343 data.SetReportBlock(report_block, 0);
2344 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002345
2346 // Report stats for second SSRC to make sure it's not outdated along with the
2347 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002348 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002349
2350 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2351 // reported, but substream 1 should.
2352 fake_clock_.AdvanceTimeMilliseconds(1);
2353 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002354 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2355 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2356 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2357 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002358}
2359
Peter Boström20f3f942015-05-15 11:33:39 +02002360TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2361 static const int kEncodedWidth = 123;
2362 static const int kEncodedHeight = 81;
2363 EncodedImage encoded_image;
2364 encoded_image._encodedWidth = kEncodedWidth;
2365 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002366 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002367
kjellander02b3d272016-04-20 05:05:54 -07002368 CodecSpecificInfo codec_info;
2369 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002370
kjellander02b3d272016-04-20 05:05:54 -07002371 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002372 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002373 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002374
2375 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2376 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2377 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2378 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2379 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2380 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2381}
2382
2383TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002384 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002385 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2386 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2387 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2388
2389 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2390
2391 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002392 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002393 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002394 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002395 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2396 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2397 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2398}
2399
sprang07fb9be2016-02-24 07:55:00 -08002400TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2401 RtcpPacketTypeCounterObserver* proxy =
2402 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2403 RtcpPacketTypeCounter counters;
sprang07fb9be2016-02-24 07:55:00 -08002404 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2405 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2406
2407 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2408
2409 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2410 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2411 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2412 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2413 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2414
2415 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2416 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2417
2418 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002419 VideoEncoderConfig config;
2420 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002421 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002422
Ying Wangef3998f2019-12-09 13:06:53 +01002423 EXPECT_METRIC_EQ(
2424 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2425 EXPECT_METRIC_EQ(
2426 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2427 EXPECT_METRIC_EQ(
2428 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2429 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2430 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002431
2432 const int kRate = 60 * 2; // Packets per minute with two streams.
2433
Ying Wangef3998f2019-12-09 13:06:53 +01002434 EXPECT_METRIC_EQ(
2435 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2436 1 * kRate));
2437 EXPECT_METRIC_EQ(
2438 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2439 2 * kRate));
2440 EXPECT_METRIC_EQ(
2441 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2442 3 * kRate));
2443 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002444 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2445 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002446
2447 // New start time but same counter values.
2448 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2449 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2450
2451 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2452
2453 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2454 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2455 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2456 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2457 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2458
2459 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2460 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2461
2462 SetUp(); // Reset stats proxy also causes histograms to be reported.
2463
Ying Wangef3998f2019-12-09 13:06:53 +01002464 EXPECT_METRIC_EQ(
2465 1, metrics::NumSamples(
2466 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2467 EXPECT_METRIC_EQ(1,
2468 metrics::NumSamples(
2469 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2470 EXPECT_METRIC_EQ(1,
2471 metrics::NumSamples(
2472 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2473 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002474 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002475 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2476
Ying Wangef3998f2019-12-09 13:06:53 +01002477 EXPECT_METRIC_EQ(
2478 1,
2479 metrics::NumEvents(
2480 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2481 EXPECT_METRIC_EQ(
2482 1,
2483 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2484 2 * kRate));
2485 EXPECT_METRIC_EQ(
2486 1,
2487 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2488 3 * kRate));
2489 EXPECT_METRIC_EQ(
2490 1, metrics::NumEvents(
2491 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2492 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002493}
2494
Henrik Boströmf45ca372020-03-24 13:30:50 +01002495TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2496 StreamDataCountersCallback* proxy =
2497 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2498 StreamDataCounters counters;
2499 proxy->DataCountersUpdated(counters, kFirstSsrc);
2500 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2501
2502 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2503 VideoSendStream::StreamStats::StreamType::kRtx);
2504 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2505 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2506 VideoSendStream::StreamStats::StreamType::kRtx);
2507 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2508}
2509
asaperssona6a699a2016-11-25 03:52:46 -08002510TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002511 test::ScopedKeyValueConfig field_trials;
2512 statistics_proxy_.reset(new SendStatisticsProxy(
2513 &fake_clock_, GetTestConfigWithFlexFec(),
2514 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 03:52:46 -08002515
2516 StreamDataCountersCallback* proxy =
2517 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2518 StreamDataCounters counters;
2519 proxy->DataCountersUpdated(counters, kFirstSsrc);
2520 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2521
Henrik Boströmf45ca372020-03-24 13:30:50 +01002522 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2523 VideoSendStream::StreamStats::StreamType::kFlexfec);
2524 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2525 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2526 VideoSendStream::StreamStats::StreamType::kFlexfec);
2527 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002528}
2529
2530TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002531 test::ScopedKeyValueConfig field_trials;
2532 statistics_proxy_.reset(new SendStatisticsProxy(
2533 &fake_clock_, GetTestConfigWithFlexFec(),
2534 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 03:52:46 -08002535
2536 StreamDataCountersCallback* proxy =
2537 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002538 StreamDataCounters counters;
2539 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002540
asapersson93e1e232017-02-06 05:18:35 -08002541 const int kMinRequiredPeriodSamples = 8;
2542 const int kPeriodIntervalMs = 2000;
2543 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2544 counters.transmitted.packets += 20;
2545 counters.transmitted.header_bytes += 500;
2546 counters.transmitted.padding_bytes += 1000;
2547 counters.transmitted.payload_bytes += 2000;
2548 counters.retransmitted.packets += 2;
2549 counters.retransmitted.header_bytes += 25;
2550 counters.retransmitted.padding_bytes += 100;
2551 counters.retransmitted.payload_bytes += 250;
2552 counters.fec = counters.retransmitted;
2553 rtx_counters.transmitted = counters.transmitted;
2554 // Advance one interval and update counters.
2555 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2556 proxy->DataCountersUpdated(counters, kFirstSsrc);
2557 proxy->DataCountersUpdated(counters, kSecondSsrc);
2558 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2559 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2560 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2561 }
asaperssona6a699a2016-11-25 03:52:46 -08002562
asaperssona6a699a2016-11-25 03:52:46 -08002563 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002564 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002565 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2566 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002567 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002568 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2569 EXPECT_METRIC_EQ(1,
2570 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002571 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002572 EXPECT_METRIC_EQ(1,
2573 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2574 EXPECT_METRIC_EQ(
2575 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002576 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002577 EXPECT_METRIC_EQ(
2578 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2579 EXPECT_METRIC_EQ(
2580 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002581 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002582 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2583 EXPECT_METRIC_EQ(1,
2584 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002585 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002586 EXPECT_METRIC_EQ(
2587 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2588 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002589 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002590}
2591
Erik Språng22c2b482016-03-01 09:40:42 +01002592TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2593 StreamDataCountersCallback* proxy =
2594 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2595 StreamDataCounters counters;
2596 StreamDataCounters rtx_counters;
2597 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002598
asapersson93e1e232017-02-06 05:18:35 -08002599 const int kMinRequiredPeriodSamples = 8;
2600 const int kPeriodIntervalMs = 2000;
2601 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2602 counters.transmitted.packets += 20;
2603 counters.transmitted.header_bytes += 500;
2604 counters.transmitted.padding_bytes += 1000;
2605 counters.transmitted.payload_bytes += 2000;
2606 counters.retransmitted.packets += 2;
2607 counters.retransmitted.header_bytes += 25;
2608 counters.retransmitted.padding_bytes += 100;
2609 counters.retransmitted.payload_bytes += 250;
2610 counters.fec = counters.retransmitted;
2611 rtx_counters.transmitted = counters.transmitted;
2612 // Advance one interval and update counters.
2613 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2614 proxy->DataCountersUpdated(counters, kFirstSsrc);
2615 proxy->DataCountersUpdated(counters, kSecondSsrc);
2616 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2617 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2618 }
Erik Språng22c2b482016-03-01 09:40:42 +01002619
2620 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002621 VideoEncoderConfig config;
2622 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002623 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002624
asapersson93e1e232017-02-06 05:18:35 -08002625 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002626 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2627 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002628 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002629 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2630 EXPECT_METRIC_EQ(1,
2631 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002632 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002633 EXPECT_METRIC_EQ(1,
2634 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2635 EXPECT_METRIC_EQ(
2636 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002637 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002638 EXPECT_METRIC_EQ(
2639 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2640 EXPECT_METRIC_EQ(
2641 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002642 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002643 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2644 EXPECT_METRIC_EQ(1,
2645 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002646 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002647 EXPECT_METRIC_EQ(
2648 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2649 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002650 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002651
asapersson93e1e232017-02-06 05:18:35 -08002652 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002653 // Double counter values, this should result in the same counts as before but
2654 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002655 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2656 counters.transmitted.packets += 20;
2657 counters.transmitted.header_bytes += 500;
2658 counters.transmitted.padding_bytes += 1000;
2659 counters.transmitted.payload_bytes += 2000;
2660 counters.retransmitted.packets += 2;
2661 counters.retransmitted.header_bytes += 25;
2662 counters.retransmitted.padding_bytes += 100;
2663 counters.retransmitted.payload_bytes += 250;
2664 counters.fec = counters.retransmitted;
2665 rtx_counters.transmitted = counters.transmitted;
2666 // Advance one interval and update counters.
2667 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2668 proxy->DataCountersUpdated(counters, kFirstSsrc);
2669 proxy->DataCountersUpdated(counters, kSecondSsrc);
2670 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2671 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2672 }
Erik Språng22c2b482016-03-01 09:40:42 +01002673
asapersson93e1e232017-02-06 05:18:35 -08002674 // Reset stats proxy also causes histograms to be reported.
2675 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002676
asapersson93e1e232017-02-06 05:18:35 -08002677 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002678 EXPECT_METRIC_EQ(
2679 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2680 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002681 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2682 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002683 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002684 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002685 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2686 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002687 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002688 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2689 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2690 EXPECT_METRIC_EQ(
2691 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2692 12));
asapersson93e1e232017-02-06 05:18:35 -08002693 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002694 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2695 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2696 EXPECT_METRIC_EQ(
2697 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2698 16));
asapersson93e1e232017-02-06 05:18:35 -08002699 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002700 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002701 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002702 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2703 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002704 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002705 EXPECT_METRIC_EQ(
2706 1, metrics::NumSamples(
2707 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2708 EXPECT_METRIC_EQ(
2709 1, metrics::NumEvents(
2710 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002711}
Erik Språng22c2b482016-03-01 09:40:42 +01002712
asapersson93e1e232017-02-06 05:18:35 -08002713TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2714 StreamDataCountersCallback* proxy =
2715 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2716 StreamDataCounters counters;
2717 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002718
asapersson93e1e232017-02-06 05:18:35 -08002719 const int kMinRequiredPeriodSamples = 8;
2720 const int kPeriodIntervalMs = 2000;
2721 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2722 counters.transmitted.packets += 20;
2723 counters.transmitted.header_bytes += 500;
2724 counters.transmitted.payload_bytes += 2000;
2725 counters.fec = counters.retransmitted;
2726 // Advance one interval and update counters.
2727 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2728 proxy->DataCountersUpdated(counters, kFirstSsrc);
2729 }
2730
2731 // RTX enabled. No data sent over RTX.
2732 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002733 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2734 EXPECT_METRIC_EQ(1,
2735 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002736}
2737
2738TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002739 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 05:18:35 -08002740 VideoSendStream::Config config(nullptr);
2741 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2742 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01002743 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2744 field_trials));
asapersson93e1e232017-02-06 05:18:35 -08002745
2746 StreamDataCountersCallback* proxy =
2747 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2748 StreamDataCounters counters;
2749
2750 const int kMinRequiredPeriodSamples = 8;
2751 const int kPeriodIntervalMs = 2000;
2752 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2753 counters.transmitted.packets += 20;
2754 counters.transmitted.header_bytes += 500;
2755 counters.transmitted.payload_bytes += 2000;
2756 counters.fec = counters.retransmitted;
2757 // Advance one interval and update counters.
2758 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2759 proxy->DataCountersUpdated(counters, kFirstSsrc);
2760 }
2761
2762 // RTX not enabled.
2763 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002764 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002765}
2766
2767TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2768 StreamDataCountersCallback* proxy =
2769 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2770 StreamDataCounters counters;
2771 StreamDataCounters rtx_counters;
2772
2773 const int kMinRequiredPeriodSamples = 8;
2774 const int kPeriodIntervalMs = 2000;
2775 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2776 counters.transmitted.packets += 20;
2777 counters.transmitted.header_bytes += 500;
2778 counters.transmitted.payload_bytes += 2000;
2779 // Advance one interval and update counters.
2780 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2781 proxy->DataCountersUpdated(counters, kFirstSsrc);
2782 }
2783
2784 // FEC enabled. No FEC data sent.
2785 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002786 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2787 EXPECT_METRIC_EQ(1,
2788 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002789}
2790
2791TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002792 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 05:18:35 -08002793 VideoSendStream::Config config(nullptr);
2794 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2795 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01002796 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2797 field_trials));
asapersson93e1e232017-02-06 05:18:35 -08002798
2799 StreamDataCountersCallback* proxy =
2800 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2801 StreamDataCounters counters;
2802
2803 const int kMinRequiredPeriodSamples = 8;
2804 const int kPeriodIntervalMs = 2000;
2805 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2806 counters.transmitted.packets += 20;
2807 counters.transmitted.header_bytes += 500;
2808 counters.transmitted.payload_bytes += 2000;
2809 counters.fec = counters.retransmitted;
2810 // Advance one interval and update counters.
2811 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2812 proxy->DataCountersUpdated(counters, kFirstSsrc);
2813 }
2814
2815 // FEC not enabled.
2816 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002817 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002818}
2819
asapersson8d75ac72017-09-15 06:41:15 -07002820TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002821 const std::string kName = "encoderName";
2822 statistics_proxy_->OnEncoderImplementationChanged(kName);
2823 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002824}
2825
Sergey Silkinbb081a62018-09-04 18:34:22 +02002826TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2827 static const int kEncodedWidth = 123;
2828 static const int kEncodedHeight = 81;
2829 EncodedImage encoded_image;
2830 encoded_image._encodedWidth = kEncodedWidth;
2831 encoded_image._encodedHeight = kEncodedHeight;
2832 encoded_image.SetSpatialIndex(0);
2833
2834 CodecSpecificInfo codec_info;
2835 codec_info.codecType = kVideoCodecVP9;
2836
2837 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002838 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002839 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2840 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2841 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2842 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2843
2844 // Top layer updates resolution.
2845 encoded_image._encodedWidth = kEncodedWidth * 2;
2846 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002847 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002848 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2849 stats = statistics_proxy_->GetStats();
2850 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2851 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2852
2853 // Low layer of next frame doesn't update resolution.
2854 encoded_image._encodedWidth = kEncodedWidth;
2855 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002856 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002857 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2858 stats = statistics_proxy_->GetStats();
2859 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2860 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2861}
2862
asapersson8d75ac72017-09-15 06:41:15 -07002863class ForcedFallbackTest : public SendStatisticsProxyTest {
2864 public:
2865 explicit ForcedFallbackTest(const std::string& field_trials)
2866 : SendStatisticsProxyTest(field_trials) {
2867 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002868 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002869 encoded_image_._encodedWidth = kWidth;
2870 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002871 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002872 }
2873
2874 ~ForcedFallbackTest() override {}
2875
2876 protected:
2877 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002878 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2879
asapersson8d75ac72017-09-15 06:41:15 -07002880 // First frame is not updating stats, insert initial frame.
2881 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2882 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2883 }
2884 for (int i = 0; i < num_frames; ++i) {
2885 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2886 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2887 }
2888 // Add frame to include last time interval.
2889 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2890 }
2891
2892 EncodedImage encoded_image_;
2893 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002894 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002895 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2896 const int kFrameIntervalMs = 1000;
2897 const int kMinFrames = 20; // Min run time 20 sec.
2898};
2899
2900class ForcedFallbackDisabled : public ForcedFallbackTest {
2901 public:
2902 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002903 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2904 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002905};
2906
2907class ForcedFallbackEnabled : public ForcedFallbackTest {
2908 public:
2909 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002910 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2911 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002912};
2913
2914TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2915 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2916 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002917 EXPECT_METRIC_EQ(0,
2918 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2919 EXPECT_METRIC_EQ(
2920 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002921}
2922
2923TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2924 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002925 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002926 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002927 EXPECT_METRIC_EQ(1,
2928 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2929 EXPECT_METRIC_EQ(
2930 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2931 EXPECT_METRIC_EQ(
2932 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2933 EXPECT_METRIC_EQ(
2934 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002935}
2936
2937TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2938 codec_info_.codecType = kVideoCodecVP9;
2939 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2940 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002941 EXPECT_METRIC_EQ(0,
2942 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2943 EXPECT_METRIC_EQ(
2944 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002945}
2946
2947TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2948 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2949 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2950 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002951 EXPECT_METRIC_EQ(0,
2952 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2953 EXPECT_METRIC_EQ(
2954 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002955}
2956
2957TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002958 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002959 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2960 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002961 EXPECT_METRIC_EQ(0,
2962 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2963 EXPECT_METRIC_EQ(
2964 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002965}
2966
2967TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2968 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2969 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002970 EXPECT_METRIC_EQ(0,
2971 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2972 EXPECT_METRIC_EQ(
2973 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002974}
2975
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002976TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2977 InsertEncodedFrames(1, kFrameIntervalMs);
2978 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2979}
2980
2981TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2982 InsertEncodedFrames(1, kFrameIntervalMs);
2983 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2984}
2985
2986TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002987 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002988 InsertEncodedFrames(1, kFrameIntervalMs);
2989 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2990}
2991
2992TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2993 encoded_image_._encodedWidth = kWidth + 1;
2994 InsertEncodedFrames(1, kFrameIntervalMs);
2995 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2996}
2997
2998TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002999 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003000 InsertEncodedFrames(1, kFrameIntervalMs);
3001 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3002}
3003
3004TEST_F(ForcedFallbackDisabled,
3005 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
3006 encoded_image_._encodedWidth = kWidth + 1;
3007 statistics_proxy_->OnMinPixelLimitReached();
3008 InsertEncodedFrames(1, kFrameIntervalMs);
3009 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3010}
3011
asapersson8d75ac72017-09-15 06:41:15 -07003012TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
3013 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003014 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003015 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003016 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003017 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003018 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003019 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003020
3021 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003022 EXPECT_METRIC_EQ(1,
3023 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3024 EXPECT_METRIC_EQ(
3025 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3026 EXPECT_METRIC_EQ(
3027 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3028 EXPECT_METRIC_EQ(
3029 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003030}
3031
3032TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
3033 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
3034 const int kMaxFrameDiffMs = 2000;
3035
3036 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
3037 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003038 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003039 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003040 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003041 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003042 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003043 InsertEncodedFrames(20, 1000);
3044 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
3045 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003046 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003047 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07003048 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003049 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003050 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003051 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003052 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003053
3054 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003055 EXPECT_METRIC_EQ(1,
3056 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3057 EXPECT_METRIC_EQ(
3058 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3059 EXPECT_METRIC_EQ(
3060 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3061 EXPECT_METRIC_EQ(
3062 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003063}
3064
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003065TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
3066 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003067 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003068 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3069
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003070 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003071 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003072 EXPECT_METRIC_EQ(0,
3073 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3074 EXPECT_METRIC_EQ(
3075 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003076}
3077
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003078TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
3079 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003080 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003081 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3082
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003083 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003084 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003085 EXPECT_METRIC_EQ(1,
3086 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3087 EXPECT_METRIC_EQ(
3088 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003089}
3090
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00003091} // namespace webrtc