blob: c83739d3ed75f1bdbbbb22cd542b12e6ec1eaf3e [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:341/*
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 04:47:3111#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:3412
Steve Antonbd631a02019-03-28 17:51:2713#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:3414#include <map>
kwiberg27f982b2016-03-01 19:52:3315#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:3416#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 17:51:2719#include "absl/algorithm/container.h"
Henrik Boström23aff9b2019-05-20 13:15:3820#include "api/units/timestamp.h"
Evan Shrubsolece0a11d2020-04-16 09:36:5521#include "api/video/video_adaptation_reason.h"
Evan Shrubsolecc62b162019-09-09 09:26:4522#include "api/video/video_bitrate_allocation.h"
23#include "api/video/video_codec_type.h"
Evan Shrubsole9b235cd2022-12-06 10:09:1024#include "api/video_codecs/scalability_mode.h"
Evan Shrubsolecc62b162019-09-09 09:26:4525#include "api/video_codecs/video_codec.h"
Henrik Boström23aff9b2019-05-20 13:15:3826#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3127#include "system_wrappers/include/metrics.h"
Evan Shrubsole09da10e2022-10-14 14:38:3128#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3129#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 11:52:4830#include "test/scoped_key_value_config.h"
Jonas Oreland6c2dae22022-09-29 08:28:2431#include "video/config/video_encoder_config.h"
Evan Shrubsole09da10e2022-10-14 14:38:3132#include "video/video_stream_encoder_observer.h"
sprang@webrtc.orgccd42842014-01-07 09:54:3433
34namespace webrtc {
asapersson5265fed2016-04-18 09:58:4735namespace {
Evan Shrubsole9b235cd2022-12-06 10:09:1036
37using ::testing::Optional;
38
asapersson5265fed2016-04-18 09:58:4739const uint32_t kFirstSsrc = 17;
40const uint32_t kSecondSsrc = 42;
41const uint32_t kFirstRtxSsrc = 18;
42const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 11:52:4643const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 09:40:3544const int kFpsPeriodicIntervalMs = 2000;
45const int kWidth = 640;
46const int kHeight = 480;
asapersson5265fed2016-04-18 09:58:4747const int kQpIdx0 = 21;
48const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 14:54:4449const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 14:32:1650const CodecSpecificInfo kDefaultCodecInfo = []() {
51 CodecSpecificInfo codec_info;
52 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 14:32:1653 return codec_info;
54}();
Evan Shrubsoledff79252020-04-16 09:34:3255
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 09:58:4765} // namespace
sprang07fb9be2016-02-24 15:55:0066
stefan@webrtc.org168f23f2014-07-11 13:44:0267class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:3468 public:
asapersson8d75ac72017-09-15 13:41:1569 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
70 explicit SendStatisticsProxyTest(const std::string& field_trials)
71 : override_field_trials_(field_trials),
Danil Chapovalov2d162c42023-09-08 09:51:1372 fake_clock_(Timestamp::Seconds(1234)),
Åsa Persson90719572021-04-08 17:05:3073 config_(GetTestConfig()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:3474 virtual ~SendStatisticsProxyTest() {}
75
76 protected:
77 virtual void SetUp() {
asapersson01d70a32016-05-20 13:29:4678 metrics::Reset();
Jonas Oreland8ca06132022-03-14 11:52:4879 statistics_proxy_.reset(
80 new SendStatisticsProxy(&fake_clock_, GetTestConfig(),
81 VideoEncoderConfig::ContentType::kRealtimeVideo,
82 override_field_trials_));
sprang@webrtc.orgccd42842014-01-07 09:54:3483 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 12:30:5084 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:3494 }
95
96 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 11:07:1097 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 15:55:0098 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-05 06:28:39102 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34103 return config;
104 }
105
asaperssona6a699a2016-11-25 11:52:46106 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 14:59:19112 config.rtp.flexfec.payload_type = 50;
113 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 12:30:50114 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 11:52:46115 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 14:50:53126 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:29133 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
Di Wu668dbf62021-02-27 08:29:15134 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29135 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:29137 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f32014-03-13 13:31:21138 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29139
140 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16141 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29142 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16143 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:29146 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16147 const VideoSendStream::StreamStats& a = it->second;
148 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29149
Henrik Boströmf45ca372020-03-24 12:30:50150 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16151 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:29153 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02154 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:29156
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59157 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:29168
Danil Chapovalovea7474e2021-05-18 10:48:12169 EXPECT_EQ(a.report_block_data.has_value(),
170 b.report_block_data.has_value());
171 if (a.report_block_data.has_value()) {
Danil Chapovalovea33f7f2023-05-04 10:12:33172 EXPECT_EQ(a.report_block_data->fraction_lost_raw(),
173 b.report_block_data->fraction_lost_raw());
174 EXPECT_EQ(a.report_block_data->cumulative_lost(),
175 b.report_block_data->cumulative_lost());
176 EXPECT_EQ(a.report_block_data->extended_highest_sequence_number(),
177 b.report_block_data->extended_highest_sequence_number());
178 EXPECT_EQ(a.report_block_data->jitter(), b.report_block_data->jitter());
Danil Chapovalovea7474e2021-05-18 10:48:12179 }
sprang@webrtc.org09315702014-02-07 12:06:29180 }
181 }
182
Jonas Oreland8ca06132022-03-14 11:52:48183 test::ScopedKeyValueConfig override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21184 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 19:52:33185 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34186 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34187 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34188};
189
Danil Chapovalovf01c2c92021-05-14 13:39:23190TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
191 ReportBlockDataObserver* callback = statistics_proxy_.get();
192 for (uint32_t ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34193 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 10:48:12194 uint32_t offset = ssrc * 4;
Danil Chapovalovec2670e2023-04-12 11:11:21195 rtcp::ReportBlock report_block;
196 report_block.SetMediaSsrc(ssrc);
197 report_block.SetCumulativeLost(offset);
198 report_block.SetExtHighestSeqNum(offset + 1);
199 report_block.SetFractionLost(offset + 2);
200 report_block.SetJitter(offset + 3);
Danil Chapovalovf01c2c92021-05-14 13:39:23201 ReportBlockData data;
Danil Chapovalovec2670e2023-04-12 11:11:21202 data.SetReportBlock(/*sender_ssrc=*/0, report_block, Timestamp::Zero());
Danil Chapovalovea7474e2021-05-18 10:48:12203 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 13:39:23204
205 callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34206 }
Danil Chapovalovf01c2c92021-05-14 13:39:23207 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49208 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 10:48:12209 uint32_t offset = ssrc * 4;
Danil Chapovalovec2670e2023-04-12 11:11:21210 rtcp::ReportBlock report_block;
211 report_block.SetMediaSsrc(ssrc);
212 report_block.SetCumulativeLost(offset);
213 report_block.SetExtHighestSeqNum(offset + 1);
214 report_block.SetFractionLost(offset + 2);
215 report_block.SetJitter(offset + 3);
Danil Chapovalovf01c2c92021-05-14 13:39:23216 ReportBlockData data;
Danil Chapovalovec2670e2023-04-12 11:11:21217 data.SetReportBlock(/*sender_ssrc=*/0, report_block, Timestamp::Zero());
Danil Chapovalovea7474e2021-05-18 10:48:12218 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 13:39:23219
220 callback->OnReportBlockDataUpdated(data);
stefan@webrtc.org58e2d262014-08-14 15:10:49221 }
sprang@webrtc.orgccd42842014-01-07 09:54:34222 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29223 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34224}
225
henrik.lundin@webrtc.orgb10363f32014-03-13 13:31:21226TEST_F(SendStatisticsProxyTest, Suspended) {
227 // Verify that the value is false by default.
228 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
229
230 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 14:28:51231 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f32014-03-13 13:31:21232 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
233
234 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 14:28:51235 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f32014-03-13 13:31:21236 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
237}
238
sprang@webrtc.orgccd42842014-01-07 09:54:34239TEST_F(SendStatisticsProxyTest, FrameCounts) {
240 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-03 06:44:01241 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34242 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16243 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
244 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16245 FrameCounts frame_counts;
246 frame_counts.key_frames = offset;
247 frame_counts.delta_frames = offset + 1;
248 stats.frame_counts = frame_counts;
249 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34250 }
asapersson35151f32016-05-03 06:44:01251 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49252 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16253 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
254 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16255 FrameCounts frame_counts;
256 frame_counts.key_frames = offset;
257 frame_counts.delta_frames = offset + 1;
258 stats.frame_counts = frame_counts;
259 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49260 }
sprang@webrtc.orgccd42842014-01-07 09:54:34261
262 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29263 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34264}
265
266TEST_F(SendStatisticsProxyTest, DataCounters) {
267 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-03 06:44:01268 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34269 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
270 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14271 size_t offset = ssrc * sizeof(StreamDataCounters);
272 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59273 counters.transmitted.payload_bytes = offset;
274 counters.transmitted.header_bytes = offset + 1;
275 counters.fec.packets = offset_uint32 + 2;
276 counters.transmitted.padding_bytes = offset + 3;
277 counters.retransmitted.packets = offset_uint32 + 4;
278 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34279 callback->DataCountersUpdated(counters, ssrc);
280 }
asapersson35151f32016-05-03 06:44:01281 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49282 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
283 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14284 size_t offset = ssrc * sizeof(StreamDataCounters);
285 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59286 counters.transmitted.payload_bytes = offset;
287 counters.transmitted.header_bytes = offset + 1;
288 counters.fec.packets = offset_uint32 + 2;
289 counters.transmitted.padding_bytes = offset + 3;
290 counters.retransmitted.packets = offset_uint32 + 4;
291 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49292 callback->DataCountersUpdated(counters, ssrc);
293 }
sprang@webrtc.orgccd42842014-01-07 09:54:34294
295 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29296 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34297}
298
299TEST_F(SendStatisticsProxyTest, Bitrate) {
300 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-03 06:44:01301 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02302 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 17:05:30303 uint32_t total = ssrc;
304 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29305 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 16:11:28306 expected_.substreams[ssrc].total_bitrate_bps = total;
307 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34308 }
asapersson35151f32016-05-03 06:44:01309 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49310 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 17:05:30311 uint32_t total = ssrc;
312 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29313 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 16:11:28314 expected_.substreams[ssrc].total_bitrate_bps = total;
315 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49316 }
sprang@webrtc.orgccd42842014-01-07 09:54:34317
318 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29319 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34320}
321
stefan@webrtc.org168f23f2014-07-11 13:44:02322TEST_F(SendStatisticsProxyTest, SendSideDelay) {
Danil Chapovalov652eccf2023-09-13 08:37:27323 for (uint32_t ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02324 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
325 // stream.
Danil Chapovalov652eccf2023-09-13 08:37:27326 expected_.substreams[ssrc].avg_delay_ms = ssrc;
327 expected_.substreams[ssrc].max_delay_ms = ssrc + 1;
328 statistics_proxy_->OnSendPacket(ssrc,
329 /*capture_time=*/fake_clock_.CurrentTime() -
330 TimeDelta::Millis(ssrc + 1));
331 statistics_proxy_->OnSendPacket(ssrc,
332 /*capture_time=*/fake_clock_.CurrentTime() -
333 TimeDelta::Millis(ssrc - 1));
stefan@webrtc.org168f23f2014-07-11 13:44:02334 }
Danil Chapovalov652eccf2023-09-13 08:37:27335 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49336 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
337 // stream.
Danil Chapovalov652eccf2023-09-13 08:37:27338 expected_.substreams[ssrc].avg_delay_ms = ssrc;
339 expected_.substreams[ssrc].max_delay_ms = ssrc + 1;
340 statistics_proxy_->OnSendPacket(ssrc,
341 /*capture_time=*/fake_clock_.CurrentTime() -
342 TimeDelta::Millis(ssrc + 1));
343 statistics_proxy_->OnSendPacket(ssrc,
344 /*capture_time=*/fake_clock_.CurrentTime() -
345 TimeDelta::Millis(ssrc - 1));
stefan@webrtc.org58e2d262014-08-14 15:10:49346 }
sprang@webrtc.orgccd42842014-01-07 09:54:34347 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02348 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34349}
350
Peter Boströme4499152016-02-05 10:13:28351TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 11:12:22352 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 07:29:58353 int encode_usage_percent = 80;
354 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
355 encode_usage_percent);
asapersson1aa420b2015-12-07 11:12:22356
357 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
358 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 07:29:58359 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 11:12:22360}
361
Henrik Boström5684af52019-04-02 13:05:21362TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
363 const int kEncodeUsagePercent = 0; // Don't care for this test.
364 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
365 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
366 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
367 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
368 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
369}
370
sakal43536c32016-10-24 08:46:43371TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
372 EncodedImage encoded_image;
373 CodecSpecificInfo codec_info;
374 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
375 for (uint32_t i = 1; i <= 3; ++i) {
376 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
377 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
378 }
379}
380
sakal87da4042016-10-31 13:53:47381TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
382 EncodedImage encoded_image;
383 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 13:54:46384 auto ssrc = config_.rtp.ssrcs[0];
385 EXPECT_EQ(absl::nullopt,
386 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 13:53:47387 encoded_image.qp_ = 3;
388 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 13:54:46389 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 13:53:47390 encoded_image.qp_ = 127;
391 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 13:54:46392 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 13:53:47393}
394
395TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
396 EncodedImage encoded_image;
397 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 13:54:46398 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 13:53:47399 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 13:54:46400 EXPECT_EQ(absl::nullopt,
401 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 13:53:47402 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 13:54:46403 EXPECT_EQ(absl::nullopt,
404 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 13:53:47405}
406
Evan Shrubsole9b235cd2022-12-06 10:09:10407TEST_F(SendStatisticsProxyTest,
408 OnSendEncodedImageSetsScalabilityModeOfCurrentLayer) {
409 EncodedImage encoded_image;
410 CodecSpecificInfo codec_info;
411 ScalabilityMode layer0_mode = ScalabilityMode::kL1T1;
412 ScalabilityMode layer1_mode = ScalabilityMode::kL1T3;
413 auto ssrc0 = config_.rtp.ssrcs[0];
414 auto ssrc1 = config_.rtp.ssrcs[1];
415 EXPECT_EQ(absl::nullopt,
416 statistics_proxy_->GetStats().substreams[ssrc0].scalability_mode);
417 EXPECT_EQ(absl::nullopt,
418 statistics_proxy_->GetStats().substreams[ssrc1].scalability_mode);
Henrik Boström2e540a22023-02-15 13:48:09419 encoded_image.SetSimulcastIndex(0);
Evan Shrubsole9b235cd2022-12-06 10:09:10420 codec_info.scalability_mode = layer0_mode;
421 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
422 EXPECT_THAT(statistics_proxy_->GetStats().substreams[ssrc0].scalability_mode,
423 layer0_mode);
424 EXPECT_EQ(absl::nullopt,
425 statistics_proxy_->GetStats().substreams[ssrc1].scalability_mode);
Henrik Boström2e540a22023-02-15 13:48:09426 encoded_image.SetSimulcastIndex(1);
Evan Shrubsole9b235cd2022-12-06 10:09:10427 codec_info.scalability_mode = layer1_mode;
428 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
429 EXPECT_THAT(statistics_proxy_->GetStats().substreams[ssrc0].scalability_mode,
430 layer0_mode);
431 EXPECT_THAT(statistics_proxy_->GetStats().substreams[ssrc1].scalability_mode,
432 layer1_mode);
433}
434
Henrik Boström23aff9b2019-05-20 13:15:38435TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
436 const uint32_t kTargetBytesPerSecond = 100000;
437 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
438 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
439
440 EncodedImage encoded_image;
441 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
442 // On the first frame we don't know the frame rate yet, calculation yields
443 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
Artem Titovab30d722021-07-27 14:22:11444 // increment by a full `kTargetBytesPerSecond`.
Henrik Boström23aff9b2019-05-20 13:15:38445 EXPECT_EQ(kTargetBytesPerSecond,
446 statistics_proxy_->GetStats().total_encoded_bytes_target);
447}
448
449TEST_F(SendStatisticsProxyTest,
450 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
451 const uint32_t kTargetBytesPerSecond = 100000;
452 const int kInterframeDelayMs = 100;
453
454 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
Artem Titovab30d722021-07-27 14:22:11455 // `fake_clock_` for testing, but the RateTracker relies on a global clock.
Henrik Boström23aff9b2019-05-20 13:15:38456 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
457 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
458 // this test can stop relying on rtc::ScopedFakeClock.
459 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 10:16:00460 fake_global_clock.SetTime(
461 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 13:15:38462
463 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
464 EncodedImage encoded_image;
465
466 // First frame
467 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
468 uint64_t first_total_encoded_bytes_target =
469 statistics_proxy_->GetStats().total_encoded_bytes_target;
470 // Second frame
471 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 10:16:00472 fake_global_clock.SetTime(
473 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 13:15:38474 encoded_image.SetTimestamp(encoded_image.Timestamp() +
475 90 * kInterframeDelayMs);
476 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
477
478 auto stats = statistics_proxy_->GetStats();
479 // By the time the second frame arrives, one frame has previously arrived
Artem Titovab30d722021-07-27 14:22:11480 // during a `kInterframeDelayMs` interval. The estimated encode frame rate at
Henrik Boström23aff9b2019-05-20 13:15:38481 // the second frame's arrival should be 10 FPS.
482 uint64_t delta_encoded_bytes_target =
483 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
484 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
485}
486
Henrik Boströma0ff50c2020-05-05 13:54:46487TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
488 const int kInterframeDelayMs = 100;
Åsa Persson603e6e32021-08-10 06:56:36489 const auto ssrc = config_.rtp.ssrcs[0];
Henrik Boströma0ff50c2020-05-05 13:54:46490 rtc::ScopedFakeClock fake_global_clock;
491 fake_global_clock.SetTime(
492 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
493
Henrik Boströma0ff50c2020-05-05 13:54:46494 // First frame
Åsa Persson603e6e32021-08-10 06:56:36495 EncodedImage encoded_image;
Henrik Boströma0ff50c2020-05-05 13:54:46496 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Henrik Boströma0ff50c2020-05-05 13:54:46497 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
498 fake_global_clock.SetTime(
499 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson603e6e32021-08-10 06:56:36500 // Second frame
Henrik Boströma0ff50c2020-05-05 13:54:46501 encoded_image.SetTimestamp(encoded_image.Timestamp() +
502 90 * kInterframeDelayMs);
503 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson603e6e32021-08-10 06:56:36504 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
505 fake_global_clock.SetTime(
506 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boströma0ff50c2020-05-05 13:54:46507
508 auto stats = statistics_proxy_->GetStats();
509 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
510}
511
Åsa Persson8d564722021-08-03 12:43:01512TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp8Simulcast) {
513 const int kInterframeDelayMs = 100;
514 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 06:56:36515 fake_global_clock.SetTime(
516 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 12:43:01517 EncodedImage encoded_image;
518 CodecSpecificInfo codec_info;
519 codec_info.codecType = kVideoCodecVP8;
520
521 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 12:43:01522 encoded_image.SetTimestamp(encoded_image.Timestamp() +
523 90 * kInterframeDelayMs);
Henrik Boström2e540a22023-02-15 13:48:09524 encoded_image.SetSimulcastIndex(0);
Åsa Persson8d564722021-08-03 12:43:01525 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boström2e540a22023-02-15 13:48:09526 encoded_image.SetSimulcastIndex(1);
Åsa Persson8d564722021-08-03 12:43:01527 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 06:56:36528 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
529 fake_global_clock.SetTime(
530 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 12:43:01531 }
532
533 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
534 EXPECT_EQ(2u, stats.substreams.size());
535 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
536 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson603e6e32021-08-10 06:56:36537
538 // Stop encoding second stream, expect framerate to be zero.
539 for (int i = 0; i < 10; ++i) {
540 encoded_image.SetTimestamp(encoded_image.Timestamp() +
541 90 * kInterframeDelayMs);
Henrik Boström2e540a22023-02-15 13:48:09542 encoded_image.SetSimulcastIndex(0);
Åsa Persson603e6e32021-08-10 06:56:36543 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
544 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
545 fake_global_clock.SetTime(
546 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
547 }
548
549 stats = statistics_proxy_->GetStats();
550 EXPECT_EQ(2u, stats.substreams.size());
551 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
552 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 0);
553
554 // Start encoding second stream.
555 for (int i = 0; i < 10; ++i) {
556 encoded_image.SetTimestamp(encoded_image.Timestamp() +
557 90 * kInterframeDelayMs);
Henrik Boström2e540a22023-02-15 13:48:09558 encoded_image.SetSimulcastIndex(0);
Åsa Persson603e6e32021-08-10 06:56:36559 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boström2e540a22023-02-15 13:48:09560 encoded_image.SetSimulcastIndex(1);
Åsa Persson603e6e32021-08-10 06:56:36561 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
562 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
563 fake_global_clock.SetTime(
564 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
565 }
566
567 stats = statistics_proxy_->GetStats();
568 EXPECT_EQ(2u, stats.substreams.size());
569 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
570 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson8d564722021-08-03 12:43:01571}
572
573TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp9Svc) {
574 const int kInterframeDelayMs = 100;
575 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 06:56:36576 fake_global_clock.SetTime(
577 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 12:43:01578 EncodedImage encoded_image;
579 CodecSpecificInfo codec_info;
580 codec_info.codecType = kVideoCodecVP9;
581
582 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 12:43:01583 encoded_image.SetTimestamp(encoded_image.Timestamp() +
584 90 * kInterframeDelayMs);
585 encoded_image.SetSpatialIndex(0);
586 codec_info.end_of_picture = false;
587 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
588 encoded_image.SetSpatialIndex(1);
589 codec_info.end_of_picture = true;
590 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 06:56:36591 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
592 fake_global_clock.SetTime(
593 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 12:43:01594 }
595
596 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
597 EXPECT_EQ(1u, stats.substreams.size());
598 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
599}
600
asapersson09f05612017-05-16 06:40:18601TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 09:34:32602 VideoAdaptationCounters cpu_counts;
603 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-16 06:40:18604 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 12:29:12605 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32606 cpu_counts.fps_adaptations = 1;
607 cpu_counts.resolution_adaptations = 0;
608 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:55609 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
610 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18611 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 12:29:12612 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32613 cpu_counts.fps_adaptations = 0;
614 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55615 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
616 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18617 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-05 06:40:50618 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32619 cpu_counts.fps_adaptations = 1;
620 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
621 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 09:36:55622 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
623 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18624 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 12:51:49625 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32626 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
627 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 09:36:55628 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
629 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18630 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
631 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
632}
633
634TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 09:34:32635 VideoAdaptationCounters cpu_counts;
636 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-16 06:40:18637 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
638 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32639 quality_counts.fps_adaptations = 1;
640 quality_counts.resolution_adaptations = 0;
641 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:55642 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
643 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18644 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
645 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32646 quality_counts.fps_adaptations = 0;
647 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55648 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
649 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18650 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
651 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32652 quality_counts.fps_adaptations = 1;
653 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
654 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 09:36:55655 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
656 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18657 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
658 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 09:34:32659 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
660 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 09:36:55661 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
662 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18663 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
664 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
665}
666
667TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 09:34:32668 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
669 VideoAdaptationCounters cpu_counts;
670 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 12:51:49671 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
672
Evan Shrubsoledff79252020-04-16 09:34:32673 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55674 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
675 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18676 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 12:51:49677 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
678 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
679
Evan Shrubsoledff79252020-04-16 09:34:32680 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 09:36:55681 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
682 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18683 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
684 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 12:51:49685 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-16 06:40:18686 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 12:51:49687}
688
asapersson09f05612017-05-16 06:40:18689TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 09:34:32690 VideoAdaptationCounters cpu_counts;
691 VideoAdaptationCounters quality_counts;
692 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 12:51:49693 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
694
Evan Shrubsoledff79252020-04-16 09:34:32695 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55696 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
697 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18698 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
699 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 12:51:49700 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
701
Evan Shrubsoledff79252020-04-16 09:34:32702 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 09:36:55703 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
704 cpu_counts, quality_counts);
asapersson09f05612017-05-16 06:40:18705 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 12:51:49706 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-16 06:40:18707 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
708 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 12:51:49709}
710
Evan Shrubsoledff79252020-04-16 09:34:32711TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
712 VideoAdaptationCounters cpu_counts;
713 VideoAdaptationCounters quality_counts;
714 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
715 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
716 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
717
718 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55719 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
720 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32721 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55722 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
723 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32724 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55725 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
726 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32727 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55728 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
729 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32730 // We have 1 fps and resolution reduction for both cpu and quality
731 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
732 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
733 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
734 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
735 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
736 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
737
738 // Disable quality scaling. Expect quality scaling not limited.
739 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
740 kScalingDisabled);
741 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
742 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
743 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
744 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
745 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
746 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
747
748 // Disable framerate scaling.
749 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
750 kFramerateScalingDisabled);
751 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
752 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
753 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
754 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
755 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
756 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
757
758 // Disable resolution scaling.
759 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
760 kResolutionScalingDisabled);
761 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
762 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
763 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
764 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
765 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
766 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
767
768 // Enable all
769 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
770 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
771 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
772 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
773 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
774 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
775 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
776}
777
asapersson09f05612017-05-16 06:40:18778TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 07:57:58779 // First RTP packet sent.
780 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-05 06:40:50781 // Min runtime has passed.
782 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
783 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53784 EXPECT_METRIC_EQ(
785 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
786 EXPECT_METRIC_EQ(
787 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-05 06:40:50788}
789
790TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 07:57:58791 // First RTP packet sent.
792 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-16 06:40:18793 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32794 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-05 06:40:50795 // Min runtime has not passed.
796 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
797 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53798 EXPECT_METRIC_EQ(
799 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
800 EXPECT_METRIC_EQ(
801 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-05 06:40:50802}
803
asapersson09f05612017-05-16 06:40:18804TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 07:57:58805 // First RTP packet sent.
806 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-16 06:40:18807 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32808 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-05 06:40:50809 // Min runtime has passed.
810 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
811 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53812 EXPECT_METRIC_EQ(
813 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
814 EXPECT_METRIC_EQ(
815 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
816 EXPECT_METRIC_EQ(
817 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
818 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-05 06:40:50819 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
820}
821
822TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 07:57:58823 // First RTP packet sent.
824 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-16 06:40:18825 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32826 VideoAdaptationCounters cpu_counts;
827 VideoAdaptationCounters quality_counts;
828 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 07:57:58829 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 09:36:55830 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
831 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:50832 fake_clock_.AdvanceTimeMilliseconds(10000);
833 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53834 EXPECT_METRIC_EQ(
835 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
836 EXPECT_METRIC_EQ(
837 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-05 06:40:50838}
839
Åsa Persson875841d2018-01-08 07:49:53840TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
841 // First RTP packet sent.
842 UpdateDataCounters(kFirstSsrc);
843 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32844 VideoAdaptationCounters cpu_counts;
845 VideoAdaptationCounters quality_counts;
846 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 07:49:53847 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 09:36:55848 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
849 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53850 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
851 fake_clock_.AdvanceTimeMilliseconds(10000);
852 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53853 EXPECT_METRIC_EQ(
854 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
855 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 07:49:53856 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
857}
858
859TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
860 // First RTP packet sent.
861 UpdateDataCounters(kFirstSsrc);
862 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32863 VideoAdaptationCounters cpu_counts;
864 VideoAdaptationCounters quality_counts;
865 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 07:49:53866 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 09:34:32867 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55868 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
869 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53870 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 09:34:32871 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 09:36:55872 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
873 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53874 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 09:34:32875 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 09:36:55876 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
877 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53878 fake_clock_.AdvanceTimeMilliseconds(10000);
879 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53880 EXPECT_METRIC_EQ(
881 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
882 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 07:49:53883 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
884}
885
886TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
887 // First RTP packet sent.
888 UpdateDataCounters(kFirstSsrc);
889 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32890 VideoAdaptationCounters cpu_counts;
891 VideoAdaptationCounters quality_counts;
892 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 07:49:53893 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 09:36:55894 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
895 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53896 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
897 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
898 fake_clock_.AdvanceTimeMilliseconds(10000);
899 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53900 EXPECT_METRIC_EQ(
901 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
902 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 07:49:53903 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
904}
905
906TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
907 // First RTP packet sent.
908 UpdateDataCounters(kFirstSsrc);
909 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32910 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
911 VideoAdaptationCounters cpu_counts;
912 VideoAdaptationCounters quality_counts;
913 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 07:49:53914 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 09:34:32915 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55916 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
917 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53918 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 09:34:32919 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 09:36:55920 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
921 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53922 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 09:34:32923 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 09:36:55924 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
925 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32926 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:55927 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
928 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32929 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 09:36:55930 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
931 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32932 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 09:36:55933 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
934 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32935 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 09:36:55936 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
937 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 09:34:32938 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 09:36:55939 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
940 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 07:49:53941
942 fake_clock_.AdvanceTimeMilliseconds(10000);
943 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:53944 EXPECT_METRIC_EQ(
945 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
946 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 07:49:53947 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
948}
949
asapersson6eca98b2017-04-05 06:40:50950TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 07:57:58951 // First RTP packet sent.
952 UpdateDataCounters(kFirstSsrc);
953
asapersson09f05612017-05-16 06:40:18954 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32955 VideoAdaptationCounters cpu_counts;
956 VideoAdaptationCounters quality_counts;
957 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
958 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:50959 fake_clock_.AdvanceTimeMilliseconds(10000);
960
asapersson09f05612017-05-16 06:40:18961 // Enable quality adaptation.
asapersson0944a802017-04-07 07:57:58962 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 09:34:32963 quality_counts.fps_adaptations = 0;
964 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
965 kResolutionScalingDisabled);
asapersson6eca98b2017-04-05 06:40:50966 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 09:34:32967 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
968 kResolutionScalingDisabled);
asapersson6eca98b2017-04-05 06:40:50969 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 09:36:55970 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
971 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:50972 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 09:36:55973 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
974 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:50975
asapersson09f05612017-05-16 06:40:18976 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32977 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
978 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:50979 fake_clock_.AdvanceTimeMilliseconds(30000);
980
asapersson09f05612017-05-16 06:40:18981 // Enable quality adaptation.
asapersson0944a802017-04-07 07:57:58982 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 09:34:32983 quality_counts.resolution_adaptations = 0;
984 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
985 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 09:36:55986 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
987 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:50988 fake_clock_.AdvanceTimeMilliseconds(10000);
989
asapersson09f05612017-05-16 06:40:18990 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 09:34:32991 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
992 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:50993 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 09:34:32994 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
995 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:50996 fake_clock_.AdvanceTimeMilliseconds(20000);
997
asapersson0944a802017-04-07 07:57:58998 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-05 06:40:50999 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531000 EXPECT_METRIC_EQ(
1001 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1002 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-05 06:40:501003 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1004}
1005
asapersson0944a802017-04-07 07:57:581006TEST_F(SendStatisticsProxyTest,
1007 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
1008 // First RTP packet sent.
1009 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-05 06:40:501010
asapersson0944a802017-04-07 07:57:581011 // Suspend and resume video.
1012 statistics_proxy_->OnSuspendChange(true);
1013 fake_clock_.AdvanceTimeMilliseconds(5000);
1014 statistics_proxy_->OnSuspendChange(false);
1015
1016 // Min runtime has passed but scaling not enabled.
1017 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1018 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531019 EXPECT_METRIC_EQ(
1020 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1021 EXPECT_METRIC_EQ(
1022 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 07:57:581023}
1024
1025TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
1026 // First RTP packet sent.
1027 UpdateDataCounters(kFirstSsrc);
1028
asapersson09f05612017-05-16 06:40:181029 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:321030 VideoAdaptationCounters cpu_counts;
1031 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 07:57:581032 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 09:34:321033 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 07:57:581034 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 09:36:551035 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1036 cpu_counts, quality_counts);
1037 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1038 cpu_counts, quality_counts);
asapersson0944a802017-04-07 07:57:581039
1040 // Suspend and resume video.
1041 statistics_proxy_->OnSuspendChange(true);
1042 fake_clock_.AdvanceTimeMilliseconds(30000);
1043 statistics_proxy_->OnSuspendChange(false);
1044
1045 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 09:36:551046 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1047 cpu_counts, quality_counts);
asapersson0944a802017-04-07 07:57:581048 fake_clock_.AdvanceTimeMilliseconds(10000);
1049
1050 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
1051 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531052 EXPECT_METRIC_EQ(
1053 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1054 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 07:57:581055 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1056}
1057
1058TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
1059 // First RTP packet sent.
1060 UpdateDataCounters(kFirstSsrc);
1061
1062 // Video not suspended.
1063 statistics_proxy_->OnSuspendChange(false);
1064 fake_clock_.AdvanceTimeMilliseconds(30000);
1065
asapersson09f05612017-05-16 06:40:181066 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:321067 VideoAdaptationCounters cpu_counts;
1068 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 07:57:581069 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 09:34:321070 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 07:57:581071 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 09:36:551072 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1073 cpu_counts, quality_counts);
asapersson0944a802017-04-07 07:57:581074
1075 // Video not suspended, stats time already started.
1076 statistics_proxy_->OnSuspendChange(false);
1077 fake_clock_.AdvanceTimeMilliseconds(10000);
1078
asapersson09f05612017-05-16 06:40:181079 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:321080 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1081 kScalingDisabled);
asapersson0944a802017-04-07 07:57:581082 fake_clock_.AdvanceTimeMilliseconds(30000);
1083
1084 // Suspend and resume video, stats time not started when scaling not enabled.
1085 statistics_proxy_->OnSuspendChange(true);
1086 fake_clock_.AdvanceTimeMilliseconds(30000);
1087 statistics_proxy_->OnSuspendChange(false);
1088 fake_clock_.AdvanceTimeMilliseconds(30000);
1089
asapersson09f05612017-05-16 06:40:181090 // Enable adaptation.
asapersson0944a802017-04-07 07:57:581091 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 09:34:321092 cpu_counts.fps_adaptations = 0;
1093 cpu_counts.resolution_adaptations = 0;
1094 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 07:57:581095 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 09:36:551096 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1097 cpu_counts, quality_counts);
asapersson0944a802017-04-07 07:57:581098
1099 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
1100 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531101 EXPECT_METRIC_EQ(
1102 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1103 EXPECT_METRIC_EQ(
1104 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 07:57:581105}
1106
1107TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
1108 // First RTP packet sent.
1109 UpdateDataCounters(kFirstSsrc);
1110
1111 // Video suspended.
1112 statistics_proxy_->OnSuspendChange(true);
1113
asapersson09f05612017-05-16 06:40:181114 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 09:34:321115 VideoAdaptationCounters cpu_counts;
1116 VideoAdaptationCounters quality_counts;
1117 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 07:57:581118 fake_clock_.AdvanceTimeMilliseconds(10000);
1119
1120 // Resume video, stats time started.
1121 // Adapt changes: 1, elapsed time: 10 sec.
1122 statistics_proxy_->OnSuspendChange(false);
1123 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 09:36:551124 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1125 cpu_counts, quality_counts);
asapersson0944a802017-04-07 07:57:581126
1127 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1128 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531129 EXPECT_METRIC_EQ(
1130 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1131 EXPECT_METRIC_EQ(
1132 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 07:57:581133}
1134
1135TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-16 06:40:181136 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-05 06:40:501137 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 09:34:321138 VideoAdaptationCounters cpu_counts;
1139 VideoAdaptationCounters quality_counts;
1140 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-05 06:40:501141 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 07:57:581142 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-05 06:40:501143
asapersson0944a802017-04-07 07:57:581144 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-05 06:40:501145 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 09:36:551146 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1147 cpu_counts, quality_counts);
asapersson0944a802017-04-07 07:57:581148 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-05 06:40:501149
asapersson0944a802017-04-07 07:57:581150 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-05 06:40:501151 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531152 EXPECT_METRIC_EQ(
1153 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1154 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-05 06:40:501155 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1156}
1157
1158TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-16 06:40:181159 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:321160 VideoAdaptationCounters cpu_counts;
1161 VideoAdaptationCounters quality_counts;
1162 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-05 06:40:501163 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 09:34:321164 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1165 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:501166
1167 // Send first packet, scaling disabled.
1168 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 07:57:581169 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-05 06:40:501170 fake_clock_.AdvanceTimeMilliseconds(60000);
1171
asapersson09f05612017-05-16 06:40:181172 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 09:34:321173 cpu_counts.resolution_adaptations = 0;
1174 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1175 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:501176 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 07:57:581177 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-05 06:40:501178
asapersson0944a802017-04-07 07:57:581179 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-05 06:40:501180 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 09:36:551181 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1182 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:501183
asapersson0944a802017-04-07 07:57:581184 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-05 06:40:501185 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531186 EXPECT_METRIC_EQ(
1187 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1188 EXPECT_METRIC_EQ(
1189 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-05 06:40:501190}
1191
1192TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-16 06:40:181193 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 07:57:581194 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 09:34:321195 VideoAdaptationCounters cpu_counts;
1196 VideoAdaptationCounters quality_counts;
1197 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1198 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:501199
asapersson0944a802017-04-07 07:57:581200 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 09:36:551201 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1202 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:501203 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 09:36:551204 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1205 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:501206 fake_clock_.AdvanceTimeMilliseconds(9000);
1207
1208 // Switch content type, real-time stats should be updated.
1209 VideoEncoderConfig config;
1210 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 07:43:261211 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 12:06:531212 EXPECT_METRIC_EQ(
1213 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1214 EXPECT_METRIC_EQ(
1215 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1216 EXPECT_METRIC_EQ(
1217 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-05 06:40:501218
asapersson0944a802017-04-07 07:57:581219 // First RTP packet sent, scaling enabled.
1220 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 09:34:321221 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1222 kScalingDisabled);
asapersson6eca98b2017-04-05 06:40:501223
asapersson0944a802017-04-07 07:57:581224 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 09:36:551225 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1226 cpu_counts, quality_counts);
1227 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1228 cpu_counts, quality_counts);
1229 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1230 cpu_counts, quality_counts);
1231 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1232 cpu_counts, quality_counts);
asapersson6eca98b2017-04-05 06:40:501233 fake_clock_.AdvanceTimeMilliseconds(120000);
1234
1235 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531236 EXPECT_METRIC_EQ(1,
1237 metrics::NumSamples(
1238 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1239 EXPECT_METRIC_EQ(
1240 1, metrics::NumEvents(
1241 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1242 EXPECT_METRIC_EQ(
1243 0, metrics::NumSamples(
1244 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-05 06:40:501245}
1246
Henrik Boströmce33b6a2019-05-28 15:42:381247TEST_F(SendStatisticsProxyTest,
1248 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 09:34:321249 VideoAdaptationCounters cpu_counts;
1250 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 15:42:381251
Evan Shrubsoledff79252020-04-16 09:34:321252 cpu_counts.resolution_adaptations = 1;
1253 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:551254 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1255 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381256
1257 EXPECT_EQ(QualityLimitationReason::kCpu,
1258 statistics_proxy_->GetStats().quality_limitation_reason);
1259}
1260
1261TEST_F(SendStatisticsProxyTest,
1262 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 09:34:321263 VideoAdaptationCounters cpu_counts;
1264 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 15:42:381265
Evan Shrubsoledff79252020-04-16 09:34:321266 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 15:42:381267
Evan Shrubsoledff79252020-04-16 09:34:321268 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:551269 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1270 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381271
1272 EXPECT_EQ(QualityLimitationReason::kCpu,
1273 statistics_proxy_->GetStats().quality_limitation_reason);
1274}
1275
1276TEST_F(SendStatisticsProxyTest,
1277 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 09:34:321278 VideoAdaptationCounters cpu_counts;
1279 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 15:42:381280
Evan Shrubsoledff79252020-04-16 09:34:321281 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 15:42:381282
Evan Shrubsoledff79252020-04-16 09:34:321283 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:551284 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1285 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381286
1287 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1288 statistics_proxy_->GetStats().quality_limitation_reason);
1289}
1290
1291TEST_F(SendStatisticsProxyTest,
1292 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 09:34:321293 VideoAdaptationCounters cpu_counts;
1294 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 15:42:381295
Evan Shrubsoledff79252020-04-16 09:34:321296 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 15:42:381297
Evan Shrubsoledff79252020-04-16 09:34:321298 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:551299 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1300 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381301
1302 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1303 statistics_proxy_->GetStats().quality_limitation_reason);
1304}
1305
1306TEST_F(SendStatisticsProxyTest,
1307 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 09:34:321308 VideoAdaptationCounters cpu_counts;
1309 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 15:42:381310
Evan Shrubsoledff79252020-04-16 09:34:321311 cpu_counts.resolution_adaptations = 1;
1312 quality_counts.resolution_adaptations = 1;
1313 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 15:42:381314
1315 // Even if the last adaptation reason is kCpu, if the counters indicate being
1316 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 09:36:551317 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1318 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381319
1320 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1321 statistics_proxy_->GetStats().quality_limitation_reason);
1322}
1323
1324TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 09:34:321325 VideoAdaptationCounters cpu_counts;
1326 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 15:42:381327
1328 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1329 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 09:34:321330 cpu_counts.resolution_adaptations = 1;
1331 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:551332 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1333 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381334 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 09:34:321335 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 09:36:551336 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1337 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381338
1339 EXPECT_EQ(QualityLimitationReason::kNone,
1340 statistics_proxy_->GetStats().quality_limitation_reason);
1341}
1342
1343TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 09:34:321344 VideoAdaptationCounters cpu_counts;
1345 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 15:42:381346
Evan Shrubsoledff79252020-04-16 09:34:321347 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 15:42:381348 // Not limited for 3000 ms
1349 fake_clock_.AdvanceTimeMilliseconds(3000);
1350 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 09:34:321351 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:551352 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1353 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381354 fake_clock_.AdvanceTimeMilliseconds(2000);
1355 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 09:34:321356 cpu_counts.resolution_adaptations = 0;
1357 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:551358 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1359 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381360 fake_clock_.AdvanceTimeMilliseconds(1000);
1361 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 09:34:321362 cpu_counts.resolution_adaptations = 1;
1363 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 09:36:551364 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1365 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 15:42:381366 fake_clock_.AdvanceTimeMilliseconds(2000);
1367
1368 auto quality_limitation_durations_ms =
1369 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1370
1371 EXPECT_EQ(3000,
1372 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1373 EXPECT_EQ(4000,
1374 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1375 EXPECT_EQ(
1376 1000,
1377 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1378 EXPECT_EQ(0,
1379 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1380}
1381
Evan Shrubsolecc62b162019-09-09 09:26:451382TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1383 EXPECT_EQ(
1384 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1385}
1386
1387TEST_F(SendStatisticsProxyTest,
1388 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1389 VideoCodec codec;
1390 VideoBitrateAllocation allocation;
1391 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1392 EXPECT_EQ(
1393 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1394}
1395
1396TEST_F(SendStatisticsProxyTest,
1397 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1398 VideoCodec codec;
1399 codec.simulcastStream[0].active = true;
1400 codec.simulcastStream[1].active = true;
1401 codec.simulcastStream[2].active = true;
1402 VideoBitrateAllocation allocation;
1403 allocation.SetBitrate(0, 0, 100);
1404 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1405 EXPECT_EQ(
1406 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1407}
1408
1409TEST_F(SendStatisticsProxyTest,
1410 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1411 VideoCodec codec;
1412 codec.simulcastStream[0].active = true;
1413 codec.simulcastStream[1].active = true;
1414 codec.simulcastStream[2].active = true;
1415 VideoBitrateAllocation allocation;
1416 allocation.SetBitrate(0, 0, 100);
1417 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1418 allocation.SetBitrate(1, 0, 100);
1419 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1420 EXPECT_EQ(
1421 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1422}
1423
1424TEST_F(SendStatisticsProxyTest,
1425 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1426 VideoCodec codec;
1427 codec.simulcastStream[0].active = true;
1428 VideoBitrateAllocation allocation;
1429 allocation.SetBitrate(0, 0, 100);
1430 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1431 // Layer 0 got more bandwidth, but still only one layer on
1432 allocation.SetBitrate(0, 0, 200);
1433 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1434 EXPECT_EQ(
1435 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1436}
1437
1438TEST_F(SendStatisticsProxyTest,
1439 QualityLimitationResolutionChangesWithTogglingLayers) {
1440 VideoCodec codec;
1441 codec.simulcastStream[0].active = true;
1442 codec.simulcastStream[1].active = true;
1443 codec.simulcastStream[2].active = true;
1444 VideoBitrateAllocation allocation;
1445 allocation.SetBitrate(0, 0, 100);
1446 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1447 EXPECT_EQ(
1448 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1449 allocation.SetBitrate(1, 0, 300);
1450 allocation.SetBitrate(2, 0, 500);
1451 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1452 EXPECT_EQ(
1453 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1454 // Layer 2 off
1455 allocation.SetBitrate(2, 0, 0);
1456 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1457 EXPECT_EQ(
1458 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1459 // Layer 2 back on
1460 allocation.SetBitrate(2, 0, 500);
1461 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1462 EXPECT_EQ(
1463 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1464 allocation.SetBitrate(0, 0, 0);
1465 allocation.SetBitrate(1, 0, 0);
1466 allocation.SetBitrate(2, 0, 0);
1467 // All layers off
1468 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1469 EXPECT_EQ(
1470 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1471}
1472
1473TEST_F(SendStatisticsProxyTest,
1474 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1475 VideoCodec codec;
1476 // 3 layers
1477 codec.simulcastStream[0].active = true;
1478 codec.simulcastStream[1].active = true;
1479 codec.simulcastStream[2].active = true;
1480 VideoBitrateAllocation allocation;
1481 allocation.SetBitrate(0, 0, 500);
1482 allocation.SetBitrate(1, 0, 500);
1483 allocation.SetBitrate(2, 0, 500);
1484 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1485 EXPECT_EQ(
1486 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1487
1488 // Down to one layer now, triggered by a config change
1489 codec.numberOfSimulcastStreams = 1;
1490 codec.simulcastStream[1].active = false;
1491 codec.simulcastStream[2].active = false;
1492 allocation.SetBitrate(0, 0, 100);
1493 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1494 EXPECT_EQ(
1495 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1496
1497 // Up to 3 layers again.
1498 codec.numberOfSimulcastStreams = 3;
1499 codec.simulcastStream[1].active = true;
1500 codec.simulcastStream[2].active = true;
1501 allocation.SetBitrate(0, 0, 500);
1502 allocation.SetBitrate(1, 0, 500);
1503 allocation.SetBitrate(2, 0, 500);
1504 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1505 EXPECT_EQ(
1506 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1507}
1508
1509TEST_F(SendStatisticsProxyTest,
1510 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1511 VideoCodec codec;
1512 codec.simulcastStream[0].active = true;
1513 codec.spatialLayers[0].active = true;
1514 codec.spatialLayers[1].active = true;
1515 codec.spatialLayers[2].active = true;
1516 VideoBitrateAllocation allocation;
1517 allocation.SetBitrate(0, 0, 500);
1518 allocation.SetBitrate(1, 0, 500);
1519 allocation.SetBitrate(2, 0, 500);
1520 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1521 EXPECT_EQ(
1522 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1523
1524 // Down to one layer now, triggered by a config change
1525 codec.spatialLayers[1].active = false;
1526 codec.spatialLayers[2].active = false;
1527 allocation.SetBitrate(0, 0, 100);
1528 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1529 EXPECT_EQ(
1530 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1531
1532 // Up to 3 layers again.
1533 codec.spatialLayers[1].active = true;
1534 codec.spatialLayers[2].active = true;
1535 allocation.SetBitrate(0, 0, 500);
1536 allocation.SetBitrate(1, 0, 500);
1537 allocation.SetBitrate(2, 0, 500);
1538 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1539 EXPECT_EQ(
1540 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1541}
1542
Ilya Nikolaevskiy5963c7c2019-10-09 16:06:581543TEST_F(SendStatisticsProxyTest,
1544 QualityLimitationReasonsAreCorrectForContentType) {
1545 // Realtime case.
1546 // Configure two streams.
1547 VideoEncoderConfig config;
1548 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1549 config.number_of_streams = 2;
1550 VideoStream stream1;
1551 stream1.width = kWidth / 2;
1552 stream1.height = kHeight / 2;
1553 VideoStream stream2;
1554 stream2.width = kWidth;
1555 stream2.height = kHeight;
1556 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1557 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1558 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1559 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1560 QualityLimitationReason::kNone);
1561 // Bw disabled one layer.
1562 VideoCodec codec;
1563 codec.numberOfSimulcastStreams = 2;
1564 codec.simulcastStream[0].active = true;
1565 codec.simulcastStream[1].active = true;
1566 VideoBitrateAllocation allocation;
1567 // Some positive bitrate only on the first stream.
1568 allocation.SetBitrate(0, 0, 10000);
1569 allocation.SetBitrate(1, 0, 0);
1570 allocation.set_bw_limited(true);
1571 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1572 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1573 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1574 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1575 QualityLimitationReason::kBandwidth);
1576 // Bw enabled all layers.
1577 allocation.SetBitrate(1, 0, 10000);
1578 allocation.set_bw_limited(false);
1579 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1580 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1581 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1582 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1583 QualityLimitationReason::kNone);
1584
1585 // Screencast case
1586 // Configure two streams.
1587 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1588 config.number_of_streams = 2;
1589 stream1.width = kWidth;
1590 stream1.height = kHeight;
1591 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1592 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1593 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1594 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1595 QualityLimitationReason::kNone);
1596 // Bw disabled one layer.
1597 // Some positive bitrate only on the second stream.
1598 allocation.SetBitrate(0, 0, 10000);
1599 allocation.SetBitrate(1, 0, 0);
1600 allocation.set_bw_limited(true);
1601 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1602 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1603 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1604 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1605 QualityLimitationReason::kBandwidth);
1606 // Bw enabled all layers.
1607 allocation.SetBitrate(1, 0, 10000);
1608 allocation.set_bw_limited(false);
1609 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1610 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1611 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1612 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1613 QualityLimitationReason::kNone);
1614}
1615
asapersson59bac1a2016-01-08 07:36:001616TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 18:45:461617 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-08 07:36:001618 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1619
Pera48ddb72016-09-29 09:48:501620 // No switch, stats should not be updated.
1621 VideoEncoderConfig config;
1622 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 07:43:261623 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 12:06:531624 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-08 07:36:001625
1626 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 09:48:501627 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 07:43:261628 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 12:06:531629 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-08 07:36:001630}
1631
asapersson320e45a2016-11-29 09:40:351632TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1633 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1634 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 18:45:461635
asapersson320e45a2016-11-29 09:40:351636 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531637 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1638 EXPECT_METRIC_EQ(
1639 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1640 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1641 EXPECT_METRIC_EQ(
1642 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 09:40:351643}
1644
1645TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 10:19:231646 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 06:57:541647 const int kFps = 5;
Åsa Persson0122e842017-10-16 10:19:231648 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1649 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1650 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 09:40:351651 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 10:19:231652
1653 // Not enough samples, stats should not be updated.
1654 for (int i = 0; i < kMinSamples - 1; ++i) {
1655 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:121656 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 09:40:351657 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1658 }
Åsa Persson0122e842017-10-16 10:19:231659 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 12:06:531660 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1661 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 10:19:231662
1663 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 08:24:121664 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 10:19:231665 for (int i = 0; i < kMinSamples; ++i) {
1666 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:121667 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 10:19:231668 encoded_image._encodedWidth = kWidth;
1669 encoded_image._encodedHeight = kHeight;
1670 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1671 encoded_image._encodedWidth = kWidth / 2;
1672 encoded_image._encodedHeight = kHeight / 2;
1673 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1674 }
1675
asapersson320e45a2016-11-29 09:40:351676 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531677 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1678 EXPECT_METRIC_EQ(
1679 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1680 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1681 EXPECT_METRIC_EQ(
1682 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 09:40:351683}
1684
1685TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1686 const int kFps = 20;
1687 const int kMinPeriodicSamples = 6;
1688 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1689 for (int i = 0; i <= frames; ++i) {
1690 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1691 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1692 }
1693 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531694 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1695 EXPECT_METRIC_EQ(
1696 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 09:40:351697}
1698
1699TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1700 EncodedImage encoded_image;
1701 const int kFps = 20;
1702 const int kMinPeriodicSamples = 6;
1703 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 10:19:231704 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 09:40:351705 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:121706 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 10:19:231707 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1708 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 09:40:351709 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1710 }
1711 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531712 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1713 EXPECT_METRIC_EQ(
1714 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 09:40:351715}
1716
1717TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1718 const int kFps = 20;
1719 const int kSuspendTimeMs = 10000;
1720 const int kMinPeriodicSamples = 6;
1721 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1722 for (int i = 0; i < frames; ++i) {
1723 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1724 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1725 }
1726 // Suspend.
1727 statistics_proxy_->OnSuspendChange(true);
1728 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1729
1730 for (int i = 0; i < frames; ++i) {
1731 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1732 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1733 }
1734 // Suspended time interval should not affect the framerate.
1735 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531736 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1737 EXPECT_METRIC_EQ(
1738 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 09:40:351739}
1740
1741TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1742 EncodedImage encoded_image;
1743 const int kFps = 20;
1744 const int kSuspendTimeMs = 10000;
1745 const int kMinPeriodicSamples = 6;
1746 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 10:19:231747 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 09:40:351748 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:121749 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 09:40:351750 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1751 }
1752 // Suspend.
1753 statistics_proxy_->OnSuspendChange(true);
1754 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1755
Åsa Persson0122e842017-10-16 10:19:231756 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 09:40:351757 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:121758 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 09:40:351759 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1760 }
1761 // Suspended time interval should not affect the framerate.
1762 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531763 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1764 EXPECT_METRIC_EQ(
1765 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 09:40:351766}
1767
asaperssonf4e44af2017-04-19 09:01:061768TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 09:34:321769 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1770 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 09:01:061771
1772 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1773 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1774
1775 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531776 EXPECT_METRIC_EQ(
1777 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 09:01:061778}
1779
1780TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 09:34:321781 VideoAdaptationCounters cpu_counts;
1782 VideoAdaptationCounters quality_counts;
1783 cpu_counts.resolution_adaptations = 0;
1784 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 09:01:061785
perkj803d97f2016-11-01 18:45:461786 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1787 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1788
Evan Shrubsoledff79252020-04-16 09:34:321789 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 09:36:551790 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1791 cpu_counts, quality_counts);
perkj803d97f2016-11-01 18:45:461792
1793 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1794 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1795
1796 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531797 EXPECT_METRIC_EQ(
1798 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1799 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 18:45:461800 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1801}
1802
asapersson4374a092016-07-27 07:39:091803TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1804 const int64_t kTimeSec = 3;
1805 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1806 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531807 EXPECT_METRIC_EQ(
1808 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1809 EXPECT_METRIC_EQ(
1810 1,
1811 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 07:39:091812}
1813
1814TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1815 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1816 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531817 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 07:39:091818}
1819
asapersson66d4b372016-12-19 14:50:531820TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1821 // First RTP packet sent.
1822 UpdateDataCounters(kFirstSsrc);
1823
1824 // Min runtime has passed.
1825 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1826 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531827 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1828 EXPECT_METRIC_EQ(1,
1829 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 14:50:531830}
1831
1832TEST_F(SendStatisticsProxyTest,
1833 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1834 // First RTP packet sent.
1835 UpdateDataCounters(kFirstSsrc);
1836
1837 // Min runtime has not passed.
1838 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1839 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531840 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1841 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 14:50:531842}
1843
1844TEST_F(SendStatisticsProxyTest,
1845 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1846 // First RTP packet not sent.
1847 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1848 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531849 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 14:50:531850}
1851
1852TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1853 // First RTP packet sent and min runtime passed.
1854 UpdateDataCounters(kFirstSsrc);
1855
1856 // No change. Video: 10000 ms, paused: 0 ms (0%).
1857 statistics_proxy_->OnSetEncoderTargetRate(50000);
1858 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1859 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1860
1861 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531862 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1863 EXPECT_METRIC_EQ(1,
1864 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1865 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1866 EXPECT_METRIC_EQ(1,
1867 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 14:50:531868}
1869
1870TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1871 // First RTP packet sent and min runtime passed.
1872 UpdateDataCounters(kFirstSsrc);
1873
1874 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1875 statistics_proxy_->OnSetEncoderTargetRate(50000);
1876 fake_clock_.AdvanceTimeMilliseconds(7000);
1877 statistics_proxy_->OnSetEncoderTargetRate(0);
1878 fake_clock_.AdvanceTimeMilliseconds(3000);
1879 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1880
1881 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531882 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1883 EXPECT_METRIC_EQ(1,
1884 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1885 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1886 EXPECT_METRIC_EQ(1,
1887 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 14:50:531888}
1889
1890TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1891 // First RTP packet sent.
1892 UpdateDataCounters(kFirstSsrc);
1893
1894 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1895 statistics_proxy_->OnSetEncoderTargetRate(0);
1896 fake_clock_.AdvanceTimeMilliseconds(1000);
1897 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1898 fake_clock_.AdvanceTimeMilliseconds(7000);
1899 statistics_proxy_->OnSetEncoderTargetRate(60000);
1900 fake_clock_.AdvanceTimeMilliseconds(3000);
1901 statistics_proxy_->OnSetEncoderTargetRate(0);
1902 fake_clock_.AdvanceTimeMilliseconds(250);
1903 statistics_proxy_->OnSetEncoderTargetRate(0);
1904 fake_clock_.AdvanceTimeMilliseconds(750);
1905 statistics_proxy_->OnSetEncoderTargetRate(60000);
1906 fake_clock_.AdvanceTimeMilliseconds(5000);
1907 statistics_proxy_->OnSetEncoderTargetRate(50000);
1908 fake_clock_.AdvanceTimeMilliseconds(4000);
1909 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1910
1911 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531912 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1913 EXPECT_METRIC_EQ(1,
1914 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1915 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1916 EXPECT_METRIC_EQ(1,
1917 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 14:50:531918}
1919
1920TEST_F(SendStatisticsProxyTest,
1921 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1922 // First RTP packet sent.
1923 UpdateDataCounters(kFirstSsrc);
1924 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1925
1926 // Min runtime has not passed.
1927 statistics_proxy_->OnSetEncoderTargetRate(50000);
1928 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1929 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1930
1931 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531932 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 14:50:531933}
1934
asapersson118ef002016-03-31 07:00:191935TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 07:00:191936 EncodedImage encoded_image;
kjellander02b3d272016-04-20 12:05:541937 CodecSpecificInfo codec_info;
1938 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 07:00:191939
perkj803d97f2016-11-01 18:45:461940 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Henrik Boström2e540a22023-02-15 13:48:091941 encoded_image.SetSimulcastIndex(0);
asapersson118ef002016-03-31 07:00:191942 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 12:05:541943 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boström2e540a22023-02-15 13:48:091944 encoded_image.SetSimulcastIndex(1);
asapersson118ef002016-03-31 07:00:191945 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 12:05:541946 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 07:00:191947 }
1948 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531949 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1950 EXPECT_METRIC_EQ(
1951 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1952 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1953 EXPECT_METRIC_EQ(
1954 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 07:00:191955}
1956
1957TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
Jonas Oreland8ca06132022-03-14 11:52:481958 test::ScopedKeyValueConfig field_trials;
asapersson118ef002016-03-31 07:00:191959 VideoSendStream::Config config(nullptr);
1960 config.rtp.ssrcs.push_back(kFirstSsrc);
1961 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 11:52:481962 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1963 field_trials));
asapersson118ef002016-03-31 07:00:191964
asapersson118ef002016-03-31 07:00:191965 EncodedImage encoded_image;
kjellander02b3d272016-04-20 12:05:541966 CodecSpecificInfo codec_info;
1967 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 07:00:191968
perkj803d97f2016-11-01 18:45:461969 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Henrik Boström2e540a22023-02-15 13:48:091970 encoded_image.SetSimulcastIndex(0);
asapersson118ef002016-03-31 07:00:191971 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 12:05:541972 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 07:00:191973 }
1974 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531975 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1976 EXPECT_METRIC_EQ(1,
1977 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 07:00:191978}
1979
Henrik Boström2e540a22023-02-15 13:48:091980TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9Svc) {
asapersson5265fed2016-04-18 09:58:471981 EncodedImage encoded_image;
kjellander02b3d272016-04-20 12:05:541982 CodecSpecificInfo codec_info;
1983 codec_info.codecType = kVideoCodecVP9;
1984 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 09:58:471985
perkj803d97f2016-11-01 18:45:461986 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 09:58:471987 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 13:33:421988 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 12:05:541989 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 09:58:471990 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 13:33:421991 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 12:05:541992 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 09:58:471993 }
1994 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:531995 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1996 EXPECT_METRIC_EQ(
1997 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1998 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1999 EXPECT_METRIC_EQ(
2000 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 09:58:472001}
2002
2003TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
Jonas Oreland8ca06132022-03-14 11:52:482004 test::ScopedKeyValueConfig field_trials;
asapersson5265fed2016-04-18 09:58:472005 VideoSendStream::Config config(nullptr);
2006 config.rtp.ssrcs.push_back(kFirstSsrc);
2007 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 11:52:482008 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2009 field_trials));
asapersson5265fed2016-04-18 09:58:472010
asapersson5265fed2016-04-18 09:58:472011 EncodedImage encoded_image;
kjellander02b3d272016-04-20 12:05:542012 CodecSpecificInfo codec_info;
2013 codec_info.codecType = kVideoCodecVP9;
2014 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 09:58:472015
perkj803d97f2016-11-01 18:45:462016 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 09:58:472017 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 12:05:542018 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 09:58:472019 }
2020 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532021 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
2022 EXPECT_METRIC_EQ(1,
2023 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 09:58:472024}
2025
asapersson827cab32016-11-02 16:08:472026TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
2027 EncodedImage encoded_image;
2028 CodecSpecificInfo codec_info;
2029 codec_info.codecType = kVideoCodecH264;
2030
2031 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Henrik Boström2e540a22023-02-15 13:48:092032 encoded_image.SetSimulcastIndex(0);
asapersson827cab32016-11-02 16:08:472033 encoded_image.qp_ = kQpIdx0;
2034 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boström2e540a22023-02-15 13:48:092035 encoded_image.SetSimulcastIndex(1);
Sergio Garcia Murillo43800f92018-06-21 14:16:382036 encoded_image.qp_ = kQpIdx1;
2037 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 16:08:472038 }
2039 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532040 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
2041 EXPECT_METRIC_EQ(
2042 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
2043 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
2044 EXPECT_METRIC_EQ(
2045 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 16:08:472046}
2047
asapersson4ee70462016-10-31 11:05:122048TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 14:54:442049 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
2050 // Configure one stream.
2051 VideoEncoderConfig config;
2052 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2053 VideoStream stream1;
2054 stream1.width = kWidth;
2055 stream1.height = kHeight;
Niels Möller97e04882018-05-25 07:43:262056 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 14:54:442057
2058 const int64_t kMaxEncodedFrameWindowMs = 800;
2059 const int kFps = 20;
2060 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2061 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2062 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2063
2064 // Stream encoded.
asapersson4ee70462016-10-31 11:05:122065 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 14:54:442066 encoded_image._encodedWidth = kWidth;
2067 encoded_image._encodedHeight = kHeight;
2068 for (int i = 0; i < kMinSamples; ++i) {
2069 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:122070 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2071 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 11:05:122072 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 14:54:442073 }
asapersson4ee70462016-10-31 11:05:122074
2075 // Histograms are updated when the statistics_proxy_ is deleted.
2076 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532077 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2078 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2079 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2080 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 11:05:122081}
2082
2083TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 14:54:442084 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
2085 // Configure two streams.
2086 VideoEncoderConfig config;
2087 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2088 VideoStream stream1;
2089 stream1.width = kWidth / 2;
2090 stream1.height = kHeight / 2;
2091 VideoStream stream2;
2092 stream2.width = kWidth;
2093 stream2.height = kHeight;
Niels Möller97e04882018-05-25 07:43:262094 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 14:54:442095
2096 const int64_t kMaxEncodedFrameWindowMs = 800;
2097 const int kFps = 20;
2098 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2099 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2100 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2101
2102 // Two streams encoded.
asapersson4ee70462016-10-31 11:05:122103 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 14:54:442104 for (int i = 0; i < kMinSamples; ++i) {
2105 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:122106 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2107 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 14:54:442108 encoded_image._encodedWidth = kWidth;
2109 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 11:05:122110 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 14:54:442111 encoded_image._encodedWidth = kWidth / 2;
2112 encoded_image._encodedHeight = kHeight / 2;
2113 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2114 }
asapersson4ee70462016-10-31 11:05:122115
2116 // Histograms are updated when the statistics_proxy_ is deleted.
2117 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532118 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2119 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2120 EXPECT_METRIC_EQ(
2121 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2122 0));
asapersson4ee70462016-10-31 11:05:122123 // No resolution disabled.
Ying Wangef3998f2019-12-09 12:06:532124 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2125 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 11:05:122126}
2127
2128TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 14:54:442129 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2130 // Configure two streams.
2131 VideoEncoderConfig config;
2132 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2133 VideoStream stream1;
2134 stream1.width = kWidth / 2;
2135 stream1.height = kHeight / 2;
2136 VideoStream stream2;
2137 stream2.width = kWidth;
2138 stream2.height = kHeight;
Niels Möller97e04882018-05-25 07:43:262139 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 14:54:442140
2141 const int64_t kMaxEncodedFrameWindowMs = 800;
2142 const int kFps = 20;
2143 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2144 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2145 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2146
2147 // One stream encoded.
asapersson4ee70462016-10-31 11:05:122148 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 14:54:442149 encoded_image._encodedWidth = kWidth / 2;
2150 encoded_image._encodedHeight = kHeight / 2;
2151 for (int i = 0; i < kMinSamples; ++i) {
2152 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 08:24:122153 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2154 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 11:05:122155 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 14:54:442156 }
asapersson4ee70462016-10-31 11:05:122157
2158 // Histograms are updated when the statistics_proxy_ is deleted.
2159 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532160 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2161 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2162 EXPECT_METRIC_EQ(
2163 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2164 100));
Åsa Perssonaa329e72017-12-15 14:54:442165 // One resolution disabled.
Ying Wangef3998f2019-12-09 12:06:532166 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2167 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2168 EXPECT_METRIC_EQ(
2169 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2170 1));
asapersson4ee70462016-10-31 11:05:122171}
2172
2173TEST_F(SendStatisticsProxyTest,
2174 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 09:34:322175 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2176 kScalingDisabled);
asapersson4ee70462016-10-31 11:05:122177 EncodedImage encoded_image;
Henrik Boström2e540a22023-02-15 13:48:092178 encoded_image.SetSimulcastIndex(0);
perkj803d97f2016-11-01 18:45:462179 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 14:32:162180 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 11:05:122181
2182 // Histograms are updated when the statistics_proxy_ is deleted.
2183 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532184 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 11:05:122185 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 12:06:532186 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2187 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 11:05:122188}
2189
2190TEST_F(SendStatisticsProxyTest,
2191 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 09:34:322192 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 11:05:122193 EncodedImage encoded_image;
Henrik Boström2e540a22023-02-15 13:48:092194 encoded_image.SetSimulcastIndex(0);
perkj803d97f2016-11-01 18:45:462195 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 14:32:162196 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 11:05:122197
2198 // Histograms are updated when the statistics_proxy_ is deleted.
2199 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532200 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 11:05:122201 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 12:06:532202 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2203 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 11:05:122204 // No resolution downscale.
Ying Wangef3998f2019-12-09 12:06:532205 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2206 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 11:05:122207}
2208
2209TEST_F(SendStatisticsProxyTest,
2210 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2211 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 09:34:322212 VideoAdaptationCounters cpu_counts;
2213 VideoAdaptationCounters quality_counts;
2214 quality_counts.resolution_adaptations = kDownscales;
2215 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 09:36:552216 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2217 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 11:05:122218 EncodedImage encoded_image;
Henrik Boström2e540a22023-02-15 13:48:092219 encoded_image.SetSimulcastIndex(0);
perkj803d97f2016-11-01 18:45:462220 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 14:32:162221 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 11:05:122222 // Histograms are updated when the statistics_proxy_ is deleted.
2223 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532224 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 11:05:122225 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 12:06:532226 EXPECT_METRIC_EQ(
2227 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2228 100));
asapersson4ee70462016-10-31 11:05:122229 // Resolution downscales.
Ying Wangef3998f2019-12-09 12:06:532230 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2231 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2232 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 11:05:122233 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2234 kDownscales));
2235}
2236
2237TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2238 // Initially false.
2239 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 13:14:422240
Åsa Perssonaa329e72017-12-15 14:54:442241 // Configure two streams.
2242 VideoEncoderConfig config;
2243 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 16:06:582244 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 14:54:442245 VideoStream stream1;
2246 stream1.width = kWidth / 2;
2247 stream1.height = kHeight / 2;
2248 VideoStream stream2;
2249 stream2.width = kWidth;
2250 stream2.height = kHeight;
Niels Möller97e04882018-05-25 07:43:262251 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 14:54:442252
Åsa Perssonaa329e72017-12-15 14:54:442253 // One stream encoded.
2254 EncodedImage encoded_image;
2255 encoded_image._encodedWidth = kWidth / 2;
2256 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 14:32:162257
2258 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 09:34:322259 VideoAdaptationCounters cpu_counts;
2260 VideoAdaptationCounters quality_counts;
2261 quality_counts.resolution_adaptations = 1;
2262 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2263 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 09:36:552264 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2265 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 11:05:122266 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2267 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 16:06:582268
2269 // Adapt up.
Evan Shrubsoledff79252020-04-16 09:34:322270 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 09:36:552271 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2272 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 16:06:582273 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2274 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2275
2276 // Bw disabled one layer.
2277 VideoCodec codec;
2278 codec.numberOfSimulcastStreams = 2;
2279 codec.simulcastStream[0].active = true;
2280 codec.simulcastStream[1].active = true;
2281 VideoBitrateAllocation allocation;
2282 // Some positive bitrate only on the second stream.
2283 allocation.SetBitrate(1, 0, 10000);
2284 allocation.set_bw_limited(true);
2285 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2286 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:262287
2288 // Revert for the next test.
2289 allocation.set_bw_limited(false);
2290 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2291 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2292
2293 // Internal encoder scaler reduced resolution.
2294 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2295 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 11:05:122296}
2297
asapersson66d4b372016-12-19 14:50:532298TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2299 // Initially zero.
2300 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2301
2302 const int kBitrate = 100000;
2303 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2304 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2305
2306 statistics_proxy_->OnSetEncoderTargetRate(0);
2307 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2308}
2309
sprang@webrtc.orgccd42842014-01-07 09:54:342310TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:522311 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 17:51:272312 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2313 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:492314 1;
Danil Chapovalovf01c2c92021-05-14 13:39:232315 // From ReportBlockDataObserver.
2316 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
Danil Chapovalovec2670e2023-04-12 11:11:212317 rtcp::ReportBlock report_block;
2318 report_block.SetMediaSsrc(excluded_ssrc);
Danil Chapovalovf01c2c92021-05-14 13:39:232319 ReportBlockData data;
Danil Chapovalovec2670e2023-04-12 11:11:212320 data.SetReportBlock(0, report_block, Timestamp::Zero());
Danil Chapovalovf01c2c92021-05-14 13:39:232321 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:342322
2323 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 16:11:282324 uint32_t total = 0;
2325 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:342326 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:522327 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:342328
2329 // From FrameCountObserver.
2330 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:162331 FrameCounts frame_counts;
2332 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:522333 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:342334
2335 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2336 EXPECT_TRUE(stats.substreams.empty());
2337}
2338
pbos@webrtc.org273a4142014-12-01 15:23:212339TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2340 static const int kEncodedWidth = 123;
2341 static const int kEncodedHeight = 81;
2342 EncodedImage encoded_image;
2343 encoded_image._encodedWidth = kEncodedWidth;
2344 encoded_image._encodedHeight = kEncodedHeight;
Henrik Boström2e540a22023-02-15 13:48:092345 encoded_image.SetSimulcastIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:212346
kjellander02b3d272016-04-20 12:05:542347 CodecSpecificInfo codec_info;
2348 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:212349
kjellander02b3d272016-04-20 12:05:542350 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boström2e540a22023-02-15 13:48:092351 encoded_image.SetSimulcastIndex(1);
kjellander02b3d272016-04-20 12:05:542352 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:212353
2354 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:162355 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2356 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2357 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2358 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:212359
2360 // Forward almost to timeout, this should not have removed stats.
Danil Chapovalov2d162c42023-09-08 09:51:132361 fake_clock_.AdvanceTime(SendStatisticsProxy::kStatsTimeout -
2362 TimeDelta::Millis(1));
pbos@webrtc.org273a4142014-12-01 15:23:212363 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:162364 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2365 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:212366
2367 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2368 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 13:39:232369 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
Danil Chapovalovec2670e2023-04-12 11:11:212370 rtcp::ReportBlock report_block;
2371 report_block.SetMediaSsrc(config_.rtp.ssrcs[0]);
Danil Chapovalovf01c2c92021-05-14 13:39:232372 ReportBlockData data;
Danil Chapovalovec2670e2023-04-12 11:11:212373 data.SetReportBlock(0, report_block, Timestamp::Zero());
Danil Chapovalovf01c2c92021-05-14 13:39:232374 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:212375
2376 // Report stats for second SSRC to make sure it's not outdated along with the
2377 // first SSRC.
kjellander02b3d272016-04-20 12:05:542378 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:212379
2380 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2381 // reported, but substream 1 should.
2382 fake_clock_.AdvanceTimeMilliseconds(1);
2383 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:162384 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2385 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2386 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2387 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:212388}
2389
Peter Boström20f3f942015-05-15 09:33:392390TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2391 static const int kEncodedWidth = 123;
2392 static const int kEncodedHeight = 81;
2393 EncodedImage encoded_image;
2394 encoded_image._encodedWidth = kEncodedWidth;
2395 encoded_image._encodedHeight = kEncodedHeight;
Henrik Boström2e540a22023-02-15 13:48:092396 encoded_image.SetSimulcastIndex(0);
Peter Boström20f3f942015-05-15 09:33:392397
kjellander02b3d272016-04-20 12:05:542398 CodecSpecificInfo codec_info;
2399 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 09:33:392400
kjellander02b3d272016-04-20 12:05:542401 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boström2e540a22023-02-15 13:48:092402 encoded_image.SetSimulcastIndex(1);
kjellander02b3d272016-04-20 12:05:542403 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 09:33:392404
2405 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2406 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2407 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2408 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2409 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2410 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2411}
2412
2413TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 16:11:282414 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 09:33:392415 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2416 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2417 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2418
2419 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2420
2421 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 16:11:282422 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 09:33:392423 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 16:11:282424 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 09:33:392425 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2426 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2427 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2428}
2429
sprang07fb9be2016-02-24 15:55:002430TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2431 RtcpPacketTypeCounterObserver* proxy =
2432 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2433 RtcpPacketTypeCounter counters;
sprang07fb9be2016-02-24 15:55:002434 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2435 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2436
2437 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2438
2439 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2440 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2441 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2442 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2443 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2444
2445 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2446 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2447
2448 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 09:48:502449 VideoEncoderConfig config;
2450 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 07:43:262451 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 15:55:002452
Ying Wangef3998f2019-12-09 12:06:532453 EXPECT_METRIC_EQ(
2454 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2455 EXPECT_METRIC_EQ(
2456 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2457 EXPECT_METRIC_EQ(
2458 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2459 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2460 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 15:55:002461
2462 const int kRate = 60 * 2; // Packets per minute with two streams.
2463
Ying Wangef3998f2019-12-09 12:06:532464 EXPECT_METRIC_EQ(
2465 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2466 1 * kRate));
2467 EXPECT_METRIC_EQ(
2468 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2469 2 * kRate));
2470 EXPECT_METRIC_EQ(
2471 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2472 3 * kRate));
2473 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 13:29:462474 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2475 4 * 100 / 5));
sprang07fb9be2016-02-24 15:55:002476
2477 // New start time but same counter values.
2478 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2479 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2480
2481 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2482
2483 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2484 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2485 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2486 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2487 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2488
2489 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2490 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2491
2492 SetUp(); // Reset stats proxy also causes histograms to be reported.
2493
Ying Wangef3998f2019-12-09 12:06:532494 EXPECT_METRIC_EQ(
2495 1, metrics::NumSamples(
2496 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2497 EXPECT_METRIC_EQ(1,
2498 metrics::NumSamples(
2499 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2500 EXPECT_METRIC_EQ(1,
2501 metrics::NumSamples(
2502 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2503 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 13:29:462504 1, metrics::NumSamples(
sprang07fb9be2016-02-24 15:55:002505 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2506
Ying Wangef3998f2019-12-09 12:06:532507 EXPECT_METRIC_EQ(
2508 1,
2509 metrics::NumEvents(
2510 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2511 EXPECT_METRIC_EQ(
2512 1,
2513 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2514 2 * kRate));
2515 EXPECT_METRIC_EQ(
2516 1,
2517 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2518 3 * kRate));
2519 EXPECT_METRIC_EQ(
2520 1, metrics::NumEvents(
2521 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2522 4 * 100 / 5));
sprang07fb9be2016-02-24 15:55:002523}
2524
Henrik Boströmf45ca372020-03-24 12:30:502525TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2526 StreamDataCountersCallback* proxy =
2527 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2528 StreamDataCounters counters;
2529 proxy->DataCountersUpdated(counters, kFirstSsrc);
2530 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2531
2532 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2533 VideoSendStream::StreamStats::StreamType::kRtx);
2534 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2535 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2536 VideoSendStream::StreamStats::StreamType::kRtx);
2537 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2538}
2539
asaperssona6a699a2016-11-25 11:52:462540TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
Jonas Oreland8ca06132022-03-14 11:52:482541 test::ScopedKeyValueConfig field_trials;
2542 statistics_proxy_.reset(new SendStatisticsProxy(
2543 &fake_clock_, GetTestConfigWithFlexFec(),
2544 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 11:52:462545
2546 StreamDataCountersCallback* proxy =
2547 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2548 StreamDataCounters counters;
2549 proxy->DataCountersUpdated(counters, kFirstSsrc);
2550 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2551
Henrik Boströmf45ca372020-03-24 12:30:502552 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2553 VideoSendStream::StreamStats::StreamType::kFlexfec);
2554 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2555 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2556 VideoSendStream::StreamStats::StreamType::kFlexfec);
2557 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 11:52:462558}
2559
2560TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
Jonas Oreland8ca06132022-03-14 11:52:482561 test::ScopedKeyValueConfig field_trials;
2562 statistics_proxy_.reset(new SendStatisticsProxy(
2563 &fake_clock_, GetTestConfigWithFlexFec(),
2564 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 11:52:462565
2566 StreamDataCountersCallback* proxy =
2567 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 11:52:462568 StreamDataCounters counters;
2569 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 11:52:462570
asapersson93e1e232017-02-06 13:18:352571 const int kMinRequiredPeriodSamples = 8;
2572 const int kPeriodIntervalMs = 2000;
2573 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2574 counters.transmitted.packets += 20;
2575 counters.transmitted.header_bytes += 500;
2576 counters.transmitted.padding_bytes += 1000;
2577 counters.transmitted.payload_bytes += 2000;
2578 counters.retransmitted.packets += 2;
2579 counters.retransmitted.header_bytes += 25;
2580 counters.retransmitted.padding_bytes += 100;
2581 counters.retransmitted.payload_bytes += 250;
2582 counters.fec = counters.retransmitted;
2583 rtx_counters.transmitted = counters.transmitted;
2584 // Advance one interval and update counters.
2585 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2586 proxy->DataCountersUpdated(counters, kFirstSsrc);
2587 proxy->DataCountersUpdated(counters, kSecondSsrc);
2588 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2589 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2590 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2591 }
asaperssona6a699a2016-11-25 11:52:462592
asaperssona6a699a2016-11-25 11:52:462593 statistics_proxy_.reset();
asapersson93e1e232017-02-06 13:18:352594 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 12:06:532595 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2596 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 13:18:352597 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 12:06:532598 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2599 EXPECT_METRIC_EQ(1,
2600 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 13:18:352601 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 12:06:532602 EXPECT_METRIC_EQ(1,
2603 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2604 EXPECT_METRIC_EQ(
2605 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 13:18:352606 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 12:06:532607 EXPECT_METRIC_EQ(
2608 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2609 EXPECT_METRIC_EQ(
2610 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 13:18:352611 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 12:06:532612 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2613 EXPECT_METRIC_EQ(1,
2614 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 13:18:352615 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 12:06:532616 EXPECT_METRIC_EQ(
2617 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2618 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 13:18:352619 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 11:52:462620}
2621
Erik Språng22c2b482016-03-01 08:40:422622TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2623 StreamDataCountersCallback* proxy =
2624 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2625 StreamDataCounters counters;
2626 StreamDataCounters rtx_counters;
Danil Chapovalov0f1a2c52023-05-26 09:30:262627 counters.first_packet_time = fake_clock_.CurrentTime();
Erik Språng22c2b482016-03-01 08:40:422628
asapersson93e1e232017-02-06 13:18:352629 const int kMinRequiredPeriodSamples = 8;
2630 const int kPeriodIntervalMs = 2000;
2631 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2632 counters.transmitted.packets += 20;
2633 counters.transmitted.header_bytes += 500;
2634 counters.transmitted.padding_bytes += 1000;
2635 counters.transmitted.payload_bytes += 2000;
2636 counters.retransmitted.packets += 2;
2637 counters.retransmitted.header_bytes += 25;
2638 counters.retransmitted.padding_bytes += 100;
2639 counters.retransmitted.payload_bytes += 250;
2640 counters.fec = counters.retransmitted;
2641 rtx_counters.transmitted = counters.transmitted;
2642 // Advance one interval and update counters.
2643 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2644 proxy->DataCountersUpdated(counters, kFirstSsrc);
2645 proxy->DataCountersUpdated(counters, kSecondSsrc);
2646 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2647 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2648 }
Erik Språng22c2b482016-03-01 08:40:422649
2650 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 09:48:502651 VideoEncoderConfig config;
2652 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 07:43:262653 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 08:40:422654
asapersson93e1e232017-02-06 13:18:352655 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 12:06:532656 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2657 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 13:18:352658 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 12:06:532659 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2660 EXPECT_METRIC_EQ(1,
2661 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 13:18:352662 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 12:06:532663 EXPECT_METRIC_EQ(1,
2664 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2665 EXPECT_METRIC_EQ(
2666 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 13:18:352667 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 12:06:532668 EXPECT_METRIC_EQ(
2669 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2670 EXPECT_METRIC_EQ(
2671 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 13:18:352672 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 12:06:532673 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2674 EXPECT_METRIC_EQ(1,
2675 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 13:18:352676 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 12:06:532677 EXPECT_METRIC_EQ(
2678 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2679 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 13:18:352680 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 08:40:422681
asapersson93e1e232017-02-06 13:18:352682 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 08:40:422683 // Double counter values, this should result in the same counts as before but
2684 // with new histogram names.
asapersson93e1e232017-02-06 13:18:352685 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2686 counters.transmitted.packets += 20;
2687 counters.transmitted.header_bytes += 500;
2688 counters.transmitted.padding_bytes += 1000;
2689 counters.transmitted.payload_bytes += 2000;
2690 counters.retransmitted.packets += 2;
2691 counters.retransmitted.header_bytes += 25;
2692 counters.retransmitted.padding_bytes += 100;
2693 counters.retransmitted.payload_bytes += 250;
2694 counters.fec = counters.retransmitted;
2695 rtx_counters.transmitted = counters.transmitted;
2696 // Advance one interval and update counters.
2697 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2698 proxy->DataCountersUpdated(counters, kFirstSsrc);
2699 proxy->DataCountersUpdated(counters, kSecondSsrc);
2700 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2701 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2702 }
Erik Språng22c2b482016-03-01 08:40:422703
asapersson93e1e232017-02-06 13:18:352704 // Reset stats proxy also causes histograms to be reported.
2705 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 08:40:422706
asapersson93e1e232017-02-06 13:18:352707 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 12:06:532708 EXPECT_METRIC_EQ(
2709 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2710 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 13:18:352711 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2712 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 12:06:532713 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 13:18:352714 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 12:06:532715 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2716 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 13:18:352717 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 12:06:532718 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2719 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2720 EXPECT_METRIC_EQ(
2721 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2722 12));
asapersson93e1e232017-02-06 13:18:352723 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 12:06:532724 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2725 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2726 EXPECT_METRIC_EQ(
2727 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2728 16));
asapersson93e1e232017-02-06 13:18:352729 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 12:06:532730 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 13:18:352731 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 12:06:532732 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2733 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 13:18:352734 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 12:06:532735 EXPECT_METRIC_EQ(
2736 1, metrics::NumSamples(
2737 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2738 EXPECT_METRIC_EQ(
2739 1, metrics::NumEvents(
2740 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 13:18:352741}
Erik Språng22c2b482016-03-01 08:40:422742
asapersson93e1e232017-02-06 13:18:352743TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2744 StreamDataCountersCallback* proxy =
2745 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2746 StreamDataCounters counters;
2747 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 08:40:422748
asapersson93e1e232017-02-06 13:18:352749 const int kMinRequiredPeriodSamples = 8;
2750 const int kPeriodIntervalMs = 2000;
2751 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2752 counters.transmitted.packets += 20;
2753 counters.transmitted.header_bytes += 500;
2754 counters.transmitted.payload_bytes += 2000;
2755 counters.fec = counters.retransmitted;
2756 // Advance one interval and update counters.
2757 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2758 proxy->DataCountersUpdated(counters, kFirstSsrc);
2759 }
2760
2761 // RTX enabled. No data sent over RTX.
2762 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532763 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2764 EXPECT_METRIC_EQ(1,
2765 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 13:18:352766}
2767
2768TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 11:52:482769 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 13:18:352770 VideoSendStream::Config config(nullptr);
2771 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2772 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 11:52:482773 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2774 field_trials));
asapersson93e1e232017-02-06 13:18:352775
2776 StreamDataCountersCallback* proxy =
2777 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2778 StreamDataCounters counters;
2779
2780 const int kMinRequiredPeriodSamples = 8;
2781 const int kPeriodIntervalMs = 2000;
2782 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2783 counters.transmitted.packets += 20;
2784 counters.transmitted.header_bytes += 500;
2785 counters.transmitted.payload_bytes += 2000;
2786 counters.fec = counters.retransmitted;
2787 // Advance one interval and update counters.
2788 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2789 proxy->DataCountersUpdated(counters, kFirstSsrc);
2790 }
2791
2792 // RTX not enabled.
2793 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532794 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 13:18:352795}
2796
2797TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2798 StreamDataCountersCallback* proxy =
2799 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2800 StreamDataCounters counters;
2801 StreamDataCounters rtx_counters;
2802
2803 const int kMinRequiredPeriodSamples = 8;
2804 const int kPeriodIntervalMs = 2000;
2805 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2806 counters.transmitted.packets += 20;
2807 counters.transmitted.header_bytes += 500;
2808 counters.transmitted.payload_bytes += 2000;
2809 // Advance one interval and update counters.
2810 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2811 proxy->DataCountersUpdated(counters, kFirstSsrc);
2812 }
2813
2814 // FEC enabled. No FEC data sent.
2815 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532816 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2817 EXPECT_METRIC_EQ(1,
2818 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 13:18:352819}
2820
2821TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 11:52:482822 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 13:18:352823 VideoSendStream::Config config(nullptr);
2824 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2825 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 11:52:482826 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2827 field_trials));
asapersson93e1e232017-02-06 13:18:352828
2829 StreamDataCountersCallback* proxy =
2830 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2831 StreamDataCounters counters;
2832
2833 const int kMinRequiredPeriodSamples = 8;
2834 const int kPeriodIntervalMs = 2000;
2835 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2836 counters.transmitted.packets += 20;
2837 counters.transmitted.header_bytes += 500;
2838 counters.transmitted.payload_bytes += 2000;
2839 counters.fec = counters.retransmitted;
2840 // Advance one interval and update counters.
2841 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2842 proxy->DataCountersUpdated(counters, kFirstSsrc);
2843 }
2844
2845 // FEC not enabled.
2846 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532847 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 08:40:422848}
2849
asapersson8d75ac72017-09-15 13:41:152850TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a72018-10-24 09:32:392851 const std::string kName = "encoderName";
Evan Shrubsole09da10e2022-10-14 14:38:312852 statistics_proxy_->OnEncoderImplementationChanged(EncoderImplementation{
2853 .name = kName,
2854 .is_hardware_accelerated = true,
2855 });
Erik Språnge2fd86a72018-10-24 09:32:392856 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
Evan Shrubsole09da10e2022-10-14 14:38:312857 EXPECT_THAT(statistics_proxy_->GetStats().power_efficient_encoder,
2858 ::testing::IsTrue());
asapersson8d75ac72017-09-15 13:41:152859}
2860
Sergey Silkinbb081a62018-09-04 16:34:222861TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2862 static const int kEncodedWidth = 123;
2863 static const int kEncodedHeight = 81;
2864 EncodedImage encoded_image;
2865 encoded_image._encodedWidth = kEncodedWidth;
2866 encoded_image._encodedHeight = kEncodedHeight;
2867 encoded_image.SetSpatialIndex(0);
2868
2869 CodecSpecificInfo codec_info;
2870 codec_info.codecType = kVideoCodecVP9;
2871
2872 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 11:42:562873 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 16:34:222874 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2875 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2876 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2877 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2878
2879 // Top layer updates resolution.
2880 encoded_image._encodedWidth = kEncodedWidth * 2;
2881 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 11:42:562882 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 16:34:222883 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2884 stats = statistics_proxy_->GetStats();
2885 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2886 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2887
2888 // Low layer of next frame doesn't update resolution.
2889 encoded_image._encodedWidth = kEncodedWidth;
2890 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 11:42:562891 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 16:34:222892 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2893 stats = statistics_proxy_->GetStats();
2894 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2895 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2896}
2897
asapersson8d75ac72017-09-15 13:41:152898class ForcedFallbackTest : public SendStatisticsProxyTest {
2899 public:
2900 explicit ForcedFallbackTest(const std::string& field_trials)
2901 : SendStatisticsProxyTest(field_trials) {
2902 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 13:41:152903 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 09:16:472904 encoded_image_._encodedWidth = kWidth;
2905 encoded_image_._encodedHeight = kHeight;
Henrik Boström2e540a22023-02-15 13:48:092906 encoded_image_.SetSimulcastIndex(0);
asapersson8d75ac72017-09-15 13:41:152907 }
2908
2909 ~ForcedFallbackTest() override {}
2910
2911 protected:
2912 void InsertEncodedFrames(int num_frames, int interval_ms) {
Evan Shrubsole09da10e2022-10-14 14:38:312913 statistics_proxy_->OnEncoderImplementationChanged(
2914 {.name = codec_name_, .is_hardware_accelerated = false});
Erik Språnge2fd86a72018-10-24 09:32:392915
asapersson8d75ac72017-09-15 13:41:152916 // First frame is not updating stats, insert initial frame.
2917 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2918 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2919 }
2920 for (int i = 0; i < num_frames; ++i) {
2921 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2922 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2923 }
2924 // Add frame to include last time interval.
2925 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2926 }
2927
2928 EncodedImage encoded_image_;
2929 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a72018-10-24 09:32:392930 std::string codec_name_;
asapersson8d75ac72017-09-15 13:41:152931 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2932 const int kFrameIntervalMs = 1000;
2933 const int kMinFrames = 20; // Min run time 20 sec.
2934};
2935
2936class ForcedFallbackDisabled : public ForcedFallbackTest {
2937 public:
2938 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 13:04:522939 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2940 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 13:41:152941};
2942
2943class ForcedFallbackEnabled : public ForcedFallbackTest {
2944 public:
2945 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 09:16:472946 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2947 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 13:41:152948};
2949
2950TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2951 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2952 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532953 EXPECT_METRIC_EQ(0,
2954 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2955 EXPECT_METRIC_EQ(
2956 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 13:41:152957}
2958
2959TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2960 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 13:04:522961 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 13:41:152962 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532963 EXPECT_METRIC_EQ(1,
2964 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2965 EXPECT_METRIC_EQ(
2966 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2967 EXPECT_METRIC_EQ(
2968 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2969 EXPECT_METRIC_EQ(
2970 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 13:41:152971}
2972
2973TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2974 codec_info_.codecType = kVideoCodecVP9;
2975 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2976 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532977 EXPECT_METRIC_EQ(0,
2978 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2979 EXPECT_METRIC_EQ(
2980 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 13:41:152981}
2982
2983TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2984 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2985 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2986 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532987 EXPECT_METRIC_EQ(0,
2988 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2989 EXPECT_METRIC_EQ(
2990 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 13:41:152991}
2992
2993TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Henrik Boström2e540a22023-02-15 13:48:092994 encoded_image_.SetSimulcastIndex(1);
asapersson8d75ac72017-09-15 13:41:152995 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2996 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:532997 EXPECT_METRIC_EQ(0,
2998 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2999 EXPECT_METRIC_EQ(
3000 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 13:41:153001}
3002
3003TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
3004 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3005 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:533006 EXPECT_METRIC_EQ(0,
3007 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3008 EXPECT_METRIC_EQ(
3009 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 13:41:153010}
3011
Åsa Perssonc3ed6302017-11-16 13:04:523012TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
3013 InsertEncodedFrames(1, kFrameIntervalMs);
3014 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3015}
3016
3017TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
3018 InsertEncodedFrames(1, kFrameIntervalMs);
3019 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3020}
3021
3022TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a72018-10-24 09:32:393023 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 13:04:523024 InsertEncodedFrames(1, kFrameIntervalMs);
3025 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3026}
3027
3028TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
3029 encoded_image_._encodedWidth = kWidth + 1;
3030 InsertEncodedFrames(1, kFrameIntervalMs);
3031 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3032}
3033
3034TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a72018-10-24 09:32:393035 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 13:04:523036 InsertEncodedFrames(1, kFrameIntervalMs);
3037 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3038}
3039
3040TEST_F(ForcedFallbackDisabled,
3041 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
3042 encoded_image_._encodedWidth = kWidth + 1;
3043 statistics_proxy_->OnMinPixelLimitReached();
3044 InsertEncodedFrames(1, kFrameIntervalMs);
3045 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3046}
3047
asapersson8d75ac72017-09-15 13:41:153048TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
3049 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 13:04:523050 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 13:41:153051 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 13:04:523052 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a72018-10-24 09:32:393053 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 13:41:153054 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 13:04:523055 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 13:41:153056
3057 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:533058 EXPECT_METRIC_EQ(1,
3059 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3060 EXPECT_METRIC_EQ(
3061 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3062 EXPECT_METRIC_EQ(
3063 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3064 EXPECT_METRIC_EQ(
3065 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 13:41:153066}
3067
3068TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
3069 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
3070 const int kMaxFrameDiffMs = 2000;
3071
3072 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
3073 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 13:04:523074 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a72018-10-24 09:32:393075 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 13:41:153076 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 13:04:523077 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a72018-10-24 09:32:393078 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 13:41:153079 InsertEncodedFrames(20, 1000);
3080 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
3081 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 13:04:523082 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a72018-10-24 09:32:393083 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 13:41:153084 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 13:04:523085 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a72018-10-24 09:32:393086 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 13:41:153087 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 13:04:523088 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 13:41:153089
3090 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:533091 EXPECT_METRIC_EQ(1,
3092 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3093 EXPECT_METRIC_EQ(
3094 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3095 EXPECT_METRIC_EQ(
3096 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3097 EXPECT_METRIC_EQ(
3098 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 13:41:153099}
3100
Åsa Persson45bbc8a2017-11-13 09:16:473101TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
3102 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a72018-10-24 09:32:393103 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 13:41:153104 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3105
Åsa Perssonc3ed6302017-11-16 13:04:523106 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 13:41:153107 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:533108 EXPECT_METRIC_EQ(0,
3109 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3110 EXPECT_METRIC_EQ(
3111 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 13:41:153112}
3113
Åsa Persson45bbc8a2017-11-13 09:16:473114TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
3115 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a72018-10-24 09:32:393116 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 13:41:153117 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3118
Åsa Perssonc3ed6302017-11-16 13:04:523119 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 13:41:153120 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 12:06:533121 EXPECT_METRIC_EQ(1,
3122 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3123 EXPECT_METRIC_EQ(
3124 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 13:41:153125}
3126
sprang@webrtc.orgccd42842014-01-07 09:54:343127} // namespace webrtc