blob: af3b0208e269c02f42d54547ddf68350c55891f7 [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"
Evan Shrubsole9b235cd2022-12-06 10:09:10 +000024#include "api/video_codecs/scalability_mode.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020025#include "api/video_codecs/video_codec.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020026#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "system_wrappers/include/metrics.h"
Evan Shrubsole09da10e2022-10-14 14:38:31 +000028#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 12:52:48 +010030#include "test/scoped_key_value_config.h"
Jonas Oreland6c2dae22022-09-29 10:28:24 +020031#include "video/config/video_encoder_config.h"
Evan Shrubsole09da10e2022-10-14 14:38:31 +000032#include "video/video_stream_encoder_observer.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000033
34namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070035namespace {
Evan Shrubsole9b235cd2022-12-06 10:09:10 +000036
37using ::testing::Optional;
38
asapersson5265fed2016-04-18 02:58:47 -070039const uint32_t kFirstSsrc = 17;
40const uint32_t kSecondSsrc = 42;
41const uint32_t kFirstRtxSsrc = 18;
42const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080043const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080044const int kFpsPeriodicIntervalMs = 2000;
45const int kWidth = 640;
46const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070047const int kQpIdx0 = 21;
48const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010049const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080050const CodecSpecificInfo kDefaultCodecInfo = []() {
51 CodecSpecificInfo codec_info;
52 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080053 return codec_info;
54}();
Evan Shrubsoledff79252020-04-16 11:34:32 +020055
56const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
57 true);
58const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
59 true,
60 false);
61const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
62 false,
63 true);
64const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
asapersson5265fed2016-04-18 02:58:47 -070065} // namespace
sprang07fb9be2016-02-24 07:55:00 -080066
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000067class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000068 public:
asapersson8d75ac72017-09-15 06:41:15 -070069 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
70 explicit SendStatisticsProxyTest(const std::string& field_trials)
71 : override_field_trials_(field_trials),
72 fake_clock_(1234),
Åsa Persson90719572021-04-08 19:05:30 +020073 config_(GetTestConfig()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000074 virtual ~SendStatisticsProxyTest() {}
75
76 protected:
77 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070078 metrics::Reset();
Jonas Oreland8ca06132022-03-14 12:52:48 +010079 statistics_proxy_.reset(
80 new SendStatisticsProxy(&fake_clock_, GetTestConfig(),
81 VideoEncoderConfig::ContentType::kRealtimeVideo,
82 override_field_trials_));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000083 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010084 for (const auto& ssrc : config_.rtp.ssrcs) {
85 expected_.substreams[ssrc].type =
86 VideoSendStream::StreamStats::StreamType::kMedia;
87 }
88 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
89 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
90 expected_.substreams[ssrc].type =
91 VideoSendStream::StreamStats::StreamType::kRtx;
92 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
93 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000094 }
95
96 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070097 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080098 config.rtp.ssrcs.push_back(kFirstSsrc);
99 config.rtp.ssrcs.push_back(kSecondSsrc);
100 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
101 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -0700102 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000103 return config;
104 }
105
asaperssona6a699a2016-11-25 03:52:46 -0800106 VideoSendStream::Config GetTestConfigWithFlexFec() {
107 VideoSendStream::Config config(nullptr);
108 config.rtp.ssrcs.push_back(kFirstSsrc);
109 config.rtp.ssrcs.push_back(kSecondSsrc);
110 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
111 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -0800112 config.rtp.flexfec.payload_type = 50;
113 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +0100114 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -0800115 return config;
116 }
117
118 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
119 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
120 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
121 stats.substreams.find(ssrc);
122 EXPECT_NE(it, stats.substreams.end());
123 return it->second;
124 }
125
asapersson66d4b372016-12-19 06:50:53 -0800126 void UpdateDataCounters(uint32_t ssrc) {
127 StreamDataCountersCallback* proxy =
128 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
129 StreamDataCounters counters;
130 proxy->DataCountersUpdated(counters, ssrc);
131 }
132
sprang@webrtc.org09315702014-02-07 12:06:29 +0000133 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
Di Wu668dbf62021-02-27 00:29:15 -0800134 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000135 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
136 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000137 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000138 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000139
140 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000141 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000143 it != one.substreams.end(); ++it) {
144 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
145 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000146 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000147 const VideoSendStream::StreamStats& a = it->second;
148 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149
Henrik Boströmf45ca372020-03-24 13:30:50 +0100150 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000151 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
152 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000153 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000154 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
155 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000156
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000157 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
158 b.rtp_stats.transmitted.payload_bytes);
159 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
160 b.rtp_stats.transmitted.header_bytes);
161 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
162 b.rtp_stats.transmitted.padding_bytes);
163 EXPECT_EQ(a.rtp_stats.transmitted.packets,
164 b.rtp_stats.transmitted.packets);
165 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
166 b.rtp_stats.retransmitted.packets);
167 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000168
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200169 EXPECT_EQ(a.report_block_data.has_value(),
170 b.report_block_data.has_value());
171 if (a.report_block_data.has_value()) {
172 const RTCPReportBlock& a_rtcp_stats =
173 a.report_block_data->report_block();
174 const RTCPReportBlock& b_rtcp_stats =
175 b.report_block_data->report_block();
176 EXPECT_EQ(a_rtcp_stats.fraction_lost, b_rtcp_stats.fraction_lost);
177 EXPECT_EQ(a_rtcp_stats.packets_lost, b_rtcp_stats.packets_lost);
178 EXPECT_EQ(a_rtcp_stats.extended_highest_sequence_number,
179 b_rtcp_stats.extended_highest_sequence_number);
180 EXPECT_EQ(a_rtcp_stats.jitter, b_rtcp_stats.jitter);
181 }
sprang@webrtc.org09315702014-02-07 12:06:29 +0000182 }
183 }
184
Jonas Oreland8ca06132022-03-14 12:52:48 +0100185 test::ScopedKeyValueConfig override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000186 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800187 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000188 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000189 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000190};
191
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200192TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
193 ReportBlockDataObserver* callback = statistics_proxy_.get();
194 for (uint32_t ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000195 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200196 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200197 RTCPReportBlock report_block;
198 report_block.source_ssrc = ssrc;
199 report_block.packets_lost = offset;
200 report_block.extended_highest_sequence_number = offset + 1;
201 report_block.fraction_lost = offset + 2;
202 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200203 ReportBlockData data;
204 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200205 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200206
207 callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000208 }
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200209 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000210 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200211 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200212 RTCPReportBlock report_block;
213 report_block.source_ssrc = ssrc;
214 report_block.packets_lost = offset;
215 report_block.extended_highest_sequence_number = offset + 1;
216 report_block.fraction_lost = offset + 2;
217 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200218 ReportBlockData data;
219 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200220 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200221
222 callback->OnReportBlockDataUpdated(data);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000223 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000225 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000226}
227
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000228TEST_F(SendStatisticsProxyTest, Suspended) {
229 // Verify that the value is false by default.
230 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
231
232 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200233 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000234 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
235
236 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200237 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000238 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
239}
240
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000241TEST_F(SendStatisticsProxyTest, FrameCounts) {
242 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700243 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000244 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000245 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
246 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000247 FrameCounts frame_counts;
248 frame_counts.key_frames = offset;
249 frame_counts.delta_frames = offset + 1;
250 stats.frame_counts = frame_counts;
251 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000252 }
asapersson35151f32016-05-02 23:44:01 -0700253 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000254 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000255 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
256 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000257 FrameCounts frame_counts;
258 frame_counts.key_frames = offset;
259 frame_counts.delta_frames = offset + 1;
260 stats.frame_counts = frame_counts;
261 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000262 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000263
264 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000265 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000266}
267
268TEST_F(SendStatisticsProxyTest, DataCounters) {
269 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700270 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000271 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
272 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000273 size_t offset = ssrc * sizeof(StreamDataCounters);
274 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000275 counters.transmitted.payload_bytes = offset;
276 counters.transmitted.header_bytes = offset + 1;
277 counters.fec.packets = offset_uint32 + 2;
278 counters.transmitted.padding_bytes = offset + 3;
279 counters.retransmitted.packets = offset_uint32 + 4;
280 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000281 callback->DataCountersUpdated(counters, ssrc);
282 }
asapersson35151f32016-05-02 23:44:01 -0700283 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000284 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
285 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000286 size_t offset = ssrc * sizeof(StreamDataCounters);
287 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000288 counters.transmitted.payload_bytes = offset;
289 counters.transmitted.header_bytes = offset + 1;
290 counters.fec.packets = offset_uint32 + 2;
291 counters.transmitted.padding_bytes = offset + 3;
292 counters.retransmitted.packets = offset_uint32 + 4;
293 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000294 callback->DataCountersUpdated(counters, ssrc);
295 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000296
297 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000298 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000299}
300
301TEST_F(SendStatisticsProxyTest, Bitrate) {
302 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700303 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000304 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200305 uint32_t total = ssrc;
306 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000307 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700308 expected_.substreams[ssrc].total_bitrate_bps = total;
309 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000310 }
asapersson35151f32016-05-02 23:44:01 -0700311 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000312 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200313 uint32_t total = ssrc;
314 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000315 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700316 expected_.substreams[ssrc].total_bitrate_bps = total;
317 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000318 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000319
320 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000321 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000322}
323
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000324TEST_F(SendStatisticsProxyTest, SendSideDelay) {
325 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700326 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000327 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
328 // stream.
329 int avg_delay_ms = ssrc;
330 int max_delay_ms = ssrc + 1;
Henrik Boströmd8199212022-10-26 16:50:53 +0200331 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000332 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
333 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
334 }
asapersson35151f32016-05-02 23:44:01 -0700335 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000336 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
337 // stream.
338 int avg_delay_ms = ssrc;
339 int max_delay_ms = ssrc + 1;
Henrik Boströmd8199212022-10-26 16:50:53 +0200340 observer->SendSideDelayUpdated(avg_delay_ms, max_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;
343 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000344 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000345 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000346}
347
Peter Boströme4499152016-02-05 11:13:28 +0100348TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800349 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200350 int encode_usage_percent = 80;
351 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
352 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800353
354 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
355 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200356 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800357}
358
Henrik Boström5684af52019-04-02 15:05:21 +0200359TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
360 const int kEncodeUsagePercent = 0; // Don't care for this test.
361 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
362 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
363 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
364 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
365 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
366}
367
sakal43536c32016-10-24 01:46:43 -0700368TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
369 EncodedImage encoded_image;
370 CodecSpecificInfo codec_info;
371 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
372 for (uint32_t i = 1; i <= 3; ++i) {
373 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
374 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
375 }
376}
377
sakal87da4042016-10-31 06:53:47 -0700378TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
379 EncodedImage encoded_image;
380 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200381 auto ssrc = config_.rtp.ssrcs[0];
382 EXPECT_EQ(absl::nullopt,
383 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700384 encoded_image.qp_ = 3;
385 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200386 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700387 encoded_image.qp_ = 127;
388 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200389 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700390}
391
392TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
393 EncodedImage encoded_image;
394 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200395 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700396 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200397 EXPECT_EQ(absl::nullopt,
398 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700399 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200400 EXPECT_EQ(absl::nullopt,
401 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700402}
403
Evan Shrubsole9b235cd2022-12-06 10:09:10 +0000404TEST_F(SendStatisticsProxyTest,
405 OnSendEncodedImageSetsScalabilityModeOfCurrentLayer) {
406 EncodedImage encoded_image;
407 CodecSpecificInfo codec_info;
408 ScalabilityMode layer0_mode = ScalabilityMode::kL1T1;
409 ScalabilityMode layer1_mode = ScalabilityMode::kL1T3;
410 auto ssrc0 = config_.rtp.ssrcs[0];
411 auto ssrc1 = config_.rtp.ssrcs[1];
412 EXPECT_EQ(absl::nullopt,
413 statistics_proxy_->GetStats().substreams[ssrc0].scalability_mode);
414 EXPECT_EQ(absl::nullopt,
415 statistics_proxy_->GetStats().substreams[ssrc1].scalability_mode);
416 encoded_image.SetSpatialIndex(0);
417 codec_info.scalability_mode = layer0_mode;
418 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
419 EXPECT_THAT(statistics_proxy_->GetStats().substreams[ssrc0].scalability_mode,
420 layer0_mode);
421 EXPECT_EQ(absl::nullopt,
422 statistics_proxy_->GetStats().substreams[ssrc1].scalability_mode);
423 encoded_image.SetSpatialIndex(1);
424 codec_info.scalability_mode = layer1_mode;
425 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
426 EXPECT_THAT(statistics_proxy_->GetStats().substreams[ssrc0].scalability_mode,
427 layer0_mode);
428 EXPECT_THAT(statistics_proxy_->GetStats().substreams[ssrc1].scalability_mode,
429 layer1_mode);
430}
431
Henrik Boström23aff9b2019-05-20 15:15:38 +0200432TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
433 const uint32_t kTargetBytesPerSecond = 100000;
434 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
435 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
436
437 EncodedImage encoded_image;
438 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
439 // On the first frame we don't know the frame rate yet, calculation yields
440 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
Artem Titovab30d722021-07-27 16:22:11 +0200441 // increment by a full `kTargetBytesPerSecond`.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200442 EXPECT_EQ(kTargetBytesPerSecond,
443 statistics_proxy_->GetStats().total_encoded_bytes_target);
444}
445
446TEST_F(SendStatisticsProxyTest,
447 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
448 const uint32_t kTargetBytesPerSecond = 100000;
449 const int kInterframeDelayMs = 100;
450
451 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
Artem Titovab30d722021-07-27 16:22:11 +0200452 // `fake_clock_` for testing, but the RateTracker relies on a global clock.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200453 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
454 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
455 // this test can stop relying on rtc::ScopedFakeClock.
456 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100457 fake_global_clock.SetTime(
458 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200459
460 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
461 EncodedImage encoded_image;
462
463 // First frame
464 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
465 uint64_t first_total_encoded_bytes_target =
466 statistics_proxy_->GetStats().total_encoded_bytes_target;
467 // Second frame
468 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100469 fake_global_clock.SetTime(
470 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200471 encoded_image.SetTimestamp(encoded_image.Timestamp() +
472 90 * kInterframeDelayMs);
473 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
474
475 auto stats = statistics_proxy_->GetStats();
476 // By the time the second frame arrives, one frame has previously arrived
Artem Titovab30d722021-07-27 16:22:11 +0200477 // during a `kInterframeDelayMs` interval. The estimated encode frame rate at
Henrik Boström23aff9b2019-05-20 15:15:38 +0200478 // the second frame's arrival should be 10 FPS.
479 uint64_t delta_encoded_bytes_target =
480 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
481 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
482}
483
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200484TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
485 const int kInterframeDelayMs = 100;
Åsa Persson603e6e32021-08-10 08:56:36 +0200486 const auto ssrc = config_.rtp.ssrcs[0];
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200487 rtc::ScopedFakeClock fake_global_clock;
488 fake_global_clock.SetTime(
489 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
490
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200491 // First frame
Åsa Persson603e6e32021-08-10 08:56:36 +0200492 EncodedImage encoded_image;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200493 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200494 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
495 fake_global_clock.SetTime(
496 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson603e6e32021-08-10 08:56:36 +0200497 // Second frame
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200498 encoded_image.SetTimestamp(encoded_image.Timestamp() +
499 90 * kInterframeDelayMs);
500 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson603e6e32021-08-10 08:56:36 +0200501 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
502 fake_global_clock.SetTime(
503 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200504
505 auto stats = statistics_proxy_->GetStats();
506 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
507}
508
Åsa Persson8d564722021-08-03 14:43:01 +0200509TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp8Simulcast) {
510 const int kInterframeDelayMs = 100;
511 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200512 fake_global_clock.SetTime(
513 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200514 EncodedImage encoded_image;
515 CodecSpecificInfo codec_info;
516 codec_info.codecType = kVideoCodecVP8;
517
518 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200519 encoded_image.SetTimestamp(encoded_image.Timestamp() +
520 90 * kInterframeDelayMs);
521 encoded_image.SetSpatialIndex(0);
522 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
523 encoded_image.SetSpatialIndex(1);
524 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200525 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
526 fake_global_clock.SetTime(
527 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200528 }
529
530 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
531 EXPECT_EQ(2u, stats.substreams.size());
532 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
533 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson603e6e32021-08-10 08:56:36 +0200534
535 // Stop encoding second stream, expect framerate to be zero.
536 for (int i = 0; i < 10; ++i) {
537 encoded_image.SetTimestamp(encoded_image.Timestamp() +
538 90 * kInterframeDelayMs);
539 encoded_image.SetSpatialIndex(0);
540 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
541 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
542 fake_global_clock.SetTime(
543 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
544 }
545
546 stats = statistics_proxy_->GetStats();
547 EXPECT_EQ(2u, stats.substreams.size());
548 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
549 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 0);
550
551 // Start encoding second stream.
552 for (int i = 0; i < 10; ++i) {
553 encoded_image.SetTimestamp(encoded_image.Timestamp() +
554 90 * kInterframeDelayMs);
555 encoded_image.SetSpatialIndex(0);
556 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
557 encoded_image.SetSpatialIndex(1);
558 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
559 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
560 fake_global_clock.SetTime(
561 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
562 }
563
564 stats = statistics_proxy_->GetStats();
565 EXPECT_EQ(2u, stats.substreams.size());
566 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
567 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson8d564722021-08-03 14:43:01 +0200568}
569
570TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp9Svc) {
571 const int kInterframeDelayMs = 100;
572 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200573 fake_global_clock.SetTime(
574 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200575 EncodedImage encoded_image;
576 CodecSpecificInfo codec_info;
577 codec_info.codecType = kVideoCodecVP9;
578
579 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200580 encoded_image.SetTimestamp(encoded_image.Timestamp() +
581 90 * kInterframeDelayMs);
582 encoded_image.SetSpatialIndex(0);
583 codec_info.end_of_picture = false;
584 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
585 encoded_image.SetSpatialIndex(1);
586 codec_info.end_of_picture = true;
587 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200588 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
589 fake_global_clock.SetTime(
590 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200591 }
592
593 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
594 EXPECT_EQ(1u, stats.substreams.size());
595 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
596}
597
asapersson09f05612017-05-15 23:40:18 -0700598TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200599 VideoAdaptationCounters cpu_counts;
600 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700601 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700602 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200603 cpu_counts.fps_adaptations = 1;
604 cpu_counts.resolution_adaptations = 0;
605 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200606 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
607 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700608 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700609 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200610 cpu_counts.fps_adaptations = 0;
611 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200612 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
613 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700614 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700615 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200616 cpu_counts.fps_adaptations = 1;
617 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
618 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200619 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
620 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700621 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700622 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200623 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
624 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200625 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
626 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700627 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
628 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
629}
630
631TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200632 VideoAdaptationCounters cpu_counts;
633 VideoAdaptationCounters 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);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200636 quality_counts.fps_adaptations = 1;
637 quality_counts.resolution_adaptations = 0;
638 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200639 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
640 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700641 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
642 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200643 quality_counts.fps_adaptations = 0;
644 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200645 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
646 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700647 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
648 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200649 quality_counts.fps_adaptations = 1;
650 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
651 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200652 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
653 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700654 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
655 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200656 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
657 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200658 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
659 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700660 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
661 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
662}
663
664TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200665 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
666 VideoAdaptationCounters cpu_counts;
667 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700668 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
669
Evan Shrubsoledff79252020-04-16 11:34:32 +0200670 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200671 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
672 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700673 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700674 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
675 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
676
Evan Shrubsoledff79252020-04-16 11:34:32 +0200677 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200678 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
679 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700680 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
681 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700682 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700683 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700684}
685
asapersson09f05612017-05-15 23:40:18 -0700686TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200687 VideoAdaptationCounters cpu_counts;
688 VideoAdaptationCounters quality_counts;
689 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700690 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
691
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);
asapersson09f05612017-05-15 23:40:18 -0700695 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
696 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700697 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
698
Evan Shrubsoledff79252020-04-16 11:34:32 +0200699 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200700 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
701 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700702 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700703 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700704 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
705 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700706}
707
Evan Shrubsoledff79252020-04-16 11:34:32 +0200708TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
709 VideoAdaptationCounters cpu_counts;
710 VideoAdaptationCounters quality_counts;
711 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
712 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
713 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
714
715 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200716 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
717 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200718 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200719 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
720 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200721 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200722 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
723 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200724 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200725 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
726 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200727 // We have 1 fps and resolution reduction for both cpu and quality
728 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
729 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
730 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
731 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
732 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
733 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
734
735 // Disable quality scaling. Expect quality scaling not limited.
736 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
737 kScalingDisabled);
738 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
739 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
740 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
741 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
742 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
743 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
744
745 // Disable framerate scaling.
746 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
747 kFramerateScalingDisabled);
748 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
749 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
750 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
751 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
752 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
753 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
754
755 // Disable resolution scaling.
756 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
757 kResolutionScalingDisabled);
758 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
759 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
760 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
761 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
762 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
763 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
764
765 // Enable all
766 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
767 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
768 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
769 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
770 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
771 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
772 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
773}
774
asapersson09f05612017-05-15 23:40:18 -0700775TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700776 // First RTP packet sent.
777 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700778 // Min runtime has passed.
779 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
780 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100781 EXPECT_METRIC_EQ(
782 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
783 EXPECT_METRIC_EQ(
784 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700785}
786
787TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700788 // First RTP packet sent.
789 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700790 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200791 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700792 // Min runtime has not passed.
793 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
794 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100795 EXPECT_METRIC_EQ(
796 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
797 EXPECT_METRIC_EQ(
798 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700799}
800
asapersson09f05612017-05-15 23:40:18 -0700801TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700802 // First RTP packet sent.
803 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700804 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200805 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700806 // Min runtime has passed.
807 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
808 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100809 EXPECT_METRIC_EQ(
810 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
811 EXPECT_METRIC_EQ(
812 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
813 EXPECT_METRIC_EQ(
814 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
815 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700816 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
817}
818
819TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700820 // First RTP packet sent.
821 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700822 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200823 VideoAdaptationCounters cpu_counts;
824 VideoAdaptationCounters quality_counts;
825 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700826 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200827 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
828 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700829 fake_clock_.AdvanceTimeMilliseconds(10000);
830 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100831 EXPECT_METRIC_EQ(
832 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
833 EXPECT_METRIC_EQ(
834 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700835}
836
Åsa Persson875841d2018-01-08 08:49:53 +0100837TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
838 // First RTP packet sent.
839 UpdateDataCounters(kFirstSsrc);
840 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200841 VideoAdaptationCounters cpu_counts;
842 VideoAdaptationCounters quality_counts;
843 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100844 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200845 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
846 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100847 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
848 fake_clock_.AdvanceTimeMilliseconds(10000);
849 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100850 EXPECT_METRIC_EQ(
851 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
852 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100853 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
854}
855
856TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
857 // First RTP packet sent.
858 UpdateDataCounters(kFirstSsrc);
859 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200860 VideoAdaptationCounters cpu_counts;
861 VideoAdaptationCounters quality_counts;
862 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100863 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200864 quality_counts.resolution_adaptations = 1;
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();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200868 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200869 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
870 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100871 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200872 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200873 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
874 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100875 fake_clock_.AdvanceTimeMilliseconds(10000);
876 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100877 EXPECT_METRIC_EQ(
878 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
879 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100880 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
881}
882
883TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
884 // First RTP packet sent.
885 UpdateDataCounters(kFirstSsrc);
886 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200887 VideoAdaptationCounters cpu_counts;
888 VideoAdaptationCounters quality_counts;
889 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100890 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
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();
894 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
895 fake_clock_.AdvanceTimeMilliseconds(10000);
896 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100897 EXPECT_METRIC_EQ(
898 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
899 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100900 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
901}
902
903TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
904 // First RTP packet sent.
905 UpdateDataCounters(kFirstSsrc);
906 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200907 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
908 VideoAdaptationCounters cpu_counts;
909 VideoAdaptationCounters quality_counts;
910 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100911 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200912 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200913 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
914 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100915 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200916 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200917 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
918 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100919 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200920 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200921 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
922 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200923 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200924 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
925 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200926 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200927 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
928 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200929 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200930 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
931 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200932 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200933 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
934 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200935 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200936 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
937 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100938
939 fake_clock_.AdvanceTimeMilliseconds(10000);
940 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100941 EXPECT_METRIC_EQ(
942 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
943 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100944 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
945}
946
asapersson6eca98b2017-04-04 23:40:50 -0700947TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700948 // First RTP packet sent.
949 UpdateDataCounters(kFirstSsrc);
950
asapersson09f05612017-05-15 23:40:18 -0700951 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200952 VideoAdaptationCounters cpu_counts;
953 VideoAdaptationCounters quality_counts;
954 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
955 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700956 fake_clock_.AdvanceTimeMilliseconds(10000);
957
asapersson09f05612017-05-15 23:40:18 -0700958 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700959 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200960 quality_counts.fps_adaptations = 0;
961 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
962 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700963 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200964 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
965 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700966 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200967 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
968 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700969 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200970 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
971 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700972
asapersson09f05612017-05-15 23:40:18 -0700973 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200974 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
975 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700976 fake_clock_.AdvanceTimeMilliseconds(30000);
977
asapersson09f05612017-05-15 23:40:18 -0700978 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700979 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200980 quality_counts.resolution_adaptations = 0;
981 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
982 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200983 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
984 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700985 fake_clock_.AdvanceTimeMilliseconds(10000);
986
asapersson09f05612017-05-15 23:40:18 -0700987 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200988 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
989 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700990 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200991 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
992 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700993 fake_clock_.AdvanceTimeMilliseconds(20000);
994
asapersson0944a802017-04-07 00:57:58 -0700995 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700996 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100997 EXPECT_METRIC_EQ(
998 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
999 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001000 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1001}
1002
asapersson0944a802017-04-07 00:57:58 -07001003TEST_F(SendStatisticsProxyTest,
1004 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
1005 // First RTP packet sent.
1006 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001007
asapersson0944a802017-04-07 00:57:58 -07001008 // Suspend and resume video.
1009 statistics_proxy_->OnSuspendChange(true);
1010 fake_clock_.AdvanceTimeMilliseconds(5000);
1011 statistics_proxy_->OnSuspendChange(false);
1012
1013 // Min runtime has passed but scaling not enabled.
1014 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1015 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001016 EXPECT_METRIC_EQ(
1017 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1018 EXPECT_METRIC_EQ(
1019 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -07001020}
1021
1022TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
1023 // First RTP packet sent.
1024 UpdateDataCounters(kFirstSsrc);
1025
asapersson09f05612017-05-15 23:40:18 -07001026 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001027 VideoAdaptationCounters cpu_counts;
1028 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -07001029 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001030 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001031 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001032 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1033 cpu_counts, quality_counts);
1034 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1035 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001036
1037 // Suspend and resume video.
1038 statistics_proxy_->OnSuspendChange(true);
1039 fake_clock_.AdvanceTimeMilliseconds(30000);
1040 statistics_proxy_->OnSuspendChange(false);
1041
1042 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001043 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1044 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001045 fake_clock_.AdvanceTimeMilliseconds(10000);
1046
1047 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
1048 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001049 EXPECT_METRIC_EQ(
1050 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1051 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -07001052 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1053}
1054
1055TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
1056 // First RTP packet sent.
1057 UpdateDataCounters(kFirstSsrc);
1058
1059 // Video not suspended.
1060 statistics_proxy_->OnSuspendChange(false);
1061 fake_clock_.AdvanceTimeMilliseconds(30000);
1062
asapersson09f05612017-05-15 23:40:18 -07001063 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001064 VideoAdaptationCounters cpu_counts;
1065 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -07001066 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001067 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001068 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001069 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1070 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001071
1072 // Video not suspended, stats time already started.
1073 statistics_proxy_->OnSuspendChange(false);
1074 fake_clock_.AdvanceTimeMilliseconds(10000);
1075
asapersson09f05612017-05-15 23:40:18 -07001076 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001077 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1078 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -07001079 fake_clock_.AdvanceTimeMilliseconds(30000);
1080
1081 // Suspend and resume video, stats time not started when scaling not enabled.
1082 statistics_proxy_->OnSuspendChange(true);
1083 fake_clock_.AdvanceTimeMilliseconds(30000);
1084 statistics_proxy_->OnSuspendChange(false);
1085 fake_clock_.AdvanceTimeMilliseconds(30000);
1086
asapersson09f05612017-05-15 23:40:18 -07001087 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -07001088 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001089 cpu_counts.fps_adaptations = 0;
1090 cpu_counts.resolution_adaptations = 0;
1091 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001092 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001093 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1094 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001095
1096 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
1097 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001098 EXPECT_METRIC_EQ(
1099 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1100 EXPECT_METRIC_EQ(
1101 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -07001102}
1103
1104TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
1105 // First RTP packet sent.
1106 UpdateDataCounters(kFirstSsrc);
1107
1108 // Video suspended.
1109 statistics_proxy_->OnSuspendChange(true);
1110
asapersson09f05612017-05-15 23:40:18 -07001111 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001112 VideoAdaptationCounters cpu_counts;
1113 VideoAdaptationCounters quality_counts;
1114 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001115 fake_clock_.AdvanceTimeMilliseconds(10000);
1116
1117 // Resume video, stats time started.
1118 // Adapt changes: 1, elapsed time: 10 sec.
1119 statistics_proxy_->OnSuspendChange(false);
1120 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001121 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1122 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001123
1124 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1125 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001126 EXPECT_METRIC_EQ(
1127 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1128 EXPECT_METRIC_EQ(
1129 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001130}
1131
1132TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001133 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001134 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001135 VideoAdaptationCounters cpu_counts;
1136 VideoAdaptationCounters quality_counts;
1137 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001138 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001139 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001140
asapersson0944a802017-04-07 00:57:58 -07001141 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001142 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001143 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1144 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001145 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001146
asapersson0944a802017-04-07 00:57:58 -07001147 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001148 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001149 EXPECT_METRIC_EQ(
1150 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1151 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001152 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1153}
1154
1155TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001156 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001157 VideoAdaptationCounters cpu_counts;
1158 VideoAdaptationCounters quality_counts;
1159 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001160 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001161 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1162 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001163
1164 // Send first packet, scaling disabled.
1165 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001166 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001167 fake_clock_.AdvanceTimeMilliseconds(60000);
1168
asapersson09f05612017-05-15 23:40:18 -07001169 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001170 cpu_counts.resolution_adaptations = 0;
1171 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1172 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001173 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001174 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001175
asapersson0944a802017-04-07 00:57:58 -07001176 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001177 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001178 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1179 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001180
asapersson0944a802017-04-07 00:57:58 -07001181 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001182 statistics_proxy_.reset();
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", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001187}
1188
1189TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001190 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001191 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001192 VideoAdaptationCounters cpu_counts;
1193 VideoAdaptationCounters quality_counts;
1194 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1195 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001196
asapersson0944a802017-04-07 00:57:58 -07001197 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001198 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1199 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001200 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001201 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1202 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001203 fake_clock_.AdvanceTimeMilliseconds(9000);
1204
1205 // Switch content type, real-time stats should be updated.
1206 VideoEncoderConfig config;
1207 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001208 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001209 EXPECT_METRIC_EQ(
1210 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1211 EXPECT_METRIC_EQ(
1212 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1213 EXPECT_METRIC_EQ(
1214 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001215
asapersson0944a802017-04-07 00:57:58 -07001216 // First RTP packet sent, scaling enabled.
1217 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001218 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1219 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001220
asapersson0944a802017-04-07 00:57:58 -07001221 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001222 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1223 cpu_counts, quality_counts);
1224 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1225 cpu_counts, quality_counts);
1226 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1227 cpu_counts, quality_counts);
1228 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1229 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001230 fake_clock_.AdvanceTimeMilliseconds(120000);
1231
1232 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001233 EXPECT_METRIC_EQ(1,
1234 metrics::NumSamples(
1235 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1236 EXPECT_METRIC_EQ(
1237 1, metrics::NumEvents(
1238 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1239 EXPECT_METRIC_EQ(
1240 0, metrics::NumSamples(
1241 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001242}
1243
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001244TEST_F(SendStatisticsProxyTest,
1245 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001246 VideoAdaptationCounters cpu_counts;
1247 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001248
Evan Shrubsoledff79252020-04-16 11:34:32 +02001249 cpu_counts.resolution_adaptations = 1;
1250 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001251 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1252 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001253
1254 EXPECT_EQ(QualityLimitationReason::kCpu,
1255 statistics_proxy_->GetStats().quality_limitation_reason);
1256}
1257
1258TEST_F(SendStatisticsProxyTest,
1259 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001260 VideoAdaptationCounters cpu_counts;
1261 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001262
Evan Shrubsoledff79252020-04-16 11:34:32 +02001263 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001264
Evan Shrubsoledff79252020-04-16 11:34:32 +02001265 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001266 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1267 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001268
1269 EXPECT_EQ(QualityLimitationReason::kCpu,
1270 statistics_proxy_->GetStats().quality_limitation_reason);
1271}
1272
1273TEST_F(SendStatisticsProxyTest,
1274 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001275 VideoAdaptationCounters cpu_counts;
1276 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001277
Evan Shrubsoledff79252020-04-16 11:34:32 +02001278 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001279
Evan Shrubsoledff79252020-04-16 11:34:32 +02001280 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001281 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1282 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001283
1284 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1285 statistics_proxy_->GetStats().quality_limitation_reason);
1286}
1287
1288TEST_F(SendStatisticsProxyTest,
1289 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001290 VideoAdaptationCounters cpu_counts;
1291 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001292
Evan Shrubsoledff79252020-04-16 11:34:32 +02001293 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001294
Evan Shrubsoledff79252020-04-16 11:34:32 +02001295 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001296 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1297 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001298
1299 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1300 statistics_proxy_->GetStats().quality_limitation_reason);
1301}
1302
1303TEST_F(SendStatisticsProxyTest,
1304 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001305 VideoAdaptationCounters cpu_counts;
1306 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001307
Evan Shrubsoledff79252020-04-16 11:34:32 +02001308 cpu_counts.resolution_adaptations = 1;
1309 quality_counts.resolution_adaptations = 1;
1310 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001311
1312 // Even if the last adaptation reason is kCpu, if the counters indicate being
1313 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001314 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1315 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001316
1317 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1318 statistics_proxy_->GetStats().quality_limitation_reason);
1319}
1320
1321TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001322 VideoAdaptationCounters cpu_counts;
1323 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001324
1325 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1326 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001327 cpu_counts.resolution_adaptations = 1;
1328 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001329 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1330 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001331 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001332 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001333 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1334 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001335
1336 EXPECT_EQ(QualityLimitationReason::kNone,
1337 statistics_proxy_->GetStats().quality_limitation_reason);
1338}
1339
1340TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001341 VideoAdaptationCounters cpu_counts;
1342 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001343
Evan Shrubsoledff79252020-04-16 11:34:32 +02001344 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001345 // Not limited for 3000 ms
1346 fake_clock_.AdvanceTimeMilliseconds(3000);
1347 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001348 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001349 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1350 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001351 fake_clock_.AdvanceTimeMilliseconds(2000);
1352 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001353 cpu_counts.resolution_adaptations = 0;
1354 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001355 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1356 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001357 fake_clock_.AdvanceTimeMilliseconds(1000);
1358 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001359 cpu_counts.resolution_adaptations = 1;
1360 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001361 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1362 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001363 fake_clock_.AdvanceTimeMilliseconds(2000);
1364
1365 auto quality_limitation_durations_ms =
1366 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1367
1368 EXPECT_EQ(3000,
1369 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1370 EXPECT_EQ(4000,
1371 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1372 EXPECT_EQ(
1373 1000,
1374 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1375 EXPECT_EQ(0,
1376 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1377}
1378
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001379TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1380 EXPECT_EQ(
1381 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1382}
1383
1384TEST_F(SendStatisticsProxyTest,
1385 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1386 VideoCodec codec;
1387 VideoBitrateAllocation allocation;
1388 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1389 EXPECT_EQ(
1390 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1391}
1392
1393TEST_F(SendStatisticsProxyTest,
1394 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1395 VideoCodec codec;
1396 codec.simulcastStream[0].active = true;
1397 codec.simulcastStream[1].active = true;
1398 codec.simulcastStream[2].active = true;
1399 VideoBitrateAllocation allocation;
1400 allocation.SetBitrate(0, 0, 100);
1401 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1402 EXPECT_EQ(
1403 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1404}
1405
1406TEST_F(SendStatisticsProxyTest,
1407 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1408 VideoCodec codec;
1409 codec.simulcastStream[0].active = true;
1410 codec.simulcastStream[1].active = true;
1411 codec.simulcastStream[2].active = true;
1412 VideoBitrateAllocation allocation;
1413 allocation.SetBitrate(0, 0, 100);
1414 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1415 allocation.SetBitrate(1, 0, 100);
1416 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1417 EXPECT_EQ(
1418 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1419}
1420
1421TEST_F(SendStatisticsProxyTest,
1422 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1423 VideoCodec codec;
1424 codec.simulcastStream[0].active = true;
1425 VideoBitrateAllocation allocation;
1426 allocation.SetBitrate(0, 0, 100);
1427 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1428 // Layer 0 got more bandwidth, but still only one layer on
1429 allocation.SetBitrate(0, 0, 200);
1430 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1431 EXPECT_EQ(
1432 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1433}
1434
1435TEST_F(SendStatisticsProxyTest,
1436 QualityLimitationResolutionChangesWithTogglingLayers) {
1437 VideoCodec codec;
1438 codec.simulcastStream[0].active = true;
1439 codec.simulcastStream[1].active = true;
1440 codec.simulcastStream[2].active = true;
1441 VideoBitrateAllocation allocation;
1442 allocation.SetBitrate(0, 0, 100);
1443 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1444 EXPECT_EQ(
1445 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1446 allocation.SetBitrate(1, 0, 300);
1447 allocation.SetBitrate(2, 0, 500);
1448 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1449 EXPECT_EQ(
1450 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1451 // Layer 2 off
1452 allocation.SetBitrate(2, 0, 0);
1453 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1454 EXPECT_EQ(
1455 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1456 // Layer 2 back on
1457 allocation.SetBitrate(2, 0, 500);
1458 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1459 EXPECT_EQ(
1460 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1461 allocation.SetBitrate(0, 0, 0);
1462 allocation.SetBitrate(1, 0, 0);
1463 allocation.SetBitrate(2, 0, 0);
1464 // All layers off
1465 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1466 EXPECT_EQ(
1467 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1468}
1469
1470TEST_F(SendStatisticsProxyTest,
1471 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1472 VideoCodec codec;
1473 // 3 layers
1474 codec.simulcastStream[0].active = true;
1475 codec.simulcastStream[1].active = true;
1476 codec.simulcastStream[2].active = true;
1477 VideoBitrateAllocation allocation;
1478 allocation.SetBitrate(0, 0, 500);
1479 allocation.SetBitrate(1, 0, 500);
1480 allocation.SetBitrate(2, 0, 500);
1481 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1482 EXPECT_EQ(
1483 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1484
1485 // Down to one layer now, triggered by a config change
1486 codec.numberOfSimulcastStreams = 1;
1487 codec.simulcastStream[1].active = false;
1488 codec.simulcastStream[2].active = false;
1489 allocation.SetBitrate(0, 0, 100);
1490 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1491 EXPECT_EQ(
1492 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1493
1494 // Up to 3 layers again.
1495 codec.numberOfSimulcastStreams = 3;
1496 codec.simulcastStream[1].active = true;
1497 codec.simulcastStream[2].active = true;
1498 allocation.SetBitrate(0, 0, 500);
1499 allocation.SetBitrate(1, 0, 500);
1500 allocation.SetBitrate(2, 0, 500);
1501 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1502 EXPECT_EQ(
1503 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1504}
1505
1506TEST_F(SendStatisticsProxyTest,
1507 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1508 VideoCodec codec;
1509 codec.simulcastStream[0].active = true;
1510 codec.spatialLayers[0].active = true;
1511 codec.spatialLayers[1].active = true;
1512 codec.spatialLayers[2].active = true;
1513 VideoBitrateAllocation allocation;
1514 allocation.SetBitrate(0, 0, 500);
1515 allocation.SetBitrate(1, 0, 500);
1516 allocation.SetBitrate(2, 0, 500);
1517 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1518 EXPECT_EQ(
1519 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1520
1521 // Down to one layer now, triggered by a config change
1522 codec.spatialLayers[1].active = false;
1523 codec.spatialLayers[2].active = false;
1524 allocation.SetBitrate(0, 0, 100);
1525 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1526 EXPECT_EQ(
1527 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1528
1529 // Up to 3 layers again.
1530 codec.spatialLayers[1].active = true;
1531 codec.spatialLayers[2].active = true;
1532 allocation.SetBitrate(0, 0, 500);
1533 allocation.SetBitrate(1, 0, 500);
1534 allocation.SetBitrate(2, 0, 500);
1535 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1536 EXPECT_EQ(
1537 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1538}
1539
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001540TEST_F(SendStatisticsProxyTest,
1541 QualityLimitationReasonsAreCorrectForContentType) {
1542 // Realtime case.
1543 // Configure two streams.
1544 VideoEncoderConfig config;
1545 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1546 config.number_of_streams = 2;
1547 VideoStream stream1;
1548 stream1.width = kWidth / 2;
1549 stream1.height = kHeight / 2;
1550 VideoStream stream2;
1551 stream2.width = kWidth;
1552 stream2.height = kHeight;
1553 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1554 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1555 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1556 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1557 QualityLimitationReason::kNone);
1558 // Bw disabled one layer.
1559 VideoCodec codec;
1560 codec.numberOfSimulcastStreams = 2;
1561 codec.simulcastStream[0].active = true;
1562 codec.simulcastStream[1].active = true;
1563 VideoBitrateAllocation allocation;
1564 // Some positive bitrate only on the first stream.
1565 allocation.SetBitrate(0, 0, 10000);
1566 allocation.SetBitrate(1, 0, 0);
1567 allocation.set_bw_limited(true);
1568 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1569 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1570 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1571 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1572 QualityLimitationReason::kBandwidth);
1573 // Bw enabled all layers.
1574 allocation.SetBitrate(1, 0, 10000);
1575 allocation.set_bw_limited(false);
1576 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1577 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1578 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1579 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1580 QualityLimitationReason::kNone);
1581
1582 // Screencast case
1583 // Configure two streams.
1584 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1585 config.number_of_streams = 2;
1586 stream1.width = kWidth;
1587 stream1.height = kHeight;
1588 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1589 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1590 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1591 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1592 QualityLimitationReason::kNone);
1593 // Bw disabled one layer.
1594 // Some positive bitrate only on the second stream.
1595 allocation.SetBitrate(0, 0, 10000);
1596 allocation.SetBitrate(1, 0, 0);
1597 allocation.set_bw_limited(true);
1598 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1599 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1600 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1601 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1602 QualityLimitationReason::kBandwidth);
1603 // Bw enabled all layers.
1604 allocation.SetBitrate(1, 0, 10000);
1605 allocation.set_bw_limited(false);
1606 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1607 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1608 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1609 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1610 QualityLimitationReason::kNone);
1611}
1612
asapersson59bac1a2016-01-07 23:36:00 -08001613TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001614 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001615 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1616
Pera48ddb72016-09-29 11:48:50 +02001617 // No switch, stats should not be updated.
1618 VideoEncoderConfig config;
1619 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001620 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001621 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001622
1623 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001624 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001625 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001626 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001627}
1628
asapersson320e45a2016-11-29 01:40:35 -08001629TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1630 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1631 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001632
asapersson320e45a2016-11-29 01:40:35 -08001633 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001634 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1635 EXPECT_METRIC_EQ(
1636 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1637 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1638 EXPECT_METRIC_EQ(
1639 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001640}
1641
1642TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001643 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001644 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001645 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1646 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1647 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001648 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001649
1650 // Not enough samples, stats should not be updated.
1651 for (int i = 0; i < kMinSamples - 1; ++i) {
1652 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001653 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001654 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1655 }
Åsa Persson0122e842017-10-16 12:19:23 +02001656 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001657 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1658 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001659
1660 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001661 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001662 for (int i = 0; i < kMinSamples; ++i) {
1663 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001664 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001665 encoded_image._encodedWidth = kWidth;
1666 encoded_image._encodedHeight = kHeight;
1667 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1668 encoded_image._encodedWidth = kWidth / 2;
1669 encoded_image._encodedHeight = kHeight / 2;
1670 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1671 }
1672
asapersson320e45a2016-11-29 01:40:35 -08001673 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001674 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1675 EXPECT_METRIC_EQ(
1676 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1677 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1678 EXPECT_METRIC_EQ(
1679 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001680}
1681
1682TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1683 const int kFps = 20;
1684 const int kMinPeriodicSamples = 6;
1685 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1686 for (int i = 0; i <= frames; ++i) {
1687 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1688 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1689 }
1690 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001691 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1692 EXPECT_METRIC_EQ(
1693 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001694}
1695
1696TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1697 EncodedImage encoded_image;
1698 const int kFps = 20;
1699 const int kMinPeriodicSamples = 6;
1700 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001701 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001702 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001703 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001704 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1705 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001706 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1707 }
1708 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001709 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1710 EXPECT_METRIC_EQ(
1711 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001712}
1713
1714TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1715 const int kFps = 20;
1716 const int kSuspendTimeMs = 10000;
1717 const int kMinPeriodicSamples = 6;
1718 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1719 for (int i = 0; i < frames; ++i) {
1720 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1721 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1722 }
1723 // Suspend.
1724 statistics_proxy_->OnSuspendChange(true);
1725 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1726
1727 for (int i = 0; i < frames; ++i) {
1728 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1729 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1730 }
1731 // Suspended time interval should not affect the framerate.
1732 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001733 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1734 EXPECT_METRIC_EQ(
1735 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001736}
1737
1738TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1739 EncodedImage encoded_image;
1740 const int kFps = 20;
1741 const int kSuspendTimeMs = 10000;
1742 const int kMinPeriodicSamples = 6;
1743 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001744 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001745 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001746 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001747 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1748 }
1749 // Suspend.
1750 statistics_proxy_->OnSuspendChange(true);
1751 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1752
Åsa Persson0122e842017-10-16 12:19:23 +02001753 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001754 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001755 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001756 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1757 }
1758 // Suspended time interval should not affect the framerate.
1759 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001760 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1761 EXPECT_METRIC_EQ(
1762 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001763}
1764
asaperssonf4e44af2017-04-19 02:01:06 -07001765TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001766 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1767 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001768
1769 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1770 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1771
1772 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001773 EXPECT_METRIC_EQ(
1774 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001775}
1776
1777TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001778 VideoAdaptationCounters cpu_counts;
1779 VideoAdaptationCounters quality_counts;
1780 cpu_counts.resolution_adaptations = 0;
1781 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001782
perkj803d97f2016-11-01 11:45:46 -07001783 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1784 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1785
Evan Shrubsoledff79252020-04-16 11:34:32 +02001786 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001787 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1788 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001789
1790 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1791 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1792
1793 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001794 EXPECT_METRIC_EQ(
1795 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1796 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001797 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1798}
1799
asapersson4374a092016-07-27 00:39:09 -07001800TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1801 const int64_t kTimeSec = 3;
1802 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1803 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001804 EXPECT_METRIC_EQ(
1805 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1806 EXPECT_METRIC_EQ(
1807 1,
1808 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001809}
1810
1811TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1812 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1813 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001814 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001815}
1816
asapersson66d4b372016-12-19 06:50:53 -08001817TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1818 // First RTP packet sent.
1819 UpdateDataCounters(kFirstSsrc);
1820
1821 // Min runtime has passed.
1822 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1823 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001824 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1825 EXPECT_METRIC_EQ(1,
1826 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001827}
1828
1829TEST_F(SendStatisticsProxyTest,
1830 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1831 // First RTP packet sent.
1832 UpdateDataCounters(kFirstSsrc);
1833
1834 // Min runtime has not passed.
1835 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1836 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001837 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1838 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001839}
1840
1841TEST_F(SendStatisticsProxyTest,
1842 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1843 // First RTP packet not sent.
1844 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1845 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001846 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001847}
1848
1849TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1850 // First RTP packet sent and min runtime passed.
1851 UpdateDataCounters(kFirstSsrc);
1852
1853 // No change. Video: 10000 ms, paused: 0 ms (0%).
1854 statistics_proxy_->OnSetEncoderTargetRate(50000);
1855 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1856 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1857
1858 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001859 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1860 EXPECT_METRIC_EQ(1,
1861 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1862 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1863 EXPECT_METRIC_EQ(1,
1864 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001865}
1866
1867TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1868 // First RTP packet sent and min runtime passed.
1869 UpdateDataCounters(kFirstSsrc);
1870
1871 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1872 statistics_proxy_->OnSetEncoderTargetRate(50000);
1873 fake_clock_.AdvanceTimeMilliseconds(7000);
1874 statistics_proxy_->OnSetEncoderTargetRate(0);
1875 fake_clock_.AdvanceTimeMilliseconds(3000);
1876 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1877
1878 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001879 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1880 EXPECT_METRIC_EQ(1,
1881 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1882 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1883 EXPECT_METRIC_EQ(1,
1884 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001885}
1886
1887TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1888 // First RTP packet sent.
1889 UpdateDataCounters(kFirstSsrc);
1890
1891 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1892 statistics_proxy_->OnSetEncoderTargetRate(0);
1893 fake_clock_.AdvanceTimeMilliseconds(1000);
1894 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1895 fake_clock_.AdvanceTimeMilliseconds(7000);
1896 statistics_proxy_->OnSetEncoderTargetRate(60000);
1897 fake_clock_.AdvanceTimeMilliseconds(3000);
1898 statistics_proxy_->OnSetEncoderTargetRate(0);
1899 fake_clock_.AdvanceTimeMilliseconds(250);
1900 statistics_proxy_->OnSetEncoderTargetRate(0);
1901 fake_clock_.AdvanceTimeMilliseconds(750);
1902 statistics_proxy_->OnSetEncoderTargetRate(60000);
1903 fake_clock_.AdvanceTimeMilliseconds(5000);
1904 statistics_proxy_->OnSetEncoderTargetRate(50000);
1905 fake_clock_.AdvanceTimeMilliseconds(4000);
1906 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1907
1908 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001909 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1910 EXPECT_METRIC_EQ(1,
1911 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1912 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1913 EXPECT_METRIC_EQ(1,
1914 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001915}
1916
1917TEST_F(SendStatisticsProxyTest,
1918 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1919 // First RTP packet sent.
1920 UpdateDataCounters(kFirstSsrc);
1921 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1922
1923 // Min runtime has not passed.
1924 statistics_proxy_->OnSetEncoderTargetRate(50000);
1925 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1926 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1927
1928 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001929 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001930}
1931
asapersson118ef002016-03-31 00:00:19 -07001932TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001933 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001934 CodecSpecificInfo codec_info;
1935 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001936
perkj803d97f2016-11-01 11:45:46 -07001937 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001938 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001939 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001940 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001941 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001942 encoded_image.qp_ = kQpIdx1;
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.S0"));
1947 EXPECT_METRIC_EQ(
1948 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1949 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1950 EXPECT_METRIC_EQ(
1951 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001952}
1953
1954TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01001955 test::ScopedKeyValueConfig field_trials;
asapersson118ef002016-03-31 00:00:19 -07001956 VideoSendStream::Config config(nullptr);
1957 config.rtp.ssrcs.push_back(kFirstSsrc);
1958 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01001959 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1960 field_trials));
asapersson118ef002016-03-31 00:00:19 -07001961
asapersson118ef002016-03-31 00:00:19 -07001962 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001963 CodecSpecificInfo codec_info;
1964 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001965
perkj803d97f2016-11-01 11:45:46 -07001966 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001967 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001968 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001969 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001970 }
1971 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001972 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1973 EXPECT_METRIC_EQ(1,
1974 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001975}
1976
asapersson5265fed2016-04-18 02:58:47 -07001977TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001978 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001979 CodecSpecificInfo codec_info;
1980 codec_info.codecType = kVideoCodecVP9;
1981 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001982
perkj803d97f2016-11-01 11:45:46 -07001983 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001984 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001985 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001986 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001987 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001988 encoded_image.SetSpatialIndex(1);
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.S0"));
1993 EXPECT_METRIC_EQ(
1994 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1995 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1996 EXPECT_METRIC_EQ(
1997 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001998}
1999
2000TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002001 test::ScopedKeyValueConfig field_trials;
asapersson5265fed2016-04-18 02:58:47 -07002002 VideoSendStream::Config config(nullptr);
2003 config.rtp.ssrcs.push_back(kFirstSsrc);
2004 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01002005 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2006 field_trials));
asapersson5265fed2016-04-18 02:58:47 -07002007
asapersson5265fed2016-04-18 02:58:47 -07002008 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07002009 CodecSpecificInfo codec_info;
2010 codec_info.codecType = kVideoCodecVP9;
2011 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07002012
perkj803d97f2016-11-01 11:45:46 -07002013 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07002014 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07002015 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07002016 }
2017 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002018 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
2019 EXPECT_METRIC_EQ(1,
2020 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07002021}
2022
asapersson827cab32016-11-02 09:08:47 -07002023TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
2024 EncodedImage encoded_image;
2025 CodecSpecificInfo codec_info;
2026 codec_info.codecType = kVideoCodecH264;
2027
2028 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002029 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07002030 encoded_image.qp_ = kQpIdx0;
2031 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002032 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02002033 encoded_image.qp_ = kQpIdx1;
2034 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07002035 }
2036 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002037 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
2038 EXPECT_METRIC_EQ(
2039 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
2040 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
2041 EXPECT_METRIC_EQ(
2042 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07002043}
2044
asapersson4ee70462016-10-31 04:05:12 -07002045TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002046 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
2047 // Configure one stream.
2048 VideoEncoderConfig config;
2049 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2050 VideoStream stream1;
2051 stream1.width = kWidth;
2052 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002053 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002054
2055 const int64_t kMaxEncodedFrameWindowMs = 800;
2056 const int kFps = 20;
2057 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2058 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2059 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2060
2061 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002062 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002063 encoded_image._encodedWidth = kWidth;
2064 encoded_image._encodedHeight = kHeight;
2065 for (int i = 0; i < kMinSamples; ++i) {
2066 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002067 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2068 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002069 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002070 }
asapersson4ee70462016-10-31 04:05:12 -07002071
2072 // Histograms are updated when the statistics_proxy_ is deleted.
2073 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002074 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2075 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2076 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2077 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002078}
2079
2080TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002081 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
2082 // Configure two streams.
2083 VideoEncoderConfig config;
2084 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2085 VideoStream stream1;
2086 stream1.width = kWidth / 2;
2087 stream1.height = kHeight / 2;
2088 VideoStream stream2;
2089 stream2.width = kWidth;
2090 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002091 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002092
2093 const int64_t kMaxEncodedFrameWindowMs = 800;
2094 const int kFps = 20;
2095 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2096 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2097 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2098
2099 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07002100 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002101 for (int i = 0; i < kMinSamples; ++i) {
2102 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002103 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2104 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002105 encoded_image._encodedWidth = kWidth;
2106 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07002107 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002108 encoded_image._encodedWidth = kWidth / 2;
2109 encoded_image._encodedHeight = kHeight / 2;
2110 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2111 }
asapersson4ee70462016-10-31 04:05:12 -07002112
2113 // Histograms are updated when the statistics_proxy_ is deleted.
2114 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002115 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2116 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2117 EXPECT_METRIC_EQ(
2118 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2119 0));
asapersson4ee70462016-10-31 04:05:12 -07002120 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002121 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2122 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002123}
2124
2125TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002126 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2127 // Configure two streams.
2128 VideoEncoderConfig config;
2129 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2130 VideoStream stream1;
2131 stream1.width = kWidth / 2;
2132 stream1.height = kHeight / 2;
2133 VideoStream stream2;
2134 stream2.width = kWidth;
2135 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002136 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002137
2138 const int64_t kMaxEncodedFrameWindowMs = 800;
2139 const int kFps = 20;
2140 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2141 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2142 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2143
2144 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002145 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002146 encoded_image._encodedWidth = kWidth / 2;
2147 encoded_image._encodedHeight = kHeight / 2;
2148 for (int i = 0; i < kMinSamples; ++i) {
2149 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002150 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2151 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002152 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002153 }
asapersson4ee70462016-10-31 04:05:12 -07002154
2155 // Histograms are updated when the statistics_proxy_ is deleted.
2156 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002157 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2158 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2159 EXPECT_METRIC_EQ(
2160 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2161 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002162 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002163 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2164 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2165 EXPECT_METRIC_EQ(
2166 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2167 1));
asapersson4ee70462016-10-31 04:05:12 -07002168}
2169
2170TEST_F(SendStatisticsProxyTest,
2171 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002172 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2173 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002174 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002175 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002176 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002177 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002178
2179 // Histograms are updated when the statistics_proxy_ is deleted.
2180 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002181 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002182 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002183 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2184 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002185}
2186
2187TEST_F(SendStatisticsProxyTest,
2188 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002189 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002190 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002191 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002192 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002193 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002194
2195 // Histograms are updated when the statistics_proxy_ is deleted.
2196 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002197 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002198 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002199 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2200 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002201 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002202 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2203 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002204}
2205
2206TEST_F(SendStatisticsProxyTest,
2207 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2208 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002209 VideoAdaptationCounters cpu_counts;
2210 VideoAdaptationCounters quality_counts;
2211 quality_counts.resolution_adaptations = kDownscales;
2212 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002213 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2214 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002215 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002216 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002217 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002218 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002219 // Histograms are updated when the statistics_proxy_ is deleted.
2220 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002221 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002222 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002223 EXPECT_METRIC_EQ(
2224 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2225 100));
asapersson4ee70462016-10-31 04:05:12 -07002226 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002227 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2228 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2229 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002230 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2231 kDownscales));
2232}
2233
2234TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2235 // Initially false.
2236 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002237
Åsa Perssonaa329e72017-12-15 15:54:44 +01002238 // Configure two streams.
2239 VideoEncoderConfig config;
2240 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002241 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002242 VideoStream stream1;
2243 stream1.width = kWidth / 2;
2244 stream1.height = kHeight / 2;
2245 VideoStream stream2;
2246 stream2.width = kWidth;
2247 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002248 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002249
Åsa Perssonaa329e72017-12-15 15:54:44 +01002250 // One stream encoded.
2251 EncodedImage encoded_image;
2252 encoded_image._encodedWidth = kWidth / 2;
2253 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002254
2255 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002256 VideoAdaptationCounters cpu_counts;
2257 VideoAdaptationCounters quality_counts;
2258 quality_counts.resolution_adaptations = 1;
2259 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2260 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002261 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2262 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002263 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2264 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002265
2266 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002267 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002268 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2269 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002270 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2271 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2272
2273 // Bw disabled one layer.
2274 VideoCodec codec;
2275 codec.numberOfSimulcastStreams = 2;
2276 codec.simulcastStream[0].active = true;
2277 codec.simulcastStream[1].active = true;
2278 VideoBitrateAllocation allocation;
2279 // Some positive bitrate only on the second stream.
2280 allocation.SetBitrate(1, 0, 10000);
2281 allocation.set_bw_limited(true);
2282 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2283 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002284
2285 // Revert for the next test.
2286 allocation.set_bw_limited(false);
2287 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2288 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2289
2290 // Internal encoder scaler reduced resolution.
2291 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2292 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002293}
2294
asapersson66d4b372016-12-19 06:50:53 -08002295TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2296 // Initially zero.
2297 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2298
2299 const int kBitrate = 100000;
2300 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2301 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2302
2303 statistics_proxy_->OnSetEncoderTargetRate(0);
2304 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2305}
2306
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002307TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002308 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002309 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2310 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002311 1;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002312 // From ReportBlockDataObserver.
2313 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2314 RTCPReportBlock report_block;
2315 report_block.source_ssrc = excluded_ssrc;
2316 ReportBlockData data;
2317 data.SetReportBlock(report_block, 0);
2318 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002319
2320 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002321 uint32_t total = 0;
2322 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002323 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002324 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002325
2326 // From FrameCountObserver.
2327 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002328 FrameCounts frame_counts;
2329 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002330 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002331
2332 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2333 EXPECT_TRUE(stats.substreams.empty());
2334}
2335
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002336TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2337 static const int kEncodedWidth = 123;
2338 static const int kEncodedHeight = 81;
2339 EncodedImage encoded_image;
2340 encoded_image._encodedWidth = kEncodedWidth;
2341 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002342 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002343
kjellander02b3d272016-04-20 05:05:54 -07002344 CodecSpecificInfo codec_info;
2345 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002346
kjellander02b3d272016-04-20 05:05:54 -07002347 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002348 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002349 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002350
2351 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002352 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2353 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2354 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2355 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002356
2357 // Forward almost to timeout, this should not have removed stats.
2358 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2359 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002360 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2361 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002362
2363 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2364 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002365 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2366 RTCPReportBlock report_block;
2367 report_block.source_ssrc = config_.rtp.ssrcs[0];
2368 ReportBlockData data;
2369 data.SetReportBlock(report_block, 0);
2370 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002371
2372 // Report stats for second SSRC to make sure it's not outdated along with the
2373 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002374 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002375
2376 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2377 // reported, but substream 1 should.
2378 fake_clock_.AdvanceTimeMilliseconds(1);
2379 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002380 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2381 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2382 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2383 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002384}
2385
Peter Boström20f3f942015-05-15 11:33:39 +02002386TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2387 static const int kEncodedWidth = 123;
2388 static const int kEncodedHeight = 81;
2389 EncodedImage encoded_image;
2390 encoded_image._encodedWidth = kEncodedWidth;
2391 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002392 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002393
kjellander02b3d272016-04-20 05:05:54 -07002394 CodecSpecificInfo codec_info;
2395 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002396
kjellander02b3d272016-04-20 05:05:54 -07002397 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002398 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002399 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002400
2401 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2402 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2403 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2404 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2405 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2406 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2407}
2408
2409TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002410 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002411 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2412 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2413 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2414
2415 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2416
2417 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002418 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002419 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002420 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002421 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2422 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2423 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2424}
2425
sprang07fb9be2016-02-24 07:55:00 -08002426TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2427 RtcpPacketTypeCounterObserver* proxy =
2428 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2429 RtcpPacketTypeCounter counters;
sprang07fb9be2016-02-24 07:55:00 -08002430 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2431 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2432
2433 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2434
2435 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2436 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2437 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2438 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2439 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2440
2441 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2442 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2443
2444 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002445 VideoEncoderConfig config;
2446 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002447 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002448
Ying Wangef3998f2019-12-09 13:06:53 +01002449 EXPECT_METRIC_EQ(
2450 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2451 EXPECT_METRIC_EQ(
2452 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2453 EXPECT_METRIC_EQ(
2454 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2455 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2456 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002457
2458 const int kRate = 60 * 2; // Packets per minute with two streams.
2459
Ying Wangef3998f2019-12-09 13:06:53 +01002460 EXPECT_METRIC_EQ(
2461 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2462 1 * kRate));
2463 EXPECT_METRIC_EQ(
2464 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2465 2 * kRate));
2466 EXPECT_METRIC_EQ(
2467 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2468 3 * kRate));
2469 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002470 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2471 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002472
2473 // New start time but same counter values.
2474 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2475 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2476
2477 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2478
2479 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2480 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2481 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2482 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2483 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2484
2485 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2486 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2487
2488 SetUp(); // Reset stats proxy also causes histograms to be reported.
2489
Ying Wangef3998f2019-12-09 13:06:53 +01002490 EXPECT_METRIC_EQ(
2491 1, metrics::NumSamples(
2492 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2493 EXPECT_METRIC_EQ(1,
2494 metrics::NumSamples(
2495 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2496 EXPECT_METRIC_EQ(1,
2497 metrics::NumSamples(
2498 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2499 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002500 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002501 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2502
Ying Wangef3998f2019-12-09 13:06:53 +01002503 EXPECT_METRIC_EQ(
2504 1,
2505 metrics::NumEvents(
2506 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2507 EXPECT_METRIC_EQ(
2508 1,
2509 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2510 2 * kRate));
2511 EXPECT_METRIC_EQ(
2512 1,
2513 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2514 3 * kRate));
2515 EXPECT_METRIC_EQ(
2516 1, metrics::NumEvents(
2517 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2518 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002519}
2520
Henrik Boströmf45ca372020-03-24 13:30:50 +01002521TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2522 StreamDataCountersCallback* proxy =
2523 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2524 StreamDataCounters counters;
2525 proxy->DataCountersUpdated(counters, kFirstSsrc);
2526 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2527
2528 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2529 VideoSendStream::StreamStats::StreamType::kRtx);
2530 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2531 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2532 VideoSendStream::StreamStats::StreamType::kRtx);
2533 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2534}
2535
asaperssona6a699a2016-11-25 03:52:46 -08002536TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002537 test::ScopedKeyValueConfig field_trials;
2538 statistics_proxy_.reset(new SendStatisticsProxy(
2539 &fake_clock_, GetTestConfigWithFlexFec(),
2540 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 03:52:46 -08002541
2542 StreamDataCountersCallback* proxy =
2543 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2544 StreamDataCounters counters;
2545 proxy->DataCountersUpdated(counters, kFirstSsrc);
2546 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2547
Henrik Boströmf45ca372020-03-24 13:30:50 +01002548 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2549 VideoSendStream::StreamStats::StreamType::kFlexfec);
2550 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2551 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2552 VideoSendStream::StreamStats::StreamType::kFlexfec);
2553 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002554}
2555
2556TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002557 test::ScopedKeyValueConfig field_trials;
2558 statistics_proxy_.reset(new SendStatisticsProxy(
2559 &fake_clock_, GetTestConfigWithFlexFec(),
2560 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 03:52:46 -08002561
2562 StreamDataCountersCallback* proxy =
2563 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002564 StreamDataCounters counters;
2565 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002566
asapersson93e1e232017-02-06 05:18:35 -08002567 const int kMinRequiredPeriodSamples = 8;
2568 const int kPeriodIntervalMs = 2000;
2569 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2570 counters.transmitted.packets += 20;
2571 counters.transmitted.header_bytes += 500;
2572 counters.transmitted.padding_bytes += 1000;
2573 counters.transmitted.payload_bytes += 2000;
2574 counters.retransmitted.packets += 2;
2575 counters.retransmitted.header_bytes += 25;
2576 counters.retransmitted.padding_bytes += 100;
2577 counters.retransmitted.payload_bytes += 250;
2578 counters.fec = counters.retransmitted;
2579 rtx_counters.transmitted = counters.transmitted;
2580 // Advance one interval and update counters.
2581 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2582 proxy->DataCountersUpdated(counters, kFirstSsrc);
2583 proxy->DataCountersUpdated(counters, kSecondSsrc);
2584 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2585 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2586 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2587 }
asaperssona6a699a2016-11-25 03:52:46 -08002588
asaperssona6a699a2016-11-25 03:52:46 -08002589 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002590 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002591 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2592 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002593 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002594 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2595 EXPECT_METRIC_EQ(1,
2596 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002597 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002598 EXPECT_METRIC_EQ(1,
2599 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2600 EXPECT_METRIC_EQ(
2601 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002602 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002603 EXPECT_METRIC_EQ(
2604 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2605 EXPECT_METRIC_EQ(
2606 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002607 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002608 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2609 EXPECT_METRIC_EQ(1,
2610 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002611 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002612 EXPECT_METRIC_EQ(
2613 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2614 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002615 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002616}
2617
Erik Språng22c2b482016-03-01 09:40:42 +01002618TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2619 StreamDataCountersCallback* proxy =
2620 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2621 StreamDataCounters counters;
2622 StreamDataCounters rtx_counters;
2623 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002624
asapersson93e1e232017-02-06 05:18:35 -08002625 const int kMinRequiredPeriodSamples = 8;
2626 const int kPeriodIntervalMs = 2000;
2627 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2628 counters.transmitted.packets += 20;
2629 counters.transmitted.header_bytes += 500;
2630 counters.transmitted.padding_bytes += 1000;
2631 counters.transmitted.payload_bytes += 2000;
2632 counters.retransmitted.packets += 2;
2633 counters.retransmitted.header_bytes += 25;
2634 counters.retransmitted.padding_bytes += 100;
2635 counters.retransmitted.payload_bytes += 250;
2636 counters.fec = counters.retransmitted;
2637 rtx_counters.transmitted = counters.transmitted;
2638 // Advance one interval and update counters.
2639 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2640 proxy->DataCountersUpdated(counters, kFirstSsrc);
2641 proxy->DataCountersUpdated(counters, kSecondSsrc);
2642 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2643 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2644 }
Erik Språng22c2b482016-03-01 09:40:42 +01002645
2646 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002647 VideoEncoderConfig config;
2648 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002649 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002650
asapersson93e1e232017-02-06 05:18:35 -08002651 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002652 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2653 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002654 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002655 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2656 EXPECT_METRIC_EQ(1,
2657 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002658 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002659 EXPECT_METRIC_EQ(1,
2660 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2661 EXPECT_METRIC_EQ(
2662 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002663 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002664 EXPECT_METRIC_EQ(
2665 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2666 EXPECT_METRIC_EQ(
2667 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002668 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002669 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2670 EXPECT_METRIC_EQ(1,
2671 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002672 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002673 EXPECT_METRIC_EQ(
2674 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2675 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002676 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002677
asapersson93e1e232017-02-06 05:18:35 -08002678 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002679 // Double counter values, this should result in the same counts as before but
2680 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002681 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2682 counters.transmitted.packets += 20;
2683 counters.transmitted.header_bytes += 500;
2684 counters.transmitted.padding_bytes += 1000;
2685 counters.transmitted.payload_bytes += 2000;
2686 counters.retransmitted.packets += 2;
2687 counters.retransmitted.header_bytes += 25;
2688 counters.retransmitted.padding_bytes += 100;
2689 counters.retransmitted.payload_bytes += 250;
2690 counters.fec = counters.retransmitted;
2691 rtx_counters.transmitted = counters.transmitted;
2692 // Advance one interval and update counters.
2693 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2694 proxy->DataCountersUpdated(counters, kFirstSsrc);
2695 proxy->DataCountersUpdated(counters, kSecondSsrc);
2696 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2697 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2698 }
Erik Språng22c2b482016-03-01 09:40:42 +01002699
asapersson93e1e232017-02-06 05:18:35 -08002700 // Reset stats proxy also causes histograms to be reported.
2701 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002702
asapersson93e1e232017-02-06 05:18:35 -08002703 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002704 EXPECT_METRIC_EQ(
2705 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2706 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002707 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2708 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002709 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002710 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002711 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2712 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002713 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002714 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2715 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2716 EXPECT_METRIC_EQ(
2717 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2718 12));
asapersson93e1e232017-02-06 05:18:35 -08002719 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002720 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2721 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2722 EXPECT_METRIC_EQ(
2723 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2724 16));
asapersson93e1e232017-02-06 05:18:35 -08002725 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002726 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002727 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002728 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2729 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002730 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002731 EXPECT_METRIC_EQ(
2732 1, metrics::NumSamples(
2733 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2734 EXPECT_METRIC_EQ(
2735 1, metrics::NumEvents(
2736 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002737}
Erik Språng22c2b482016-03-01 09:40:42 +01002738
asapersson93e1e232017-02-06 05:18:35 -08002739TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2740 StreamDataCountersCallback* proxy =
2741 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2742 StreamDataCounters counters;
2743 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002744
asapersson93e1e232017-02-06 05:18:35 -08002745 const int kMinRequiredPeriodSamples = 8;
2746 const int kPeriodIntervalMs = 2000;
2747 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2748 counters.transmitted.packets += 20;
2749 counters.transmitted.header_bytes += 500;
2750 counters.transmitted.payload_bytes += 2000;
2751 counters.fec = counters.retransmitted;
2752 // Advance one interval and update counters.
2753 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2754 proxy->DataCountersUpdated(counters, kFirstSsrc);
2755 }
2756
2757 // RTX enabled. No data sent over RTX.
2758 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002759 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2760 EXPECT_METRIC_EQ(1,
2761 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002762}
2763
2764TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002765 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 05:18:35 -08002766 VideoSendStream::Config config(nullptr);
2767 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2768 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01002769 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2770 field_trials));
asapersson93e1e232017-02-06 05:18:35 -08002771
2772 StreamDataCountersCallback* proxy =
2773 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2774 StreamDataCounters counters;
2775
2776 const int kMinRequiredPeriodSamples = 8;
2777 const int kPeriodIntervalMs = 2000;
2778 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2779 counters.transmitted.packets += 20;
2780 counters.transmitted.header_bytes += 500;
2781 counters.transmitted.payload_bytes += 2000;
2782 counters.fec = counters.retransmitted;
2783 // Advance one interval and update counters.
2784 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2785 proxy->DataCountersUpdated(counters, kFirstSsrc);
2786 }
2787
2788 // RTX not enabled.
2789 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002790 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002791}
2792
2793TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2794 StreamDataCountersCallback* proxy =
2795 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2796 StreamDataCounters counters;
2797 StreamDataCounters rtx_counters;
2798
2799 const int kMinRequiredPeriodSamples = 8;
2800 const int kPeriodIntervalMs = 2000;
2801 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2802 counters.transmitted.packets += 20;
2803 counters.transmitted.header_bytes += 500;
2804 counters.transmitted.payload_bytes += 2000;
2805 // Advance one interval and update counters.
2806 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2807 proxy->DataCountersUpdated(counters, kFirstSsrc);
2808 }
2809
2810 // FEC enabled. No FEC data sent.
2811 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002812 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2813 EXPECT_METRIC_EQ(1,
2814 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002815}
2816
2817TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002818 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 05:18:35 -08002819 VideoSendStream::Config config(nullptr);
2820 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2821 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01002822 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2823 field_trials));
asapersson93e1e232017-02-06 05:18:35 -08002824
2825 StreamDataCountersCallback* proxy =
2826 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2827 StreamDataCounters counters;
2828
2829 const int kMinRequiredPeriodSamples = 8;
2830 const int kPeriodIntervalMs = 2000;
2831 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2832 counters.transmitted.packets += 20;
2833 counters.transmitted.header_bytes += 500;
2834 counters.transmitted.payload_bytes += 2000;
2835 counters.fec = counters.retransmitted;
2836 // Advance one interval and update counters.
2837 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2838 proxy->DataCountersUpdated(counters, kFirstSsrc);
2839 }
2840
2841 // FEC not enabled.
2842 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002843 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002844}
2845
asapersson8d75ac72017-09-15 06:41:15 -07002846TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002847 const std::string kName = "encoderName";
Evan Shrubsole09da10e2022-10-14 14:38:31 +00002848 statistics_proxy_->OnEncoderImplementationChanged(EncoderImplementation{
2849 .name = kName,
2850 .is_hardware_accelerated = true,
2851 });
Erik Språnge2fd86a2018-10-24 11:32:39 +02002852 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
Evan Shrubsole09da10e2022-10-14 14:38:31 +00002853 EXPECT_THAT(statistics_proxy_->GetStats().power_efficient_encoder,
2854 ::testing::IsTrue());
asapersson8d75ac72017-09-15 06:41:15 -07002855}
2856
Sergey Silkinbb081a62018-09-04 18:34:22 +02002857TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2858 static const int kEncodedWidth = 123;
2859 static const int kEncodedHeight = 81;
2860 EncodedImage encoded_image;
2861 encoded_image._encodedWidth = kEncodedWidth;
2862 encoded_image._encodedHeight = kEncodedHeight;
2863 encoded_image.SetSpatialIndex(0);
2864
2865 CodecSpecificInfo codec_info;
2866 codec_info.codecType = kVideoCodecVP9;
2867
2868 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002869 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002870 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2871 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2872 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2873 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2874
2875 // Top layer updates resolution.
2876 encoded_image._encodedWidth = kEncodedWidth * 2;
2877 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002878 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002879 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2880 stats = statistics_proxy_->GetStats();
2881 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2882 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2883
2884 // Low layer of next frame doesn't update resolution.
2885 encoded_image._encodedWidth = kEncodedWidth;
2886 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002887 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002888 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2889 stats = statistics_proxy_->GetStats();
2890 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2891 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2892}
2893
asapersson8d75ac72017-09-15 06:41:15 -07002894class ForcedFallbackTest : public SendStatisticsProxyTest {
2895 public:
2896 explicit ForcedFallbackTest(const std::string& field_trials)
2897 : SendStatisticsProxyTest(field_trials) {
2898 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002899 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002900 encoded_image_._encodedWidth = kWidth;
2901 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002902 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002903 }
2904
2905 ~ForcedFallbackTest() override {}
2906
2907 protected:
2908 void InsertEncodedFrames(int num_frames, int interval_ms) {
Evan Shrubsole09da10e2022-10-14 14:38:31 +00002909 statistics_proxy_->OnEncoderImplementationChanged(
2910 {.name = codec_name_, .is_hardware_accelerated = false});
Erik Språnge2fd86a2018-10-24 11:32:39 +02002911
asapersson8d75ac72017-09-15 06:41:15 -07002912 // First frame is not updating stats, insert initial frame.
2913 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2914 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2915 }
2916 for (int i = 0; i < num_frames; ++i) {
2917 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2918 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2919 }
2920 // Add frame to include last time interval.
2921 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2922 }
2923
2924 EncodedImage encoded_image_;
2925 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002926 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002927 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2928 const int kFrameIntervalMs = 1000;
2929 const int kMinFrames = 20; // Min run time 20 sec.
2930};
2931
2932class ForcedFallbackDisabled : public ForcedFallbackTest {
2933 public:
2934 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002935 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2936 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002937};
2938
2939class ForcedFallbackEnabled : public ForcedFallbackTest {
2940 public:
2941 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002942 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2943 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002944};
2945
2946TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2947 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2948 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002949 EXPECT_METRIC_EQ(0,
2950 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2951 EXPECT_METRIC_EQ(
2952 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002953}
2954
2955TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2956 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002957 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002958 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002959 EXPECT_METRIC_EQ(1,
2960 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2961 EXPECT_METRIC_EQ(
2962 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2963 EXPECT_METRIC_EQ(
2964 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2965 EXPECT_METRIC_EQ(
2966 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002967}
2968
2969TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2970 codec_info_.codecType = kVideoCodecVP9;
2971 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2972 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002973 EXPECT_METRIC_EQ(0,
2974 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2975 EXPECT_METRIC_EQ(
2976 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002977}
2978
2979TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2980 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2981 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2982 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002983 EXPECT_METRIC_EQ(0,
2984 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2985 EXPECT_METRIC_EQ(
2986 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002987}
2988
2989TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002990 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002991 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2992 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002993 EXPECT_METRIC_EQ(0,
2994 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2995 EXPECT_METRIC_EQ(
2996 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002997}
2998
2999TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
3000 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3001 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003002 EXPECT_METRIC_EQ(0,
3003 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3004 EXPECT_METRIC_EQ(
3005 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003006}
3007
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003008TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
3009 InsertEncodedFrames(1, kFrameIntervalMs);
3010 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3011}
3012
3013TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
3014 InsertEncodedFrames(1, kFrameIntervalMs);
3015 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3016}
3017
3018TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02003019 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003020 InsertEncodedFrames(1, kFrameIntervalMs);
3021 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3022}
3023
3024TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
3025 encoded_image_._encodedWidth = kWidth + 1;
3026 InsertEncodedFrames(1, kFrameIntervalMs);
3027 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3028}
3029
3030TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02003031 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003032 InsertEncodedFrames(1, kFrameIntervalMs);
3033 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3034}
3035
3036TEST_F(ForcedFallbackDisabled,
3037 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
3038 encoded_image_._encodedWidth = kWidth + 1;
3039 statistics_proxy_->OnMinPixelLimitReached();
3040 InsertEncodedFrames(1, kFrameIntervalMs);
3041 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3042}
3043
asapersson8d75ac72017-09-15 06:41:15 -07003044TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
3045 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003046 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003047 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003048 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003049 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003050 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003051 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003052
3053 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003054 EXPECT_METRIC_EQ(1,
3055 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3056 EXPECT_METRIC_EQ(
3057 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3058 EXPECT_METRIC_EQ(
3059 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3060 EXPECT_METRIC_EQ(
3061 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003062}
3063
3064TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
3065 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
3066 const int kMaxFrameDiffMs = 2000;
3067
3068 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
3069 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003070 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003071 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003072 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003073 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003074 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003075 InsertEncodedFrames(20, 1000);
3076 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
3077 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003078 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003079 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07003080 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003081 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003082 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003083 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003084 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003085
3086 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003087 EXPECT_METRIC_EQ(1,
3088 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3089 EXPECT_METRIC_EQ(
3090 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3091 EXPECT_METRIC_EQ(
3092 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3093 EXPECT_METRIC_EQ(
3094 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003095}
3096
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003097TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
3098 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003099 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003100 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3101
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003102 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003103 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003104 EXPECT_METRIC_EQ(0,
3105 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3106 EXPECT_METRIC_EQ(
3107 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003108}
3109
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003110TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
3111 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003112 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003113 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3114
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003115 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003116 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003117 EXPECT_METRIC_EQ(1,
3118 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3119 EXPECT_METRIC_EQ(
3120 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003121}
3122
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00003123} // namespace webrtc