blob: d24b3c80a6e52998c960865ea99fb0bf80e89fa1 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
Steve Antonbd631a02019-03-28 10:51:27 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 10:51:27 -070019#include "absl/algorithm/container.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020020#include "api/units/timestamp.h"
Evan Shrubsolece0a11d2020-04-16 11:36:55 +020021#include "api/video/video_adaptation_reason.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020022#include "api/video/video_bitrate_allocation.h"
23#include "api/video/video_codec_type.h"
24#include "api/video_codecs/video_codec.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020025#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "system_wrappers/include/metrics.h"
Evan Shrubsole09da10e2022-10-14 14:38:31 +000027#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 12:52:48 +010029#include "test/scoped_key_value_config.h"
Jonas Oreland6c2dae22022-09-29 10:28:24 +020030#include "video/config/video_encoder_config.h"
Evan Shrubsole09da10e2022-10-14 14:38:31 +000031#include "video/video_stream_encoder_observer.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000032
33namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070034namespace {
35const uint32_t kFirstSsrc = 17;
36const uint32_t kSecondSsrc = 42;
37const uint32_t kFirstRtxSsrc = 18;
38const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080039const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080040const int kFpsPeriodicIntervalMs = 2000;
41const int kWidth = 640;
42const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070043const int kQpIdx0 = 21;
44const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010045const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080046const CodecSpecificInfo kDefaultCodecInfo = []() {
47 CodecSpecificInfo codec_info;
48 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080049 return codec_info;
50}();
Evan Shrubsoledff79252020-04-16 11:34:32 +020051
52const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
53 true);
54const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
55 true,
56 false);
57const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
58 false,
59 true);
60const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
asapersson5265fed2016-04-18 02:58:47 -070061} // namespace
sprang07fb9be2016-02-24 07:55:00 -080062
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000063class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000064 public:
asapersson8d75ac72017-09-15 06:41:15 -070065 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
66 explicit SendStatisticsProxyTest(const std::string& field_trials)
67 : override_field_trials_(field_trials),
68 fake_clock_(1234),
Åsa Persson90719572021-04-08 19:05:30 +020069 config_(GetTestConfig()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000070 virtual ~SendStatisticsProxyTest() {}
71
72 protected:
73 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070074 metrics::Reset();
Jonas Oreland8ca06132022-03-14 12:52:48 +010075 statistics_proxy_.reset(
76 new SendStatisticsProxy(&fake_clock_, GetTestConfig(),
77 VideoEncoderConfig::ContentType::kRealtimeVideo,
78 override_field_trials_));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000079 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010080 for (const auto& ssrc : config_.rtp.ssrcs) {
81 expected_.substreams[ssrc].type =
82 VideoSendStream::StreamStats::StreamType::kMedia;
83 }
84 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
85 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
86 expected_.substreams[ssrc].type =
87 VideoSendStream::StreamStats::StreamType::kRtx;
88 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
89 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000090 }
91
92 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070093 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080094 config.rtp.ssrcs.push_back(kFirstSsrc);
95 config.rtp.ssrcs.push_back(kSecondSsrc);
96 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
97 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070098 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000099 return config;
100 }
101
asaperssona6a699a2016-11-25 03:52:46 -0800102 VideoSendStream::Config GetTestConfigWithFlexFec() {
103 VideoSendStream::Config config(nullptr);
104 config.rtp.ssrcs.push_back(kFirstSsrc);
105 config.rtp.ssrcs.push_back(kSecondSsrc);
106 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
107 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -0800108 config.rtp.flexfec.payload_type = 50;
109 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +0100110 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -0800111 return config;
112 }
113
114 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
115 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
116 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
117 stats.substreams.find(ssrc);
118 EXPECT_NE(it, stats.substreams.end());
119 return it->second;
120 }
121
asapersson66d4b372016-12-19 06:50:53 -0800122 void UpdateDataCounters(uint32_t ssrc) {
123 StreamDataCountersCallback* proxy =
124 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
125 StreamDataCounters counters;
126 proxy->DataCountersUpdated(counters, ssrc);
127 }
128
sprang@webrtc.org09315702014-02-07 12:06:29 +0000129 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
Di Wu668dbf62021-02-27 00:29:15 -0800130 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000131 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
132 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000133 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000134 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000135
136 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000137 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000138 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000139 it != one.substreams.end(); ++it) {
140 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
141 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000143 const VideoSendStream::StreamStats& a = it->second;
144 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000145
Henrik Boströmf45ca372020-03-24 13:30:50 +0100146 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000147 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
148 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000149 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000150 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
151 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000152
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000153 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
154 b.rtp_stats.transmitted.payload_bytes);
155 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
156 b.rtp_stats.transmitted.header_bytes);
157 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
158 b.rtp_stats.transmitted.padding_bytes);
159 EXPECT_EQ(a.rtp_stats.transmitted.packets,
160 b.rtp_stats.transmitted.packets);
161 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
162 b.rtp_stats.retransmitted.packets);
163 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000164
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200165 EXPECT_EQ(a.report_block_data.has_value(),
166 b.report_block_data.has_value());
167 if (a.report_block_data.has_value()) {
168 const RTCPReportBlock& a_rtcp_stats =
169 a.report_block_data->report_block();
170 const RTCPReportBlock& b_rtcp_stats =
171 b.report_block_data->report_block();
172 EXPECT_EQ(a_rtcp_stats.fraction_lost, b_rtcp_stats.fraction_lost);
173 EXPECT_EQ(a_rtcp_stats.packets_lost, b_rtcp_stats.packets_lost);
174 EXPECT_EQ(a_rtcp_stats.extended_highest_sequence_number,
175 b_rtcp_stats.extended_highest_sequence_number);
176 EXPECT_EQ(a_rtcp_stats.jitter, b_rtcp_stats.jitter);
177 }
sprang@webrtc.org09315702014-02-07 12:06:29 +0000178 }
179 }
180
Jonas Oreland8ca06132022-03-14 12:52:48 +0100181 test::ScopedKeyValueConfig override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000182 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800183 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000185 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000186};
187
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200188TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
189 ReportBlockDataObserver* callback = statistics_proxy_.get();
190 for (uint32_t ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000191 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200192 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200193 RTCPReportBlock report_block;
194 report_block.source_ssrc = ssrc;
195 report_block.packets_lost = offset;
196 report_block.extended_highest_sequence_number = offset + 1;
197 report_block.fraction_lost = offset + 2;
198 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200199 ReportBlockData data;
200 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200201 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200202
203 callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000204 }
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200205 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000206 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200207 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200208 RTCPReportBlock report_block;
209 report_block.source_ssrc = ssrc;
210 report_block.packets_lost = offset;
211 report_block.extended_highest_sequence_number = offset + 1;
212 report_block.fraction_lost = offset + 2;
213 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200214 ReportBlockData data;
215 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200216 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200217
218 callback->OnReportBlockDataUpdated(data);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000219 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000220 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000221 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000222}
223
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000224TEST_F(SendStatisticsProxyTest, Suspended) {
225 // Verify that the value is false by default.
226 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
227
228 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200229 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000230 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
231
232 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200233 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000234 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
235}
236
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000237TEST_F(SendStatisticsProxyTest, FrameCounts) {
238 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700239 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000240 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000241 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
242 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000243 FrameCounts frame_counts;
244 frame_counts.key_frames = offset;
245 frame_counts.delta_frames = offset + 1;
246 stats.frame_counts = frame_counts;
247 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000248 }
asapersson35151f32016-05-02 23:44:01 -0700249 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000250 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000251 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
252 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000253 FrameCounts frame_counts;
254 frame_counts.key_frames = offset;
255 frame_counts.delta_frames = offset + 1;
256 stats.frame_counts = frame_counts;
257 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000258 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000259
260 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000261 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000262}
263
264TEST_F(SendStatisticsProxyTest, DataCounters) {
265 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700266 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000267 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
268 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000269 size_t offset = ssrc * sizeof(StreamDataCounters);
270 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000271 counters.transmitted.payload_bytes = offset;
272 counters.transmitted.header_bytes = offset + 1;
273 counters.fec.packets = offset_uint32 + 2;
274 counters.transmitted.padding_bytes = offset + 3;
275 counters.retransmitted.packets = offset_uint32 + 4;
276 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000277 callback->DataCountersUpdated(counters, ssrc);
278 }
asapersson35151f32016-05-02 23:44:01 -0700279 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
281 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000282 size_t offset = ssrc * sizeof(StreamDataCounters);
283 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000284 counters.transmitted.payload_bytes = offset;
285 counters.transmitted.header_bytes = offset + 1;
286 counters.fec.packets = offset_uint32 + 2;
287 counters.transmitted.padding_bytes = offset + 3;
288 counters.retransmitted.packets = offset_uint32 + 4;
289 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000290 callback->DataCountersUpdated(counters, ssrc);
291 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000292
293 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000294 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000295}
296
297TEST_F(SendStatisticsProxyTest, Bitrate) {
298 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700299 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000300 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200301 uint32_t total = ssrc;
302 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000303 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700304 expected_.substreams[ssrc].total_bitrate_bps = total;
305 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000306 }
asapersson35151f32016-05-02 23:44:01 -0700307 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000308 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200309 uint32_t total = ssrc;
310 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000311 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700312 expected_.substreams[ssrc].total_bitrate_bps = total;
313 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000314 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000315
316 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000317 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000318}
319
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000320TEST_F(SendStatisticsProxyTest, SendSideDelay) {
321 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700322 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000323 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
324 // stream.
325 int avg_delay_ms = ssrc;
326 int max_delay_ms = ssrc + 1;
Henrik Boströmd8199212022-10-26 16:50:53 +0200327 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000328 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
329 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
330 }
asapersson35151f32016-05-02 23:44:01 -0700331 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000332 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
333 // stream.
334 int avg_delay_ms = ssrc;
335 int max_delay_ms = ssrc + 1;
Henrik Boströmd8199212022-10-26 16:50:53 +0200336 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000337 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
338 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
339 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000340 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000341 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000342}
343
Peter Boströme4499152016-02-05 11:13:28 +0100344TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800345 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200346 int encode_usage_percent = 80;
347 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
348 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800349
350 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
351 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200352 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800353}
354
Henrik Boström5684af52019-04-02 15:05:21 +0200355TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
356 const int kEncodeUsagePercent = 0; // Don't care for this test.
357 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
358 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
359 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
360 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
361 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
362}
363
sakal43536c32016-10-24 01:46:43 -0700364TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
365 EncodedImage encoded_image;
366 CodecSpecificInfo codec_info;
367 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
368 for (uint32_t i = 1; i <= 3; ++i) {
369 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
370 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
371 }
372}
373
sakal87da4042016-10-31 06:53:47 -0700374TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
375 EncodedImage encoded_image;
376 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200377 auto ssrc = config_.rtp.ssrcs[0];
378 EXPECT_EQ(absl::nullopt,
379 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700380 encoded_image.qp_ = 3;
381 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200382 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700383 encoded_image.qp_ = 127;
384 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200385 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700386}
387
388TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
389 EncodedImage encoded_image;
390 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200391 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700392 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200393 EXPECT_EQ(absl::nullopt,
394 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700395 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200396 EXPECT_EQ(absl::nullopt,
397 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700398}
399
Henrik Boström23aff9b2019-05-20 15:15:38 +0200400TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
401 const uint32_t kTargetBytesPerSecond = 100000;
402 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
403 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
404
405 EncodedImage encoded_image;
406 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
407 // On the first frame we don't know the frame rate yet, calculation yields
408 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
Artem Titovab30d722021-07-27 16:22:11 +0200409 // increment by a full `kTargetBytesPerSecond`.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200410 EXPECT_EQ(kTargetBytesPerSecond,
411 statistics_proxy_->GetStats().total_encoded_bytes_target);
412}
413
414TEST_F(SendStatisticsProxyTest,
415 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
416 const uint32_t kTargetBytesPerSecond = 100000;
417 const int kInterframeDelayMs = 100;
418
419 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
Artem Titovab30d722021-07-27 16:22:11 +0200420 // `fake_clock_` for testing, but the RateTracker relies on a global clock.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200421 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
422 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
423 // this test can stop relying on rtc::ScopedFakeClock.
424 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100425 fake_global_clock.SetTime(
426 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200427
428 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
429 EncodedImage encoded_image;
430
431 // First frame
432 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
433 uint64_t first_total_encoded_bytes_target =
434 statistics_proxy_->GetStats().total_encoded_bytes_target;
435 // Second frame
436 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100437 fake_global_clock.SetTime(
438 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200439 encoded_image.SetTimestamp(encoded_image.Timestamp() +
440 90 * kInterframeDelayMs);
441 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
442
443 auto stats = statistics_proxy_->GetStats();
444 // By the time the second frame arrives, one frame has previously arrived
Artem Titovab30d722021-07-27 16:22:11 +0200445 // during a `kInterframeDelayMs` interval. The estimated encode frame rate at
Henrik Boström23aff9b2019-05-20 15:15:38 +0200446 // the second frame's arrival should be 10 FPS.
447 uint64_t delta_encoded_bytes_target =
448 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
449 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
450}
451
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200452TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
453 const int kInterframeDelayMs = 100;
Åsa Persson603e6e32021-08-10 08:56:36 +0200454 const auto ssrc = config_.rtp.ssrcs[0];
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200455 rtc::ScopedFakeClock fake_global_clock;
456 fake_global_clock.SetTime(
457 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
458
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200459 // First frame
Åsa Persson603e6e32021-08-10 08:56:36 +0200460 EncodedImage encoded_image;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200461 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200462 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
463 fake_global_clock.SetTime(
464 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson603e6e32021-08-10 08:56:36 +0200465 // Second frame
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200466 encoded_image.SetTimestamp(encoded_image.Timestamp() +
467 90 * kInterframeDelayMs);
468 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson603e6e32021-08-10 08:56:36 +0200469 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
470 fake_global_clock.SetTime(
471 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200472
473 auto stats = statistics_proxy_->GetStats();
474 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
475}
476
Åsa Persson8d564722021-08-03 14:43:01 +0200477TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp8Simulcast) {
478 const int kInterframeDelayMs = 100;
479 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200480 fake_global_clock.SetTime(
481 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200482 EncodedImage encoded_image;
483 CodecSpecificInfo codec_info;
484 codec_info.codecType = kVideoCodecVP8;
485
486 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200487 encoded_image.SetTimestamp(encoded_image.Timestamp() +
488 90 * kInterframeDelayMs);
489 encoded_image.SetSpatialIndex(0);
490 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
491 encoded_image.SetSpatialIndex(1);
492 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200493 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
494 fake_global_clock.SetTime(
495 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200496 }
497
498 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
499 EXPECT_EQ(2u, stats.substreams.size());
500 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
501 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson603e6e32021-08-10 08:56:36 +0200502
503 // Stop encoding second stream, expect framerate to be zero.
504 for (int i = 0; i < 10; ++i) {
505 encoded_image.SetTimestamp(encoded_image.Timestamp() +
506 90 * kInterframeDelayMs);
507 encoded_image.SetSpatialIndex(0);
508 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
509 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
510 fake_global_clock.SetTime(
511 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
512 }
513
514 stats = statistics_proxy_->GetStats();
515 EXPECT_EQ(2u, stats.substreams.size());
516 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
517 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 0);
518
519 // Start encoding second stream.
520 for (int i = 0; i < 10; ++i) {
521 encoded_image.SetTimestamp(encoded_image.Timestamp() +
522 90 * kInterframeDelayMs);
523 encoded_image.SetSpatialIndex(0);
524 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
525 encoded_image.SetSpatialIndex(1);
526 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
527 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
528 fake_global_clock.SetTime(
529 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
530 }
531
532 stats = statistics_proxy_->GetStats();
533 EXPECT_EQ(2u, stats.substreams.size());
534 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
535 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson8d564722021-08-03 14:43:01 +0200536}
537
538TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp9Svc) {
539 const int kInterframeDelayMs = 100;
540 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200541 fake_global_clock.SetTime(
542 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200543 EncodedImage encoded_image;
544 CodecSpecificInfo codec_info;
545 codec_info.codecType = kVideoCodecVP9;
546
547 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200548 encoded_image.SetTimestamp(encoded_image.Timestamp() +
549 90 * kInterframeDelayMs);
550 encoded_image.SetSpatialIndex(0);
551 codec_info.end_of_picture = false;
552 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
553 encoded_image.SetSpatialIndex(1);
554 codec_info.end_of_picture = true;
555 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200556 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
557 fake_global_clock.SetTime(
558 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200559 }
560
561 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
562 EXPECT_EQ(1u, stats.substreams.size());
563 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
564}
565
asapersson09f05612017-05-15 23:40:18 -0700566TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200567 VideoAdaptationCounters cpu_counts;
568 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700569 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700570 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200571 cpu_counts.fps_adaptations = 1;
572 cpu_counts.resolution_adaptations = 0;
573 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200574 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
575 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700576 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700577 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200578 cpu_counts.fps_adaptations = 0;
579 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200580 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
581 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700582 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700583 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200584 cpu_counts.fps_adaptations = 1;
585 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
586 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200587 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
588 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700589 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700590 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200591 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
592 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200593 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
594 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700595 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
596 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
597}
598
599TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200600 VideoAdaptationCounters cpu_counts;
601 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700602 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
603 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200604 quality_counts.fps_adaptations = 1;
605 quality_counts.resolution_adaptations = 0;
606 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200607 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
608 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700609 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
610 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200611 quality_counts.fps_adaptations = 0;
612 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200613 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
614 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700615 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
616 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200617 quality_counts.fps_adaptations = 1;
618 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
619 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200620 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
621 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700622 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
623 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200624 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
625 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200626 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
627 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700628 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
629 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
630}
631
632TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200633 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
634 VideoAdaptationCounters cpu_counts;
635 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700636 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
637
Evan Shrubsoledff79252020-04-16 11:34:32 +0200638 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200639 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
640 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700641 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700642 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
643 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
644
Evan Shrubsoledff79252020-04-16 11:34:32 +0200645 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200646 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
647 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700648 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
649 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700650 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700651 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700652}
653
asapersson09f05612017-05-15 23:40:18 -0700654TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200655 VideoAdaptationCounters cpu_counts;
656 VideoAdaptationCounters quality_counts;
657 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700658 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
659
Evan Shrubsoledff79252020-04-16 11:34:32 +0200660 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200661 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
662 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700663 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
664 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700665 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
666
Evan Shrubsoledff79252020-04-16 11:34:32 +0200667 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200668 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
669 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700670 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700671 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700672 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
673 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700674}
675
Evan Shrubsoledff79252020-04-16 11:34:32 +0200676TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
677 VideoAdaptationCounters cpu_counts;
678 VideoAdaptationCounters quality_counts;
679 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
680 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
681 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
682
683 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200684 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
685 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200686 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200687 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
688 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200689 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200690 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
691 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200692 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200693 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
694 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200695 // We have 1 fps and resolution reduction for both cpu and quality
696 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
697 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
698 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
699 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
700 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
701 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
702
703 // Disable quality scaling. Expect quality scaling not limited.
704 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
705 kScalingDisabled);
706 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
707 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
708 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
709 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
710 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
711 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
712
713 // Disable framerate scaling.
714 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
715 kFramerateScalingDisabled);
716 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
717 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
718 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
719 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
720 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
721 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
722
723 // Disable resolution scaling.
724 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
725 kResolutionScalingDisabled);
726 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
727 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
728 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
729 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
730 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
731 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
732
733 // Enable all
734 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
735 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
736 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
737 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
738 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
739 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
740 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
741}
742
asapersson09f05612017-05-15 23:40:18 -0700743TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700744 // First RTP packet sent.
745 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700746 // Min runtime has passed.
747 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
748 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100749 EXPECT_METRIC_EQ(
750 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
751 EXPECT_METRIC_EQ(
752 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700753}
754
755TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700756 // First RTP packet sent.
757 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700758 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200759 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700760 // Min runtime has not passed.
761 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
762 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100763 EXPECT_METRIC_EQ(
764 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
765 EXPECT_METRIC_EQ(
766 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700767}
768
asapersson09f05612017-05-15 23:40:18 -0700769TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700770 // First RTP packet sent.
771 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700772 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200773 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700774 // Min runtime has passed.
775 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
776 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100777 EXPECT_METRIC_EQ(
778 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
779 EXPECT_METRIC_EQ(
780 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
781 EXPECT_METRIC_EQ(
782 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
783 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700784 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
785}
786
787TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700788 // First RTP packet sent.
789 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700790 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200791 VideoAdaptationCounters cpu_counts;
792 VideoAdaptationCounters quality_counts;
793 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700794 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200795 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
796 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700797 fake_clock_.AdvanceTimeMilliseconds(10000);
798 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100799 EXPECT_METRIC_EQ(
800 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
801 EXPECT_METRIC_EQ(
802 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700803}
804
Åsa Persson875841d2018-01-08 08:49:53 +0100805TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
806 // First RTP packet sent.
807 UpdateDataCounters(kFirstSsrc);
808 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200809 VideoAdaptationCounters cpu_counts;
810 VideoAdaptationCounters quality_counts;
811 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100812 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200813 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
814 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100815 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
816 fake_clock_.AdvanceTimeMilliseconds(10000);
817 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100818 EXPECT_METRIC_EQ(
819 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
820 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100821 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
822}
823
824TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
825 // First RTP packet sent.
826 UpdateDataCounters(kFirstSsrc);
827 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200828 VideoAdaptationCounters cpu_counts;
829 VideoAdaptationCounters quality_counts;
830 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100831 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200832 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200833 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
834 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100835 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200836 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200837 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
838 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100839 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200840 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200841 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
842 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100843 fake_clock_.AdvanceTimeMilliseconds(10000);
844 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100845 EXPECT_METRIC_EQ(
846 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
847 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100848 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
849}
850
851TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
852 // First RTP packet sent.
853 UpdateDataCounters(kFirstSsrc);
854 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200855 VideoAdaptationCounters cpu_counts;
856 VideoAdaptationCounters quality_counts;
857 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100858 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200859 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
860 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100861 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
862 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
863 fake_clock_.AdvanceTimeMilliseconds(10000);
864 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100865 EXPECT_METRIC_EQ(
866 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
867 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100868 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
869}
870
871TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
872 // First RTP packet sent.
873 UpdateDataCounters(kFirstSsrc);
874 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200875 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
876 VideoAdaptationCounters cpu_counts;
877 VideoAdaptationCounters quality_counts;
878 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100879 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200880 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200881 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
882 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100883 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200884 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200885 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
886 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100887 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200888 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200889 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
890 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200891 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200892 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
893 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200894 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200895 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
896 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200897 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200898 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
899 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200900 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200901 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
902 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200903 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200904 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
905 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100906
907 fake_clock_.AdvanceTimeMilliseconds(10000);
908 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100909 EXPECT_METRIC_EQ(
910 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
911 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100912 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
913}
914
asapersson6eca98b2017-04-04 23:40:50 -0700915TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700916 // First RTP packet sent.
917 UpdateDataCounters(kFirstSsrc);
918
asapersson09f05612017-05-15 23:40:18 -0700919 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200920 VideoAdaptationCounters cpu_counts;
921 VideoAdaptationCounters quality_counts;
922 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
923 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700924 fake_clock_.AdvanceTimeMilliseconds(10000);
925
asapersson09f05612017-05-15 23:40:18 -0700926 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700927 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200928 quality_counts.fps_adaptations = 0;
929 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
930 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700931 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200932 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
933 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700934 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200935 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
936 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700937 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200938 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
939 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700940
asapersson09f05612017-05-15 23:40:18 -0700941 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200942 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
943 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700944 fake_clock_.AdvanceTimeMilliseconds(30000);
945
asapersson09f05612017-05-15 23:40:18 -0700946 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700947 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200948 quality_counts.resolution_adaptations = 0;
949 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
950 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200951 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
952 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700953 fake_clock_.AdvanceTimeMilliseconds(10000);
954
asapersson09f05612017-05-15 23:40:18 -0700955 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200956 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
957 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700958 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200959 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
960 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700961 fake_clock_.AdvanceTimeMilliseconds(20000);
962
asapersson0944a802017-04-07 00:57:58 -0700963 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700964 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100965 EXPECT_METRIC_EQ(
966 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
967 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700968 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
969}
970
asapersson0944a802017-04-07 00:57:58 -0700971TEST_F(SendStatisticsProxyTest,
972 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
973 // First RTP packet sent.
974 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700975
asapersson0944a802017-04-07 00:57:58 -0700976 // Suspend and resume video.
977 statistics_proxy_->OnSuspendChange(true);
978 fake_clock_.AdvanceTimeMilliseconds(5000);
979 statistics_proxy_->OnSuspendChange(false);
980
981 // Min runtime has passed but scaling not enabled.
982 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
983 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100984 EXPECT_METRIC_EQ(
985 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
986 EXPECT_METRIC_EQ(
987 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700988}
989
990TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
991 // First RTP packet sent.
992 UpdateDataCounters(kFirstSsrc);
993
asapersson09f05612017-05-15 23:40:18 -0700994 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200995 VideoAdaptationCounters cpu_counts;
996 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700997 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200998 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700999 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001000 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1001 cpu_counts, quality_counts);
1002 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1003 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001004
1005 // Suspend and resume video.
1006 statistics_proxy_->OnSuspendChange(true);
1007 fake_clock_.AdvanceTimeMilliseconds(30000);
1008 statistics_proxy_->OnSuspendChange(false);
1009
1010 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001011 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1012 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001013 fake_clock_.AdvanceTimeMilliseconds(10000);
1014
1015 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
1016 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001017 EXPECT_METRIC_EQ(
1018 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1019 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -07001020 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1021}
1022
1023TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
1024 // First RTP packet sent.
1025 UpdateDataCounters(kFirstSsrc);
1026
1027 // Video not suspended.
1028 statistics_proxy_->OnSuspendChange(false);
1029 fake_clock_.AdvanceTimeMilliseconds(30000);
1030
asapersson09f05612017-05-15 23:40:18 -07001031 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001032 VideoAdaptationCounters cpu_counts;
1033 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -07001034 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001035 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001036 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001037 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1038 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001039
1040 // Video not suspended, stats time already started.
1041 statistics_proxy_->OnSuspendChange(false);
1042 fake_clock_.AdvanceTimeMilliseconds(10000);
1043
asapersson09f05612017-05-15 23:40:18 -07001044 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001045 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1046 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -07001047 fake_clock_.AdvanceTimeMilliseconds(30000);
1048
1049 // Suspend and resume video, stats time not started when scaling not enabled.
1050 statistics_proxy_->OnSuspendChange(true);
1051 fake_clock_.AdvanceTimeMilliseconds(30000);
1052 statistics_proxy_->OnSuspendChange(false);
1053 fake_clock_.AdvanceTimeMilliseconds(30000);
1054
asapersson09f05612017-05-15 23:40:18 -07001055 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -07001056 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001057 cpu_counts.fps_adaptations = 0;
1058 cpu_counts.resolution_adaptations = 0;
1059 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001060 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001061 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1062 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001063
1064 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
1065 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001066 EXPECT_METRIC_EQ(
1067 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1068 EXPECT_METRIC_EQ(
1069 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -07001070}
1071
1072TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
1073 // First RTP packet sent.
1074 UpdateDataCounters(kFirstSsrc);
1075
1076 // Video suspended.
1077 statistics_proxy_->OnSuspendChange(true);
1078
asapersson09f05612017-05-15 23:40:18 -07001079 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001080 VideoAdaptationCounters cpu_counts;
1081 VideoAdaptationCounters quality_counts;
1082 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001083 fake_clock_.AdvanceTimeMilliseconds(10000);
1084
1085 // Resume video, stats time started.
1086 // Adapt changes: 1, elapsed time: 10 sec.
1087 statistics_proxy_->OnSuspendChange(false);
1088 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001089 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1090 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001091
1092 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1093 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001094 EXPECT_METRIC_EQ(
1095 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1096 EXPECT_METRIC_EQ(
1097 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001098}
1099
1100TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001101 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001102 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001103 VideoAdaptationCounters cpu_counts;
1104 VideoAdaptationCounters quality_counts;
1105 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001106 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001107 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001108
asapersson0944a802017-04-07 00:57:58 -07001109 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001110 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001111 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1112 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001113 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001114
asapersson0944a802017-04-07 00:57:58 -07001115 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001116 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001117 EXPECT_METRIC_EQ(
1118 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1119 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001120 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1121}
1122
1123TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001124 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001125 VideoAdaptationCounters cpu_counts;
1126 VideoAdaptationCounters quality_counts;
1127 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001128 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001129 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1130 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001131
1132 // Send first packet, scaling disabled.
1133 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001134 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001135 fake_clock_.AdvanceTimeMilliseconds(60000);
1136
asapersson09f05612017-05-15 23:40:18 -07001137 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001138 cpu_counts.resolution_adaptations = 0;
1139 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1140 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001141 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001142 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001143
asapersson0944a802017-04-07 00:57:58 -07001144 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001145 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001146 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1147 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001148
asapersson0944a802017-04-07 00:57:58 -07001149 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001150 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001151 EXPECT_METRIC_EQ(
1152 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1153 EXPECT_METRIC_EQ(
1154 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001155}
1156
1157TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001158 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001159 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001160 VideoAdaptationCounters cpu_counts;
1161 VideoAdaptationCounters quality_counts;
1162 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1163 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001164
asapersson0944a802017-04-07 00:57:58 -07001165 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001166 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1167 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001168 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001169 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1170 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001171 fake_clock_.AdvanceTimeMilliseconds(9000);
1172
1173 // Switch content type, real-time stats should be updated.
1174 VideoEncoderConfig config;
1175 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001176 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001177 EXPECT_METRIC_EQ(
1178 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1179 EXPECT_METRIC_EQ(
1180 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1181 EXPECT_METRIC_EQ(
1182 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001183
asapersson0944a802017-04-07 00:57:58 -07001184 // First RTP packet sent, scaling enabled.
1185 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001186 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1187 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001188
asapersson0944a802017-04-07 00:57:58 -07001189 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001190 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1191 cpu_counts, quality_counts);
1192 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1193 cpu_counts, quality_counts);
1194 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1195 cpu_counts, quality_counts);
1196 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1197 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001198 fake_clock_.AdvanceTimeMilliseconds(120000);
1199
1200 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001201 EXPECT_METRIC_EQ(1,
1202 metrics::NumSamples(
1203 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1204 EXPECT_METRIC_EQ(
1205 1, metrics::NumEvents(
1206 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1207 EXPECT_METRIC_EQ(
1208 0, metrics::NumSamples(
1209 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001210}
1211
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001212TEST_F(SendStatisticsProxyTest,
1213 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001214 VideoAdaptationCounters cpu_counts;
1215 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001216
Evan Shrubsoledff79252020-04-16 11:34:32 +02001217 cpu_counts.resolution_adaptations = 1;
1218 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001219 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1220 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001221
1222 EXPECT_EQ(QualityLimitationReason::kCpu,
1223 statistics_proxy_->GetStats().quality_limitation_reason);
1224}
1225
1226TEST_F(SendStatisticsProxyTest,
1227 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001228 VideoAdaptationCounters cpu_counts;
1229 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001230
Evan Shrubsoledff79252020-04-16 11:34:32 +02001231 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001232
Evan Shrubsoledff79252020-04-16 11:34:32 +02001233 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001234 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1235 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001236
1237 EXPECT_EQ(QualityLimitationReason::kCpu,
1238 statistics_proxy_->GetStats().quality_limitation_reason);
1239}
1240
1241TEST_F(SendStatisticsProxyTest,
1242 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001243 VideoAdaptationCounters cpu_counts;
1244 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001245
Evan Shrubsoledff79252020-04-16 11:34:32 +02001246 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001247
Evan Shrubsoledff79252020-04-16 11:34:32 +02001248 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001249 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1250 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001251
1252 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1253 statistics_proxy_->GetStats().quality_limitation_reason);
1254}
1255
1256TEST_F(SendStatisticsProxyTest,
1257 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001258 VideoAdaptationCounters cpu_counts;
1259 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001260
Evan Shrubsoledff79252020-04-16 11:34:32 +02001261 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001262
Evan Shrubsoledff79252020-04-16 11:34:32 +02001263 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001264 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1265 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001266
1267 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1268 statistics_proxy_->GetStats().quality_limitation_reason);
1269}
1270
1271TEST_F(SendStatisticsProxyTest,
1272 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001273 VideoAdaptationCounters cpu_counts;
1274 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001275
Evan Shrubsoledff79252020-04-16 11:34:32 +02001276 cpu_counts.resolution_adaptations = 1;
1277 quality_counts.resolution_adaptations = 1;
1278 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001279
1280 // Even if the last adaptation reason is kCpu, if the counters indicate being
1281 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001282 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1283 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001284
1285 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1286 statistics_proxy_->GetStats().quality_limitation_reason);
1287}
1288
1289TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001290 VideoAdaptationCounters cpu_counts;
1291 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001292
1293 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1294 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001295 cpu_counts.resolution_adaptations = 1;
1296 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001297 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1298 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001299 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001300 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001301 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1302 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001303
1304 EXPECT_EQ(QualityLimitationReason::kNone,
1305 statistics_proxy_->GetStats().quality_limitation_reason);
1306}
1307
1308TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001309 VideoAdaptationCounters cpu_counts;
1310 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001311
Evan Shrubsoledff79252020-04-16 11:34:32 +02001312 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001313 // Not limited for 3000 ms
1314 fake_clock_.AdvanceTimeMilliseconds(3000);
1315 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001316 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001317 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1318 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001319 fake_clock_.AdvanceTimeMilliseconds(2000);
1320 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001321 cpu_counts.resolution_adaptations = 0;
1322 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001323 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1324 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001325 fake_clock_.AdvanceTimeMilliseconds(1000);
1326 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001327 cpu_counts.resolution_adaptations = 1;
1328 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001329 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1330 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001331 fake_clock_.AdvanceTimeMilliseconds(2000);
1332
1333 auto quality_limitation_durations_ms =
1334 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1335
1336 EXPECT_EQ(3000,
1337 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1338 EXPECT_EQ(4000,
1339 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1340 EXPECT_EQ(
1341 1000,
1342 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1343 EXPECT_EQ(0,
1344 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1345}
1346
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001347TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1348 EXPECT_EQ(
1349 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1350}
1351
1352TEST_F(SendStatisticsProxyTest,
1353 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1354 VideoCodec codec;
1355 VideoBitrateAllocation allocation;
1356 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1357 EXPECT_EQ(
1358 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1359}
1360
1361TEST_F(SendStatisticsProxyTest,
1362 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1363 VideoCodec codec;
1364 codec.simulcastStream[0].active = true;
1365 codec.simulcastStream[1].active = true;
1366 codec.simulcastStream[2].active = true;
1367 VideoBitrateAllocation allocation;
1368 allocation.SetBitrate(0, 0, 100);
1369 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1370 EXPECT_EQ(
1371 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1372}
1373
1374TEST_F(SendStatisticsProxyTest,
1375 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1376 VideoCodec codec;
1377 codec.simulcastStream[0].active = true;
1378 codec.simulcastStream[1].active = true;
1379 codec.simulcastStream[2].active = true;
1380 VideoBitrateAllocation allocation;
1381 allocation.SetBitrate(0, 0, 100);
1382 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1383 allocation.SetBitrate(1, 0, 100);
1384 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1385 EXPECT_EQ(
1386 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1387}
1388
1389TEST_F(SendStatisticsProxyTest,
1390 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1391 VideoCodec codec;
1392 codec.simulcastStream[0].active = true;
1393 VideoBitrateAllocation allocation;
1394 allocation.SetBitrate(0, 0, 100);
1395 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1396 // Layer 0 got more bandwidth, but still only one layer on
1397 allocation.SetBitrate(0, 0, 200);
1398 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1399 EXPECT_EQ(
1400 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1401}
1402
1403TEST_F(SendStatisticsProxyTest,
1404 QualityLimitationResolutionChangesWithTogglingLayers) {
1405 VideoCodec codec;
1406 codec.simulcastStream[0].active = true;
1407 codec.simulcastStream[1].active = true;
1408 codec.simulcastStream[2].active = true;
1409 VideoBitrateAllocation allocation;
1410 allocation.SetBitrate(0, 0, 100);
1411 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1412 EXPECT_EQ(
1413 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1414 allocation.SetBitrate(1, 0, 300);
1415 allocation.SetBitrate(2, 0, 500);
1416 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1417 EXPECT_EQ(
1418 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1419 // Layer 2 off
1420 allocation.SetBitrate(2, 0, 0);
1421 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1422 EXPECT_EQ(
1423 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1424 // Layer 2 back on
1425 allocation.SetBitrate(2, 0, 500);
1426 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1427 EXPECT_EQ(
1428 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1429 allocation.SetBitrate(0, 0, 0);
1430 allocation.SetBitrate(1, 0, 0);
1431 allocation.SetBitrate(2, 0, 0);
1432 // All layers off
1433 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1434 EXPECT_EQ(
1435 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1436}
1437
1438TEST_F(SendStatisticsProxyTest,
1439 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1440 VideoCodec codec;
1441 // 3 layers
1442 codec.simulcastStream[0].active = true;
1443 codec.simulcastStream[1].active = true;
1444 codec.simulcastStream[2].active = true;
1445 VideoBitrateAllocation allocation;
1446 allocation.SetBitrate(0, 0, 500);
1447 allocation.SetBitrate(1, 0, 500);
1448 allocation.SetBitrate(2, 0, 500);
1449 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1450 EXPECT_EQ(
1451 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1452
1453 // Down to one layer now, triggered by a config change
1454 codec.numberOfSimulcastStreams = 1;
1455 codec.simulcastStream[1].active = false;
1456 codec.simulcastStream[2].active = false;
1457 allocation.SetBitrate(0, 0, 100);
1458 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1459 EXPECT_EQ(
1460 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1461
1462 // Up to 3 layers again.
1463 codec.numberOfSimulcastStreams = 3;
1464 codec.simulcastStream[1].active = true;
1465 codec.simulcastStream[2].active = true;
1466 allocation.SetBitrate(0, 0, 500);
1467 allocation.SetBitrate(1, 0, 500);
1468 allocation.SetBitrate(2, 0, 500);
1469 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1470 EXPECT_EQ(
1471 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1472}
1473
1474TEST_F(SendStatisticsProxyTest,
1475 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1476 VideoCodec codec;
1477 codec.simulcastStream[0].active = true;
1478 codec.spatialLayers[0].active = true;
1479 codec.spatialLayers[1].active = true;
1480 codec.spatialLayers[2].active = true;
1481 VideoBitrateAllocation allocation;
1482 allocation.SetBitrate(0, 0, 500);
1483 allocation.SetBitrate(1, 0, 500);
1484 allocation.SetBitrate(2, 0, 500);
1485 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1486 EXPECT_EQ(
1487 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1488
1489 // Down to one layer now, triggered by a config change
1490 codec.spatialLayers[1].active = false;
1491 codec.spatialLayers[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.spatialLayers[1].active = true;
1499 codec.spatialLayers[2].active = true;
1500 allocation.SetBitrate(0, 0, 500);
1501 allocation.SetBitrate(1, 0, 500);
1502 allocation.SetBitrate(2, 0, 500);
1503 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1504 EXPECT_EQ(
1505 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1506}
1507
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001508TEST_F(SendStatisticsProxyTest,
1509 QualityLimitationReasonsAreCorrectForContentType) {
1510 // Realtime case.
1511 // Configure two streams.
1512 VideoEncoderConfig config;
1513 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1514 config.number_of_streams = 2;
1515 VideoStream stream1;
1516 stream1.width = kWidth / 2;
1517 stream1.height = kHeight / 2;
1518 VideoStream stream2;
1519 stream2.width = kWidth;
1520 stream2.height = kHeight;
1521 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1522 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1523 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1524 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1525 QualityLimitationReason::kNone);
1526 // Bw disabled one layer.
1527 VideoCodec codec;
1528 codec.numberOfSimulcastStreams = 2;
1529 codec.simulcastStream[0].active = true;
1530 codec.simulcastStream[1].active = true;
1531 VideoBitrateAllocation allocation;
1532 // Some positive bitrate only on the first stream.
1533 allocation.SetBitrate(0, 0, 10000);
1534 allocation.SetBitrate(1, 0, 0);
1535 allocation.set_bw_limited(true);
1536 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1537 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1538 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1539 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1540 QualityLimitationReason::kBandwidth);
1541 // Bw enabled all layers.
1542 allocation.SetBitrate(1, 0, 10000);
1543 allocation.set_bw_limited(false);
1544 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1545 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1546 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1547 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1548 QualityLimitationReason::kNone);
1549
1550 // Screencast case
1551 // Configure two streams.
1552 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1553 config.number_of_streams = 2;
1554 stream1.width = kWidth;
1555 stream1.height = kHeight;
1556 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1557 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1558 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1559 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1560 QualityLimitationReason::kNone);
1561 // Bw disabled one layer.
1562 // Some positive bitrate only on the second stream.
1563 allocation.SetBitrate(0, 0, 10000);
1564 allocation.SetBitrate(1, 0, 0);
1565 allocation.set_bw_limited(true);
1566 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1567 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1568 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1569 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1570 QualityLimitationReason::kBandwidth);
1571 // Bw enabled all layers.
1572 allocation.SetBitrate(1, 0, 10000);
1573 allocation.set_bw_limited(false);
1574 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1575 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1576 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1577 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1578 QualityLimitationReason::kNone);
1579}
1580
asapersson59bac1a2016-01-07 23:36:00 -08001581TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001582 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001583 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1584
Pera48ddb72016-09-29 11:48:50 +02001585 // No switch, stats should not be updated.
1586 VideoEncoderConfig config;
1587 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001588 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001589 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001590
1591 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001592 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001593 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001594 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001595}
1596
asapersson320e45a2016-11-29 01:40:35 -08001597TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1598 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1599 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001600
asapersson320e45a2016-11-29 01:40:35 -08001601 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001602 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1603 EXPECT_METRIC_EQ(
1604 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1605 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1606 EXPECT_METRIC_EQ(
1607 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001608}
1609
1610TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001611 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001612 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001613 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1614 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1615 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001616 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001617
1618 // Not enough samples, stats should not be updated.
1619 for (int i = 0; i < kMinSamples - 1; ++i) {
1620 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001621 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001622 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1623 }
Åsa Persson0122e842017-10-16 12:19:23 +02001624 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001625 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1626 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001627
1628 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001629 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001630 for (int i = 0; i < kMinSamples; ++i) {
1631 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001632 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001633 encoded_image._encodedWidth = kWidth;
1634 encoded_image._encodedHeight = kHeight;
1635 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1636 encoded_image._encodedWidth = kWidth / 2;
1637 encoded_image._encodedHeight = kHeight / 2;
1638 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1639 }
1640
asapersson320e45a2016-11-29 01:40:35 -08001641 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001642 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1643 EXPECT_METRIC_EQ(
1644 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1645 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1646 EXPECT_METRIC_EQ(
1647 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001648}
1649
1650TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1651 const int kFps = 20;
1652 const int kMinPeriodicSamples = 6;
1653 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1654 for (int i = 0; i <= frames; ++i) {
1655 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1656 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1657 }
1658 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001659 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1660 EXPECT_METRIC_EQ(
1661 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001662}
1663
1664TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1665 EncodedImage encoded_image;
1666 const int kFps = 20;
1667 const int kMinPeriodicSamples = 6;
1668 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001669 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001670 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001671 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001672 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1673 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001674 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1675 }
1676 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001677 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1678 EXPECT_METRIC_EQ(
1679 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001680}
1681
1682TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1683 const int kFps = 20;
1684 const int kSuspendTimeMs = 10000;
1685 const int kMinPeriodicSamples = 6;
1686 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1687 for (int i = 0; i < frames; ++i) {
1688 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1689 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1690 }
1691 // Suspend.
1692 statistics_proxy_->OnSuspendChange(true);
1693 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1694
1695 for (int i = 0; i < frames; ++i) {
1696 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1697 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1698 }
1699 // Suspended time interval should not affect the framerate.
1700 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001701 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1702 EXPECT_METRIC_EQ(
1703 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001704}
1705
1706TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1707 EncodedImage encoded_image;
1708 const int kFps = 20;
1709 const int kSuspendTimeMs = 10000;
1710 const int kMinPeriodicSamples = 6;
1711 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001712 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001713 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001714 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001715 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1716 }
1717 // Suspend.
1718 statistics_proxy_->OnSuspendChange(true);
1719 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1720
Åsa Persson0122e842017-10-16 12:19:23 +02001721 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001722 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001723 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001724 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1725 }
1726 // Suspended time interval should not affect the framerate.
1727 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001728 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1729 EXPECT_METRIC_EQ(
1730 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001731}
1732
asaperssonf4e44af2017-04-19 02:01:06 -07001733TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001734 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1735 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001736
1737 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1738 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1739
1740 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001741 EXPECT_METRIC_EQ(
1742 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001743}
1744
1745TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001746 VideoAdaptationCounters cpu_counts;
1747 VideoAdaptationCounters quality_counts;
1748 cpu_counts.resolution_adaptations = 0;
1749 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001750
perkj803d97f2016-11-01 11:45:46 -07001751 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1752 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1753
Evan Shrubsoledff79252020-04-16 11:34:32 +02001754 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001755 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1756 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001757
1758 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1759 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1760
1761 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001762 EXPECT_METRIC_EQ(
1763 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1764 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001765 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1766}
1767
asapersson4374a092016-07-27 00:39:09 -07001768TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1769 const int64_t kTimeSec = 3;
1770 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1771 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001772 EXPECT_METRIC_EQ(
1773 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1774 EXPECT_METRIC_EQ(
1775 1,
1776 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001777}
1778
1779TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1780 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1781 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001782 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001783}
1784
asapersson66d4b372016-12-19 06:50:53 -08001785TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1786 // First RTP packet sent.
1787 UpdateDataCounters(kFirstSsrc);
1788
1789 // Min runtime has passed.
1790 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1791 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001792 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1793 EXPECT_METRIC_EQ(1,
1794 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001795}
1796
1797TEST_F(SendStatisticsProxyTest,
1798 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1799 // First RTP packet sent.
1800 UpdateDataCounters(kFirstSsrc);
1801
1802 // Min runtime has not passed.
1803 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1804 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001805 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1806 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001807}
1808
1809TEST_F(SendStatisticsProxyTest,
1810 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1811 // First RTP packet not sent.
1812 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1813 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001814 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001815}
1816
1817TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1818 // First RTP packet sent and min runtime passed.
1819 UpdateDataCounters(kFirstSsrc);
1820
1821 // No change. Video: 10000 ms, paused: 0 ms (0%).
1822 statistics_proxy_->OnSetEncoderTargetRate(50000);
1823 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1824 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1825
1826 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001827 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1828 EXPECT_METRIC_EQ(1,
1829 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1830 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1831 EXPECT_METRIC_EQ(1,
1832 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001833}
1834
1835TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1836 // First RTP packet sent and min runtime passed.
1837 UpdateDataCounters(kFirstSsrc);
1838
1839 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1840 statistics_proxy_->OnSetEncoderTargetRate(50000);
1841 fake_clock_.AdvanceTimeMilliseconds(7000);
1842 statistics_proxy_->OnSetEncoderTargetRate(0);
1843 fake_clock_.AdvanceTimeMilliseconds(3000);
1844 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1845
1846 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001847 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1848 EXPECT_METRIC_EQ(1,
1849 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1850 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1851 EXPECT_METRIC_EQ(1,
1852 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001853}
1854
1855TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1856 // First RTP packet sent.
1857 UpdateDataCounters(kFirstSsrc);
1858
1859 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1860 statistics_proxy_->OnSetEncoderTargetRate(0);
1861 fake_clock_.AdvanceTimeMilliseconds(1000);
1862 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1863 fake_clock_.AdvanceTimeMilliseconds(7000);
1864 statistics_proxy_->OnSetEncoderTargetRate(60000);
1865 fake_clock_.AdvanceTimeMilliseconds(3000);
1866 statistics_proxy_->OnSetEncoderTargetRate(0);
1867 fake_clock_.AdvanceTimeMilliseconds(250);
1868 statistics_proxy_->OnSetEncoderTargetRate(0);
1869 fake_clock_.AdvanceTimeMilliseconds(750);
1870 statistics_proxy_->OnSetEncoderTargetRate(60000);
1871 fake_clock_.AdvanceTimeMilliseconds(5000);
1872 statistics_proxy_->OnSetEncoderTargetRate(50000);
1873 fake_clock_.AdvanceTimeMilliseconds(4000);
1874 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1875
1876 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001877 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1878 EXPECT_METRIC_EQ(1,
1879 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1880 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1881 EXPECT_METRIC_EQ(1,
1882 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001883}
1884
1885TEST_F(SendStatisticsProxyTest,
1886 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1887 // First RTP packet sent.
1888 UpdateDataCounters(kFirstSsrc);
1889 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1890
1891 // Min runtime has not passed.
1892 statistics_proxy_->OnSetEncoderTargetRate(50000);
1893 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1894 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1895
1896 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001897 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001898}
1899
asapersson118ef002016-03-31 00:00:19 -07001900TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001901 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001902 CodecSpecificInfo codec_info;
1903 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001904
perkj803d97f2016-11-01 11:45:46 -07001905 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001906 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001907 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001908 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001909 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001910 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001911 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001912 }
1913 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001914 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1915 EXPECT_METRIC_EQ(
1916 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1917 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1918 EXPECT_METRIC_EQ(
1919 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001920}
1921
1922TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01001923 test::ScopedKeyValueConfig field_trials;
asapersson118ef002016-03-31 00:00:19 -07001924 VideoSendStream::Config config(nullptr);
1925 config.rtp.ssrcs.push_back(kFirstSsrc);
1926 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01001927 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1928 field_trials));
asapersson118ef002016-03-31 00:00:19 -07001929
asapersson118ef002016-03-31 00:00:19 -07001930 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001931 CodecSpecificInfo codec_info;
1932 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001933
perkj803d97f2016-11-01 11:45:46 -07001934 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001935 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001936 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001937 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001938 }
1939 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001940 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1941 EXPECT_METRIC_EQ(1,
1942 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001943}
1944
asapersson5265fed2016-04-18 02:58:47 -07001945TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001946 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001947 CodecSpecificInfo codec_info;
1948 codec_info.codecType = kVideoCodecVP9;
1949 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001950
perkj803d97f2016-11-01 11:45:46 -07001951 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001952 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001953 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001954 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001955 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001956 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001957 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001958 }
1959 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001960 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1961 EXPECT_METRIC_EQ(
1962 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1963 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1964 EXPECT_METRIC_EQ(
1965 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001966}
1967
1968TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01001969 test::ScopedKeyValueConfig field_trials;
asapersson5265fed2016-04-18 02:58:47 -07001970 VideoSendStream::Config config(nullptr);
1971 config.rtp.ssrcs.push_back(kFirstSsrc);
1972 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01001973 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1974 field_trials));
asapersson5265fed2016-04-18 02:58:47 -07001975
asapersson5265fed2016-04-18 02:58:47 -07001976 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001977 CodecSpecificInfo codec_info;
1978 codec_info.codecType = kVideoCodecVP9;
1979 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001980
perkj803d97f2016-11-01 11:45:46 -07001981 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001982 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001983 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001984 }
1985 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001986 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1987 EXPECT_METRIC_EQ(1,
1988 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001989}
1990
asapersson827cab32016-11-02 09:08:47 -07001991TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1992 EncodedImage encoded_image;
1993 CodecSpecificInfo codec_info;
1994 codec_info.codecType = kVideoCodecH264;
1995
1996 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001997 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001998 encoded_image.qp_ = kQpIdx0;
1999 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002000 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02002001 encoded_image.qp_ = kQpIdx1;
2002 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07002003 }
2004 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002005 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
2006 EXPECT_METRIC_EQ(
2007 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
2008 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
2009 EXPECT_METRIC_EQ(
2010 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07002011}
2012
asapersson4ee70462016-10-31 04:05:12 -07002013TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002014 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
2015 // Configure one stream.
2016 VideoEncoderConfig config;
2017 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2018 VideoStream stream1;
2019 stream1.width = kWidth;
2020 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002021 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002022
2023 const int64_t kMaxEncodedFrameWindowMs = 800;
2024 const int kFps = 20;
2025 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2026 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2027 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2028
2029 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002030 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002031 encoded_image._encodedWidth = kWidth;
2032 encoded_image._encodedHeight = kHeight;
2033 for (int i = 0; i < kMinSamples; ++i) {
2034 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002035 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2036 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002037 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002038 }
asapersson4ee70462016-10-31 04:05:12 -07002039
2040 // Histograms are updated when the statistics_proxy_ is deleted.
2041 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002042 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2043 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2044 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2045 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002046}
2047
2048TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002049 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
2050 // Configure two streams.
2051 VideoEncoderConfig config;
2052 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2053 VideoStream stream1;
2054 stream1.width = kWidth / 2;
2055 stream1.height = kHeight / 2;
2056 VideoStream stream2;
2057 stream2.width = kWidth;
2058 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002059 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002060
2061 const int64_t kMaxEncodedFrameWindowMs = 800;
2062 const int kFps = 20;
2063 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2064 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2065 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2066
2067 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07002068 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002069 for (int i = 0; i < kMinSamples; ++i) {
2070 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002071 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2072 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002073 encoded_image._encodedWidth = kWidth;
2074 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07002075 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002076 encoded_image._encodedWidth = kWidth / 2;
2077 encoded_image._encodedHeight = kHeight / 2;
2078 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2079 }
asapersson4ee70462016-10-31 04:05:12 -07002080
2081 // Histograms are updated when the statistics_proxy_ is deleted.
2082 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002083 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2084 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2085 EXPECT_METRIC_EQ(
2086 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2087 0));
asapersson4ee70462016-10-31 04:05:12 -07002088 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002089 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2090 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002091}
2092
2093TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002094 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2095 // Configure two streams.
2096 VideoEncoderConfig config;
2097 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2098 VideoStream stream1;
2099 stream1.width = kWidth / 2;
2100 stream1.height = kHeight / 2;
2101 VideoStream stream2;
2102 stream2.width = kWidth;
2103 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002104 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002105
2106 const int64_t kMaxEncodedFrameWindowMs = 800;
2107 const int kFps = 20;
2108 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2109 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2110 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2111
2112 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002113 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002114 encoded_image._encodedWidth = kWidth / 2;
2115 encoded_image._encodedHeight = kHeight / 2;
2116 for (int i = 0; i < kMinSamples; ++i) {
2117 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002118 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2119 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002120 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002121 }
asapersson4ee70462016-10-31 04:05:12 -07002122
2123 // Histograms are updated when the statistics_proxy_ is deleted.
2124 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002125 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2126 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2127 EXPECT_METRIC_EQ(
2128 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2129 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002130 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002131 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2132 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2133 EXPECT_METRIC_EQ(
2134 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2135 1));
asapersson4ee70462016-10-31 04:05:12 -07002136}
2137
2138TEST_F(SendStatisticsProxyTest,
2139 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002140 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2141 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002142 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002143 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002144 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002145 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002146
2147 // Histograms are updated when the statistics_proxy_ is deleted.
2148 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002149 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002150 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002151 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2152 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002153}
2154
2155TEST_F(SendStatisticsProxyTest,
2156 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002157 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002158 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002159 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002160 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002161 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002162
2163 // Histograms are updated when the statistics_proxy_ is deleted.
2164 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002165 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002166 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002167 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2168 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002169 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002170 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2171 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002172}
2173
2174TEST_F(SendStatisticsProxyTest,
2175 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2176 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002177 VideoAdaptationCounters cpu_counts;
2178 VideoAdaptationCounters quality_counts;
2179 quality_counts.resolution_adaptations = kDownscales;
2180 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002181 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2182 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002183 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002184 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002185 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002186 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002187 // Histograms are updated when the statistics_proxy_ is deleted.
2188 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002189 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002190 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002191 EXPECT_METRIC_EQ(
2192 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2193 100));
asapersson4ee70462016-10-31 04:05:12 -07002194 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002195 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2196 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2197 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002198 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2199 kDownscales));
2200}
2201
2202TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2203 // Initially false.
2204 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002205
Åsa Perssonaa329e72017-12-15 15:54:44 +01002206 // Configure two streams.
2207 VideoEncoderConfig config;
2208 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002209 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002210 VideoStream stream1;
2211 stream1.width = kWidth / 2;
2212 stream1.height = kHeight / 2;
2213 VideoStream stream2;
2214 stream2.width = kWidth;
2215 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002216 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002217
Åsa Perssonaa329e72017-12-15 15:54:44 +01002218 // One stream encoded.
2219 EncodedImage encoded_image;
2220 encoded_image._encodedWidth = kWidth / 2;
2221 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002222
2223 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002224 VideoAdaptationCounters cpu_counts;
2225 VideoAdaptationCounters quality_counts;
2226 quality_counts.resolution_adaptations = 1;
2227 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2228 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002229 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2230 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002231 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2232 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002233
2234 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002235 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002236 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2237 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002238 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2239 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2240
2241 // Bw disabled one layer.
2242 VideoCodec codec;
2243 codec.numberOfSimulcastStreams = 2;
2244 codec.simulcastStream[0].active = true;
2245 codec.simulcastStream[1].active = true;
2246 VideoBitrateAllocation allocation;
2247 // Some positive bitrate only on the second stream.
2248 allocation.SetBitrate(1, 0, 10000);
2249 allocation.set_bw_limited(true);
2250 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2251 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002252
2253 // Revert for the next test.
2254 allocation.set_bw_limited(false);
2255 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2256 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2257
2258 // Internal encoder scaler reduced resolution.
2259 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2260 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002261}
2262
asapersson66d4b372016-12-19 06:50:53 -08002263TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2264 // Initially zero.
2265 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2266
2267 const int kBitrate = 100000;
2268 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2269 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2270
2271 statistics_proxy_->OnSetEncoderTargetRate(0);
2272 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2273}
2274
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002275TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002276 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002277 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2278 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002279 1;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002280 // From ReportBlockDataObserver.
2281 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2282 RTCPReportBlock report_block;
2283 report_block.source_ssrc = excluded_ssrc;
2284 ReportBlockData data;
2285 data.SetReportBlock(report_block, 0);
2286 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002287
2288 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002289 uint32_t total = 0;
2290 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002291 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002292 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002293
2294 // From FrameCountObserver.
2295 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002296 FrameCounts frame_counts;
2297 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002298 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002299
2300 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2301 EXPECT_TRUE(stats.substreams.empty());
2302}
2303
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002304TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2305 static const int kEncodedWidth = 123;
2306 static const int kEncodedHeight = 81;
2307 EncodedImage encoded_image;
2308 encoded_image._encodedWidth = kEncodedWidth;
2309 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002310 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002311
kjellander02b3d272016-04-20 05:05:54 -07002312 CodecSpecificInfo codec_info;
2313 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002314
kjellander02b3d272016-04-20 05:05:54 -07002315 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002316 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002317 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002318
2319 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002320 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2321 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2322 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2323 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002324
2325 // Forward almost to timeout, this should not have removed stats.
2326 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2327 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002328 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2329 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002330
2331 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2332 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002333 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2334 RTCPReportBlock report_block;
2335 report_block.source_ssrc = config_.rtp.ssrcs[0];
2336 ReportBlockData data;
2337 data.SetReportBlock(report_block, 0);
2338 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002339
2340 // Report stats for second SSRC to make sure it's not outdated along with the
2341 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002342 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002343
2344 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2345 // reported, but substream 1 should.
2346 fake_clock_.AdvanceTimeMilliseconds(1);
2347 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002348 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2349 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2350 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2351 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002352}
2353
Peter Boström20f3f942015-05-15 11:33:39 +02002354TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2355 static const int kEncodedWidth = 123;
2356 static const int kEncodedHeight = 81;
2357 EncodedImage encoded_image;
2358 encoded_image._encodedWidth = kEncodedWidth;
2359 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002360 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002361
kjellander02b3d272016-04-20 05:05:54 -07002362 CodecSpecificInfo codec_info;
2363 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002364
kjellander02b3d272016-04-20 05:05:54 -07002365 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002366 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002367 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002368
2369 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2370 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2371 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2372 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2373 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2374 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2375}
2376
2377TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002378 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002379 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2380 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2381 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2382
2383 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2384
2385 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002386 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002387 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002388 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002389 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2390 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2391 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2392}
2393
sprang07fb9be2016-02-24 07:55:00 -08002394TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2395 RtcpPacketTypeCounterObserver* proxy =
2396 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2397 RtcpPacketTypeCounter counters;
sprang07fb9be2016-02-24 07:55:00 -08002398 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2399 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2400
2401 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2402
2403 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2404 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2405 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2406 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2407 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2408
2409 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2410 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2411
2412 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002413 VideoEncoderConfig config;
2414 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002415 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002416
Ying Wangef3998f2019-12-09 13:06:53 +01002417 EXPECT_METRIC_EQ(
2418 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2419 EXPECT_METRIC_EQ(
2420 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2421 EXPECT_METRIC_EQ(
2422 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2423 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2424 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002425
2426 const int kRate = 60 * 2; // Packets per minute with two streams.
2427
Ying Wangef3998f2019-12-09 13:06:53 +01002428 EXPECT_METRIC_EQ(
2429 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2430 1 * kRate));
2431 EXPECT_METRIC_EQ(
2432 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2433 2 * kRate));
2434 EXPECT_METRIC_EQ(
2435 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2436 3 * kRate));
2437 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002438 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2439 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002440
2441 // New start time but same counter values.
2442 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2443 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2444
2445 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2446
2447 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2448 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2449 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2450 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2451 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2452
2453 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2454 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2455
2456 SetUp(); // Reset stats proxy also causes histograms to be reported.
2457
Ying Wangef3998f2019-12-09 13:06:53 +01002458 EXPECT_METRIC_EQ(
2459 1, metrics::NumSamples(
2460 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2461 EXPECT_METRIC_EQ(1,
2462 metrics::NumSamples(
2463 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2464 EXPECT_METRIC_EQ(1,
2465 metrics::NumSamples(
2466 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2467 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002468 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002469 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2470
Ying Wangef3998f2019-12-09 13:06:53 +01002471 EXPECT_METRIC_EQ(
2472 1,
2473 metrics::NumEvents(
2474 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2475 EXPECT_METRIC_EQ(
2476 1,
2477 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2478 2 * kRate));
2479 EXPECT_METRIC_EQ(
2480 1,
2481 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2482 3 * kRate));
2483 EXPECT_METRIC_EQ(
2484 1, metrics::NumEvents(
2485 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2486 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002487}
2488
Henrik Boströmf45ca372020-03-24 13:30:50 +01002489TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2490 StreamDataCountersCallback* proxy =
2491 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2492 StreamDataCounters counters;
2493 proxy->DataCountersUpdated(counters, kFirstSsrc);
2494 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2495
2496 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2497 VideoSendStream::StreamStats::StreamType::kRtx);
2498 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2499 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2500 VideoSendStream::StreamStats::StreamType::kRtx);
2501 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2502}
2503
asaperssona6a699a2016-11-25 03:52:46 -08002504TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002505 test::ScopedKeyValueConfig field_trials;
2506 statistics_proxy_.reset(new SendStatisticsProxy(
2507 &fake_clock_, GetTestConfigWithFlexFec(),
2508 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 03:52:46 -08002509
2510 StreamDataCountersCallback* proxy =
2511 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2512 StreamDataCounters counters;
2513 proxy->DataCountersUpdated(counters, kFirstSsrc);
2514 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2515
Henrik Boströmf45ca372020-03-24 13:30:50 +01002516 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2517 VideoSendStream::StreamStats::StreamType::kFlexfec);
2518 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2519 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2520 VideoSendStream::StreamStats::StreamType::kFlexfec);
2521 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002522}
2523
2524TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002525 test::ScopedKeyValueConfig field_trials;
2526 statistics_proxy_.reset(new SendStatisticsProxy(
2527 &fake_clock_, GetTestConfigWithFlexFec(),
2528 VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
asaperssona6a699a2016-11-25 03:52:46 -08002529
2530 StreamDataCountersCallback* proxy =
2531 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002532 StreamDataCounters counters;
2533 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002534
asapersson93e1e232017-02-06 05:18:35 -08002535 const int kMinRequiredPeriodSamples = 8;
2536 const int kPeriodIntervalMs = 2000;
2537 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2538 counters.transmitted.packets += 20;
2539 counters.transmitted.header_bytes += 500;
2540 counters.transmitted.padding_bytes += 1000;
2541 counters.transmitted.payload_bytes += 2000;
2542 counters.retransmitted.packets += 2;
2543 counters.retransmitted.header_bytes += 25;
2544 counters.retransmitted.padding_bytes += 100;
2545 counters.retransmitted.payload_bytes += 250;
2546 counters.fec = counters.retransmitted;
2547 rtx_counters.transmitted = counters.transmitted;
2548 // Advance one interval and update counters.
2549 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2550 proxy->DataCountersUpdated(counters, kFirstSsrc);
2551 proxy->DataCountersUpdated(counters, kSecondSsrc);
2552 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2553 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2554 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2555 }
asaperssona6a699a2016-11-25 03:52:46 -08002556
asaperssona6a699a2016-11-25 03:52:46 -08002557 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002558 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002559 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2560 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002561 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002562 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2563 EXPECT_METRIC_EQ(1,
2564 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002565 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002566 EXPECT_METRIC_EQ(1,
2567 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2568 EXPECT_METRIC_EQ(
2569 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002570 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002571 EXPECT_METRIC_EQ(
2572 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2573 EXPECT_METRIC_EQ(
2574 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002575 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002576 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2577 EXPECT_METRIC_EQ(1,
2578 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002579 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002580 EXPECT_METRIC_EQ(
2581 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2582 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002583 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002584}
2585
Erik Språng22c2b482016-03-01 09:40:42 +01002586TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2587 StreamDataCountersCallback* proxy =
2588 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2589 StreamDataCounters counters;
2590 StreamDataCounters rtx_counters;
2591 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002592
asapersson93e1e232017-02-06 05:18:35 -08002593 const int kMinRequiredPeriodSamples = 8;
2594 const int kPeriodIntervalMs = 2000;
2595 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2596 counters.transmitted.packets += 20;
2597 counters.transmitted.header_bytes += 500;
2598 counters.transmitted.padding_bytes += 1000;
2599 counters.transmitted.payload_bytes += 2000;
2600 counters.retransmitted.packets += 2;
2601 counters.retransmitted.header_bytes += 25;
2602 counters.retransmitted.padding_bytes += 100;
2603 counters.retransmitted.payload_bytes += 250;
2604 counters.fec = counters.retransmitted;
2605 rtx_counters.transmitted = counters.transmitted;
2606 // Advance one interval and update counters.
2607 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2608 proxy->DataCountersUpdated(counters, kFirstSsrc);
2609 proxy->DataCountersUpdated(counters, kSecondSsrc);
2610 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2611 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2612 }
Erik Språng22c2b482016-03-01 09:40:42 +01002613
2614 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002615 VideoEncoderConfig config;
2616 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002617 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002618
asapersson93e1e232017-02-06 05:18:35 -08002619 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002620 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2621 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002622 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002623 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2624 EXPECT_METRIC_EQ(1,
2625 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002626 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002627 EXPECT_METRIC_EQ(1,
2628 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2629 EXPECT_METRIC_EQ(
2630 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002631 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002632 EXPECT_METRIC_EQ(
2633 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2634 EXPECT_METRIC_EQ(
2635 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002636 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002637 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2638 EXPECT_METRIC_EQ(1,
2639 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002640 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002641 EXPECT_METRIC_EQ(
2642 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2643 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002644 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002645
asapersson93e1e232017-02-06 05:18:35 -08002646 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002647 // Double counter values, this should result in the same counts as before but
2648 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002649 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2650 counters.transmitted.packets += 20;
2651 counters.transmitted.header_bytes += 500;
2652 counters.transmitted.padding_bytes += 1000;
2653 counters.transmitted.payload_bytes += 2000;
2654 counters.retransmitted.packets += 2;
2655 counters.retransmitted.header_bytes += 25;
2656 counters.retransmitted.padding_bytes += 100;
2657 counters.retransmitted.payload_bytes += 250;
2658 counters.fec = counters.retransmitted;
2659 rtx_counters.transmitted = counters.transmitted;
2660 // Advance one interval and update counters.
2661 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2662 proxy->DataCountersUpdated(counters, kFirstSsrc);
2663 proxy->DataCountersUpdated(counters, kSecondSsrc);
2664 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2665 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2666 }
Erik Språng22c2b482016-03-01 09:40:42 +01002667
asapersson93e1e232017-02-06 05:18:35 -08002668 // Reset stats proxy also causes histograms to be reported.
2669 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002670
asapersson93e1e232017-02-06 05:18:35 -08002671 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002672 EXPECT_METRIC_EQ(
2673 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2674 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002675 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2676 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002677 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002678 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002679 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2680 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002681 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002682 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2683 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2684 EXPECT_METRIC_EQ(
2685 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2686 12));
asapersson93e1e232017-02-06 05:18:35 -08002687 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002688 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2689 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2690 EXPECT_METRIC_EQ(
2691 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2692 16));
asapersson93e1e232017-02-06 05:18:35 -08002693 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002694 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002695 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002696 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2697 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002698 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002699 EXPECT_METRIC_EQ(
2700 1, metrics::NumSamples(
2701 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2702 EXPECT_METRIC_EQ(
2703 1, metrics::NumEvents(
2704 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002705}
Erik Språng22c2b482016-03-01 09:40:42 +01002706
asapersson93e1e232017-02-06 05:18:35 -08002707TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2708 StreamDataCountersCallback* proxy =
2709 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2710 StreamDataCounters counters;
2711 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002712
asapersson93e1e232017-02-06 05:18:35 -08002713 const int kMinRequiredPeriodSamples = 8;
2714 const int kPeriodIntervalMs = 2000;
2715 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2716 counters.transmitted.packets += 20;
2717 counters.transmitted.header_bytes += 500;
2718 counters.transmitted.payload_bytes += 2000;
2719 counters.fec = counters.retransmitted;
2720 // Advance one interval and update counters.
2721 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2722 proxy->DataCountersUpdated(counters, kFirstSsrc);
2723 }
2724
2725 // RTX enabled. No data sent over RTX.
2726 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002727 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2728 EXPECT_METRIC_EQ(1,
2729 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002730}
2731
2732TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002733 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 05:18:35 -08002734 VideoSendStream::Config config(nullptr);
2735 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2736 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01002737 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2738 field_trials));
asapersson93e1e232017-02-06 05:18:35 -08002739
2740 StreamDataCountersCallback* proxy =
2741 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2742 StreamDataCounters counters;
2743
2744 const int kMinRequiredPeriodSamples = 8;
2745 const int kPeriodIntervalMs = 2000;
2746 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2747 counters.transmitted.packets += 20;
2748 counters.transmitted.header_bytes += 500;
2749 counters.transmitted.payload_bytes += 2000;
2750 counters.fec = counters.retransmitted;
2751 // Advance one interval and update counters.
2752 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2753 proxy->DataCountersUpdated(counters, kFirstSsrc);
2754 }
2755
2756 // RTX not enabled.
2757 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002758 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002759}
2760
2761TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2762 StreamDataCountersCallback* proxy =
2763 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2764 StreamDataCounters counters;
2765 StreamDataCounters rtx_counters;
2766
2767 const int kMinRequiredPeriodSamples = 8;
2768 const int kPeriodIntervalMs = 2000;
2769 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2770 counters.transmitted.packets += 20;
2771 counters.transmitted.header_bytes += 500;
2772 counters.transmitted.payload_bytes += 2000;
2773 // Advance one interval and update counters.
2774 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2775 proxy->DataCountersUpdated(counters, kFirstSsrc);
2776 }
2777
2778 // FEC enabled. No FEC data sent.
2779 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002780 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2781 EXPECT_METRIC_EQ(1,
2782 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002783}
2784
2785TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
Jonas Oreland8ca06132022-03-14 12:52:48 +01002786 test::ScopedKeyValueConfig field_trials;
asapersson93e1e232017-02-06 05:18:35 -08002787 VideoSendStream::Config config(nullptr);
2788 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2789 statistics_proxy_.reset(new SendStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +01002790 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2791 field_trials));
asapersson93e1e232017-02-06 05:18:35 -08002792
2793 StreamDataCountersCallback* proxy =
2794 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2795 StreamDataCounters counters;
2796
2797 const int kMinRequiredPeriodSamples = 8;
2798 const int kPeriodIntervalMs = 2000;
2799 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2800 counters.transmitted.packets += 20;
2801 counters.transmitted.header_bytes += 500;
2802 counters.transmitted.payload_bytes += 2000;
2803 counters.fec = counters.retransmitted;
2804 // Advance one interval and update counters.
2805 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2806 proxy->DataCountersUpdated(counters, kFirstSsrc);
2807 }
2808
2809 // FEC not enabled.
2810 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002811 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002812}
2813
asapersson8d75ac72017-09-15 06:41:15 -07002814TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002815 const std::string kName = "encoderName";
Evan Shrubsole09da10e2022-10-14 14:38:31 +00002816 statistics_proxy_->OnEncoderImplementationChanged(EncoderImplementation{
2817 .name = kName,
2818 .is_hardware_accelerated = true,
2819 });
Erik Språnge2fd86a2018-10-24 11:32:39 +02002820 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
Evan Shrubsole09da10e2022-10-14 14:38:31 +00002821 EXPECT_THAT(statistics_proxy_->GetStats().power_efficient_encoder,
2822 ::testing::IsTrue());
asapersson8d75ac72017-09-15 06:41:15 -07002823}
2824
Sergey Silkinbb081a62018-09-04 18:34:22 +02002825TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2826 static const int kEncodedWidth = 123;
2827 static const int kEncodedHeight = 81;
2828 EncodedImage encoded_image;
2829 encoded_image._encodedWidth = kEncodedWidth;
2830 encoded_image._encodedHeight = kEncodedHeight;
2831 encoded_image.SetSpatialIndex(0);
2832
2833 CodecSpecificInfo codec_info;
2834 codec_info.codecType = kVideoCodecVP9;
2835
2836 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002837 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002838 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2839 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2840 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2841 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2842
2843 // Top layer updates resolution.
2844 encoded_image._encodedWidth = kEncodedWidth * 2;
2845 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002846 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002847 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2848 stats = statistics_proxy_->GetStats();
2849 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2850 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2851
2852 // Low layer of next frame doesn't update resolution.
2853 encoded_image._encodedWidth = kEncodedWidth;
2854 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002855 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002856 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2857 stats = statistics_proxy_->GetStats();
2858 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2859 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2860}
2861
asapersson8d75ac72017-09-15 06:41:15 -07002862class ForcedFallbackTest : public SendStatisticsProxyTest {
2863 public:
2864 explicit ForcedFallbackTest(const std::string& field_trials)
2865 : SendStatisticsProxyTest(field_trials) {
2866 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002867 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002868 encoded_image_._encodedWidth = kWidth;
2869 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002870 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002871 }
2872
2873 ~ForcedFallbackTest() override {}
2874
2875 protected:
2876 void InsertEncodedFrames(int num_frames, int interval_ms) {
Evan Shrubsole09da10e2022-10-14 14:38:31 +00002877 statistics_proxy_->OnEncoderImplementationChanged(
2878 {.name = codec_name_, .is_hardware_accelerated = false});
Erik Språnge2fd86a2018-10-24 11:32:39 +02002879
asapersson8d75ac72017-09-15 06:41:15 -07002880 // First frame is not updating stats, insert initial frame.
2881 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2882 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2883 }
2884 for (int i = 0; i < num_frames; ++i) {
2885 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2886 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2887 }
2888 // Add frame to include last time interval.
2889 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2890 }
2891
2892 EncodedImage encoded_image_;
2893 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002894 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002895 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2896 const int kFrameIntervalMs = 1000;
2897 const int kMinFrames = 20; // Min run time 20 sec.
2898};
2899
2900class ForcedFallbackDisabled : public ForcedFallbackTest {
2901 public:
2902 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002903 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2904 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002905};
2906
2907class ForcedFallbackEnabled : public ForcedFallbackTest {
2908 public:
2909 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002910 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2911 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002912};
2913
2914TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2915 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2916 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002917 EXPECT_METRIC_EQ(0,
2918 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2919 EXPECT_METRIC_EQ(
2920 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002921}
2922
2923TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2924 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002925 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002926 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002927 EXPECT_METRIC_EQ(1,
2928 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2929 EXPECT_METRIC_EQ(
2930 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2931 EXPECT_METRIC_EQ(
2932 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2933 EXPECT_METRIC_EQ(
2934 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002935}
2936
2937TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2938 codec_info_.codecType = kVideoCodecVP9;
2939 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2940 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002941 EXPECT_METRIC_EQ(0,
2942 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2943 EXPECT_METRIC_EQ(
2944 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002945}
2946
2947TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2948 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2949 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2950 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002951 EXPECT_METRIC_EQ(0,
2952 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2953 EXPECT_METRIC_EQ(
2954 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002955}
2956
2957TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002958 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002959 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2960 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002961 EXPECT_METRIC_EQ(0,
2962 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2963 EXPECT_METRIC_EQ(
2964 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002965}
2966
2967TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2968 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2969 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002970 EXPECT_METRIC_EQ(0,
2971 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2972 EXPECT_METRIC_EQ(
2973 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002974}
2975
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002976TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2977 InsertEncodedFrames(1, kFrameIntervalMs);
2978 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2979}
2980
2981TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2982 InsertEncodedFrames(1, kFrameIntervalMs);
2983 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2984}
2985
2986TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002987 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002988 InsertEncodedFrames(1, kFrameIntervalMs);
2989 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2990}
2991
2992TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2993 encoded_image_._encodedWidth = kWidth + 1;
2994 InsertEncodedFrames(1, kFrameIntervalMs);
2995 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2996}
2997
2998TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002999 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003000 InsertEncodedFrames(1, kFrameIntervalMs);
3001 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3002}
3003
3004TEST_F(ForcedFallbackDisabled,
3005 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
3006 encoded_image_._encodedWidth = kWidth + 1;
3007 statistics_proxy_->OnMinPixelLimitReached();
3008 InsertEncodedFrames(1, kFrameIntervalMs);
3009 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3010}
3011
asapersson8d75ac72017-09-15 06:41:15 -07003012TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
3013 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003014 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003015 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003016 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003017 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003018 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003019 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003020
3021 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003022 EXPECT_METRIC_EQ(1,
3023 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3024 EXPECT_METRIC_EQ(
3025 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3026 EXPECT_METRIC_EQ(
3027 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3028 EXPECT_METRIC_EQ(
3029 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003030}
3031
3032TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
3033 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
3034 const int kMaxFrameDiffMs = 2000;
3035
3036 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
3037 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003038 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003039 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003040 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003041 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003042 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003043 InsertEncodedFrames(20, 1000);
3044 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
3045 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003046 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003047 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07003048 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003049 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003050 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003051 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003052 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003053
3054 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003055 EXPECT_METRIC_EQ(1,
3056 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3057 EXPECT_METRIC_EQ(
3058 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3059 EXPECT_METRIC_EQ(
3060 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3061 EXPECT_METRIC_EQ(
3062 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003063}
3064
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003065TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
3066 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003067 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003068 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3069
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003070 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003071 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003072 EXPECT_METRIC_EQ(0,
3073 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3074 EXPECT_METRIC_EQ(
3075 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003076}
3077
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003078TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
3079 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003080 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003081 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3082
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003083 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003084 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003085 EXPECT_METRIC_EQ(1,
3086 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3087 EXPECT_METRIC_EQ(
3088 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003089}
3090
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00003091} // namespace webrtc