blob: 9c3b2c188bbaff377a7dd7e3cc0534235f89504a [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"
25#include "api/video_codecs/video_encoder_config.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020026#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070028#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000030
31namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070032namespace {
33const uint32_t kFirstSsrc = 17;
34const uint32_t kSecondSsrc = 42;
35const uint32_t kFirstRtxSsrc = 18;
36const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080037const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080038const int kFpsPeriodicIntervalMs = 2000;
39const int kWidth = 640;
40const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070041const int kQpIdx0 = 21;
42const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010043const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080044const CodecSpecificInfo kDefaultCodecInfo = []() {
45 CodecSpecificInfo codec_info;
46 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080047 return codec_info;
48}();
Evan Shrubsoledff79252020-04-16 11:34:32 +020049
50const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
51 true);
52const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
53 true,
54 false);
55const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
56 false,
57 true);
58const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
asapersson5265fed2016-04-18 02:58:47 -070059} // namespace
sprang07fb9be2016-02-24 07:55:00 -080060
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000061class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000062 public:
asapersson8d75ac72017-09-15 06:41:15 -070063 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
64 explicit SendStatisticsProxyTest(const std::string& field_trials)
65 : override_field_trials_(field_trials),
66 fake_clock_(1234),
Åsa Persson90719572021-04-08 19:05:30 +020067 config_(GetTestConfig()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000068 virtual ~SendStatisticsProxyTest() {}
69
70 protected:
71 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070072 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080073 statistics_proxy_.reset(new SendStatisticsProxy(
74 &fake_clock_, GetTestConfig(),
75 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000076 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010077 for (const auto& ssrc : config_.rtp.ssrcs) {
78 expected_.substreams[ssrc].type =
79 VideoSendStream::StreamStats::StreamType::kMedia;
80 }
81 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
82 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
83 expected_.substreams[ssrc].type =
84 VideoSendStream::StreamStats::StreamType::kRtx;
85 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
86 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000087 }
88
89 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070090 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080091 config.rtp.ssrcs.push_back(kFirstSsrc);
92 config.rtp.ssrcs.push_back(kSecondSsrc);
93 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
94 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070095 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000096 return config;
97 }
98
asaperssona6a699a2016-11-25 03:52:46 -080099 VideoSendStream::Config GetTestConfigWithFlexFec() {
100 VideoSendStream::Config config(nullptr);
101 config.rtp.ssrcs.push_back(kFirstSsrc);
102 config.rtp.ssrcs.push_back(kSecondSsrc);
103 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
104 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -0800105 config.rtp.flexfec.payload_type = 50;
106 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +0100107 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -0800108 return config;
109 }
110
111 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
112 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
113 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
114 stats.substreams.find(ssrc);
115 EXPECT_NE(it, stats.substreams.end());
116 return it->second;
117 }
118
asapersson66d4b372016-12-19 06:50:53 -0800119 void UpdateDataCounters(uint32_t ssrc) {
120 StreamDataCountersCallback* proxy =
121 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
122 StreamDataCounters counters;
123 proxy->DataCountersUpdated(counters, ssrc);
124 }
125
sprang@webrtc.org09315702014-02-07 12:06:29 +0000126 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
Di Wu668dbf62021-02-27 00:29:15 -0800127 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000128 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
129 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000130 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000131 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
133 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000134 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000135 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000136 it != one.substreams.end(); ++it) {
137 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
138 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000139 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000140 const VideoSendStream::StreamStats& a = it->second;
141 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142
Henrik Boströmf45ca372020-03-24 13:30:50 +0100143 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000144 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
145 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000146 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000147 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
148 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000150 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
151 b.rtp_stats.transmitted.payload_bytes);
152 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
153 b.rtp_stats.transmitted.header_bytes);
154 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
155 b.rtp_stats.transmitted.padding_bytes);
156 EXPECT_EQ(a.rtp_stats.transmitted.packets,
157 b.rtp_stats.transmitted.packets);
158 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
159 b.rtp_stats.retransmitted.packets);
160 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000161
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200162 EXPECT_EQ(a.report_block_data.has_value(),
163 b.report_block_data.has_value());
164 if (a.report_block_data.has_value()) {
165 const RTCPReportBlock& a_rtcp_stats =
166 a.report_block_data->report_block();
167 const RTCPReportBlock& b_rtcp_stats =
168 b.report_block_data->report_block();
169 EXPECT_EQ(a_rtcp_stats.fraction_lost, b_rtcp_stats.fraction_lost);
170 EXPECT_EQ(a_rtcp_stats.packets_lost, b_rtcp_stats.packets_lost);
171 EXPECT_EQ(a_rtcp_stats.extended_highest_sequence_number,
172 b_rtcp_stats.extended_highest_sequence_number);
173 EXPECT_EQ(a_rtcp_stats.jitter, b_rtcp_stats.jitter);
174 }
sprang@webrtc.org09315702014-02-07 12:06:29 +0000175 }
176 }
177
asapersson8d75ac72017-09-15 06:41:15 -0700178 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000179 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800180 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000181 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000183};
184
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200185TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
186 ReportBlockDataObserver* callback = statistics_proxy_.get();
187 for (uint32_t ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000188 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200189 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200190 RTCPReportBlock report_block;
191 report_block.source_ssrc = ssrc;
192 report_block.packets_lost = offset;
193 report_block.extended_highest_sequence_number = offset + 1;
194 report_block.fraction_lost = offset + 2;
195 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200196 ReportBlockData data;
197 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200198 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200199
200 callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000201 }
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200202 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000203 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200204 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200205 RTCPReportBlock report_block;
206 report_block.source_ssrc = ssrc;
207 report_block.packets_lost = offset;
208 report_block.extended_highest_sequence_number = offset + 1;
209 report_block.fraction_lost = offset + 2;
210 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200211 ReportBlockData data;
212 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200213 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200214
215 callback->OnReportBlockDataUpdated(data);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000216 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000217 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000218 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000219}
220
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000221TEST_F(SendStatisticsProxyTest, Suspended) {
222 // Verify that the value is false by default.
223 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
224
225 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200226 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000227 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
228
229 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200230 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000231 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
232}
233
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000234TEST_F(SendStatisticsProxyTest, FrameCounts) {
235 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700236 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000237 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000238 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
239 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000240 FrameCounts frame_counts;
241 frame_counts.key_frames = offset;
242 frame_counts.delta_frames = offset + 1;
243 stats.frame_counts = frame_counts;
244 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000245 }
asapersson35151f32016-05-02 23:44:01 -0700246 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000247 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000248 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
249 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000250 FrameCounts frame_counts;
251 frame_counts.key_frames = offset;
252 frame_counts.delta_frames = offset + 1;
253 stats.frame_counts = frame_counts;
254 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000255 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000256
257 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000258 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000259}
260
261TEST_F(SendStatisticsProxyTest, DataCounters) {
262 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700263 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000264 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
265 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000266 size_t offset = ssrc * sizeof(StreamDataCounters);
267 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000268 counters.transmitted.payload_bytes = offset;
269 counters.transmitted.header_bytes = offset + 1;
270 counters.fec.packets = offset_uint32 + 2;
271 counters.transmitted.padding_bytes = offset + 3;
272 counters.retransmitted.packets = offset_uint32 + 4;
273 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000274 callback->DataCountersUpdated(counters, ssrc);
275 }
asapersson35151f32016-05-02 23:44:01 -0700276 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000277 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
278 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000279 size_t offset = ssrc * sizeof(StreamDataCounters);
280 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000281 counters.transmitted.payload_bytes = offset;
282 counters.transmitted.header_bytes = offset + 1;
283 counters.fec.packets = offset_uint32 + 2;
284 counters.transmitted.padding_bytes = offset + 3;
285 counters.retransmitted.packets = offset_uint32 + 4;
286 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000287 callback->DataCountersUpdated(counters, ssrc);
288 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000289
290 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000291 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000292}
293
294TEST_F(SendStatisticsProxyTest, Bitrate) {
295 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700296 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000297 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200298 uint32_t total = ssrc;
299 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000300 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700301 expected_.substreams[ssrc].total_bitrate_bps = total;
302 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000303 }
asapersson35151f32016-05-02 23:44:01 -0700304 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000305 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200306 uint32_t total = ssrc;
307 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000308 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700309 expected_.substreams[ssrc].total_bitrate_bps = total;
310 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000311 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000312
313 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000314 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000315}
316
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000317TEST_F(SendStatisticsProxyTest, SendSideDelay) {
318 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700319 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000320 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
321 // stream.
322 int avg_delay_ms = ssrc;
323 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200324 uint64_t total_packet_send_delay_ms = ssrc + 2;
325 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
326 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000327 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
328 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200329 expected_.substreams[ssrc].total_packet_send_delay_ms =
330 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000331 }
asapersson35151f32016-05-02 23:44:01 -0700332 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000333 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
334 // stream.
335 int avg_delay_ms = ssrc;
336 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200337 uint64_t total_packet_send_delay_ms = ssrc + 2;
338 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
339 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000340 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
341 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200342 expected_.substreams[ssrc].total_packet_send_delay_ms =
343 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000344 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000345 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000346 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000347}
348
Peter Boströme4499152016-02-05 11:13:28 +0100349TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800350 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200351 int encode_usage_percent = 80;
352 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
353 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800354
355 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
356 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200357 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800358}
359
Henrik Boström5684af52019-04-02 15:05:21 +0200360TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
361 const int kEncodeUsagePercent = 0; // Don't care for this test.
362 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
363 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
364 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
365 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
366 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
367}
368
sakal43536c32016-10-24 01:46:43 -0700369TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
370 EncodedImage encoded_image;
371 CodecSpecificInfo codec_info;
372 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
373 for (uint32_t i = 1; i <= 3; ++i) {
374 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
375 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
376 }
377}
378
sakal87da4042016-10-31 06:53:47 -0700379TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
380 EncodedImage encoded_image;
381 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200382 auto ssrc = config_.rtp.ssrcs[0];
383 EXPECT_EQ(absl::nullopt,
384 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700385 encoded_image.qp_ = 3;
386 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200387 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700388 encoded_image.qp_ = 127;
389 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200390 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700391}
392
393TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
394 EncodedImage encoded_image;
395 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200396 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700397 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200398 EXPECT_EQ(absl::nullopt,
399 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700400 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200401 EXPECT_EQ(absl::nullopt,
402 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700403}
404
Henrik Boström23aff9b2019-05-20 15:15:38 +0200405TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
406 const uint32_t kTargetBytesPerSecond = 100000;
407 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
408 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
409
410 EncodedImage encoded_image;
411 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
412 // On the first frame we don't know the frame rate yet, calculation yields
413 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
Artem Titovab30d722021-07-27 16:22:11 +0200414 // increment by a full `kTargetBytesPerSecond`.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200415 EXPECT_EQ(kTargetBytesPerSecond,
416 statistics_proxy_->GetStats().total_encoded_bytes_target);
417}
418
419TEST_F(SendStatisticsProxyTest,
420 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
421 const uint32_t kTargetBytesPerSecond = 100000;
422 const int kInterframeDelayMs = 100;
423
424 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
Artem Titovab30d722021-07-27 16:22:11 +0200425 // `fake_clock_` for testing, but the RateTracker relies on a global clock.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200426 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
427 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
428 // this test can stop relying on rtc::ScopedFakeClock.
429 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100430 fake_global_clock.SetTime(
431 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200432
433 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
434 EncodedImage encoded_image;
435
436 // First frame
437 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
438 uint64_t first_total_encoded_bytes_target =
439 statistics_proxy_->GetStats().total_encoded_bytes_target;
440 // Second frame
441 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100442 fake_global_clock.SetTime(
443 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200444 encoded_image.SetTimestamp(encoded_image.Timestamp() +
445 90 * kInterframeDelayMs);
446 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
447
448 auto stats = statistics_proxy_->GetStats();
449 // By the time the second frame arrives, one frame has previously arrived
Artem Titovab30d722021-07-27 16:22:11 +0200450 // during a `kInterframeDelayMs` interval. The estimated encode frame rate at
Henrik Boström23aff9b2019-05-20 15:15:38 +0200451 // the second frame's arrival should be 10 FPS.
452 uint64_t delta_encoded_bytes_target =
453 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
454 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
455}
456
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200457TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
458 const int kInterframeDelayMs = 100;
Åsa Persson603e6e32021-08-10 08:56:36 +0200459 const auto ssrc = config_.rtp.ssrcs[0];
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200460 rtc::ScopedFakeClock fake_global_clock;
461 fake_global_clock.SetTime(
462 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
463
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200464 // First frame
Åsa Persson603e6e32021-08-10 08:56:36 +0200465 EncodedImage encoded_image;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200466 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200467 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
468 fake_global_clock.SetTime(
469 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson603e6e32021-08-10 08:56:36 +0200470 // Second frame
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200471 encoded_image.SetTimestamp(encoded_image.Timestamp() +
472 90 * kInterframeDelayMs);
473 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson603e6e32021-08-10 08:56:36 +0200474 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
475 fake_global_clock.SetTime(
476 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200477
478 auto stats = statistics_proxy_->GetStats();
479 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
480}
481
Åsa Persson8d564722021-08-03 14:43:01 +0200482TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp8Simulcast) {
483 const int kInterframeDelayMs = 100;
484 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200485 fake_global_clock.SetTime(
486 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200487 EncodedImage encoded_image;
488 CodecSpecificInfo codec_info;
489 codec_info.codecType = kVideoCodecVP8;
490
491 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200492 encoded_image.SetTimestamp(encoded_image.Timestamp() +
493 90 * kInterframeDelayMs);
494 encoded_image.SetSpatialIndex(0);
495 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
496 encoded_image.SetSpatialIndex(1);
497 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200498 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
499 fake_global_clock.SetTime(
500 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200501 }
502
503 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
504 EXPECT_EQ(2u, stats.substreams.size());
505 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
506 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson603e6e32021-08-10 08:56:36 +0200507
508 // Stop encoding second stream, expect framerate to be zero.
509 for (int i = 0; i < 10; ++i) {
510 encoded_image.SetTimestamp(encoded_image.Timestamp() +
511 90 * kInterframeDelayMs);
512 encoded_image.SetSpatialIndex(0);
513 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
514 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
515 fake_global_clock.SetTime(
516 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
517 }
518
519 stats = statistics_proxy_->GetStats();
520 EXPECT_EQ(2u, stats.substreams.size());
521 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
522 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 0);
523
524 // Start encoding second stream.
525 for (int i = 0; i < 10; ++i) {
526 encoded_image.SetTimestamp(encoded_image.Timestamp() +
527 90 * kInterframeDelayMs);
528 encoded_image.SetSpatialIndex(0);
529 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
530 encoded_image.SetSpatialIndex(1);
531 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
532 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
533 fake_global_clock.SetTime(
534 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
535 }
536
537 stats = statistics_proxy_->GetStats();
538 EXPECT_EQ(2u, stats.substreams.size());
539 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
540 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
Åsa Persson8d564722021-08-03 14:43:01 +0200541}
542
543TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp9Svc) {
544 const int kInterframeDelayMs = 100;
545 rtc::ScopedFakeClock fake_global_clock;
Åsa Persson603e6e32021-08-10 08:56:36 +0200546 fake_global_clock.SetTime(
547 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200548 EncodedImage encoded_image;
549 CodecSpecificInfo codec_info;
550 codec_info.codecType = kVideoCodecVP9;
551
552 for (int i = 0; i < 10; ++i) {
Åsa Persson8d564722021-08-03 14:43:01 +0200553 encoded_image.SetTimestamp(encoded_image.Timestamp() +
554 90 * kInterframeDelayMs);
555 encoded_image.SetSpatialIndex(0);
556 codec_info.end_of_picture = false;
557 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
558 encoded_image.SetSpatialIndex(1);
559 codec_info.end_of_picture = true;
560 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Åsa Persson603e6e32021-08-10 08:56:36 +0200561 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
562 fake_global_clock.SetTime(
563 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Åsa Persson8d564722021-08-03 14:43:01 +0200564 }
565
566 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
567 EXPECT_EQ(1u, stats.substreams.size());
568 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
569}
570
asapersson09f05612017-05-15 23:40:18 -0700571TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200572 VideoAdaptationCounters cpu_counts;
573 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700574 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700575 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200576 cpu_counts.fps_adaptations = 1;
577 cpu_counts.resolution_adaptations = 0;
578 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200579 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
580 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700581 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700582 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200583 cpu_counts.fps_adaptations = 0;
584 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200585 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
586 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700587 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700588 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200589 cpu_counts.fps_adaptations = 1;
590 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
591 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200592 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
593 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700594 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700595 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200596 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
597 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200598 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
599 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700600 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
601 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
602}
603
604TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200605 VideoAdaptationCounters cpu_counts;
606 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700607 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
608 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200609 quality_counts.fps_adaptations = 1;
610 quality_counts.resolution_adaptations = 0;
611 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200612 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
613 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700614 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
615 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200616 quality_counts.fps_adaptations = 0;
617 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200618 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
619 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700620 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
621 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200622 quality_counts.fps_adaptations = 1;
623 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
624 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200625 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
626 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700627 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
628 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200629 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
630 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200631 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
632 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700633 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
634 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
635}
636
637TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200638 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
639 VideoAdaptationCounters cpu_counts;
640 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700641 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
642
Evan Shrubsoledff79252020-04-16 11:34:32 +0200643 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200644 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
645 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700646 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700647 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
648 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
649
Evan Shrubsoledff79252020-04-16 11:34:32 +0200650 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200651 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
652 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700653 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
654 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700655 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700656 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700657}
658
asapersson09f05612017-05-15 23:40:18 -0700659TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200660 VideoAdaptationCounters cpu_counts;
661 VideoAdaptationCounters quality_counts;
662 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700663 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
664
Evan Shrubsoledff79252020-04-16 11:34:32 +0200665 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200666 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
667 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700668 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
669 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700670 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
671
Evan Shrubsoledff79252020-04-16 11:34:32 +0200672 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200673 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
674 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700675 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700676 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700677 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
678 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700679}
680
Evan Shrubsoledff79252020-04-16 11:34:32 +0200681TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
682 VideoAdaptationCounters cpu_counts;
683 VideoAdaptationCounters quality_counts;
684 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
685 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
686 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
687
688 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200689 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
690 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200691 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200692 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
693 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200694 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200695 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
696 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200697 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200698 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
699 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200700 // We have 1 fps and resolution reduction for both cpu and quality
701 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
702 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
703 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
704 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
705 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
706 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
707
708 // Disable quality scaling. Expect quality scaling not limited.
709 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
710 kScalingDisabled);
711 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
712 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
713 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
714 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
715 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
716 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
717
718 // Disable framerate scaling.
719 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
720 kFramerateScalingDisabled);
721 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
722 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
723 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
724 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
725 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
726 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
727
728 // Disable resolution scaling.
729 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
730 kResolutionScalingDisabled);
731 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
732 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
733 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
734 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
735 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
736 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
737
738 // Enable all
739 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
740 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
741 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
742 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
743 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
744 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
745 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
746}
747
asapersson09f05612017-05-15 23:40:18 -0700748TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700749 // First RTP packet sent.
750 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700751 // Min runtime has passed.
752 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
753 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100754 EXPECT_METRIC_EQ(
755 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
756 EXPECT_METRIC_EQ(
757 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700758}
759
760TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700761 // First RTP packet sent.
762 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700763 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200764 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700765 // Min runtime has not passed.
766 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
767 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100768 EXPECT_METRIC_EQ(
769 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
770 EXPECT_METRIC_EQ(
771 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700772}
773
asapersson09f05612017-05-15 23:40:18 -0700774TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700775 // First RTP packet sent.
776 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700777 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200778 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700779 // Min runtime has passed.
780 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
781 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100782 EXPECT_METRIC_EQ(
783 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
784 EXPECT_METRIC_EQ(
785 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
786 EXPECT_METRIC_EQ(
787 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
788 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700789 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
790}
791
792TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700793 // First RTP packet sent.
794 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700795 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200796 VideoAdaptationCounters cpu_counts;
797 VideoAdaptationCounters quality_counts;
798 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700799 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200800 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
801 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700802 fake_clock_.AdvanceTimeMilliseconds(10000);
803 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100804 EXPECT_METRIC_EQ(
805 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
806 EXPECT_METRIC_EQ(
807 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700808}
809
Åsa Persson875841d2018-01-08 08:49:53 +0100810TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
811 // First RTP packet sent.
812 UpdateDataCounters(kFirstSsrc);
813 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200814 VideoAdaptationCounters cpu_counts;
815 VideoAdaptationCounters quality_counts;
816 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100817 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200818 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
819 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100820 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
821 fake_clock_.AdvanceTimeMilliseconds(10000);
822 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100823 EXPECT_METRIC_EQ(
824 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
825 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100826 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
827}
828
829TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
830 // First RTP packet sent.
831 UpdateDataCounters(kFirstSsrc);
832 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200833 VideoAdaptationCounters cpu_counts;
834 VideoAdaptationCounters quality_counts;
835 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100836 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200837 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200838 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
839 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100840 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200841 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200842 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
843 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100844 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200845 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200846 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
847 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100848 fake_clock_.AdvanceTimeMilliseconds(10000);
849 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100850 EXPECT_METRIC_EQ(
851 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
852 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100853 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
854}
855
856TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
857 // First RTP packet sent.
858 UpdateDataCounters(kFirstSsrc);
859 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200860 VideoAdaptationCounters cpu_counts;
861 VideoAdaptationCounters quality_counts;
862 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100863 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200864 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
865 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100866 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
867 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
868 fake_clock_.AdvanceTimeMilliseconds(10000);
869 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100870 EXPECT_METRIC_EQ(
871 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
872 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100873 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
874}
875
876TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
877 // First RTP packet sent.
878 UpdateDataCounters(kFirstSsrc);
879 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200880 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
881 VideoAdaptationCounters cpu_counts;
882 VideoAdaptationCounters quality_counts;
883 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100884 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200885 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200886 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
887 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100888 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200889 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200890 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
891 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100892 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200893 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200894 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
895 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200896 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200897 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
898 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200899 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200900 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
901 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200902 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200903 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
904 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200905 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200906 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
907 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200908 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200909 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
910 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100911
912 fake_clock_.AdvanceTimeMilliseconds(10000);
913 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100914 EXPECT_METRIC_EQ(
915 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
916 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100917 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
918}
919
asapersson6eca98b2017-04-04 23:40:50 -0700920TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700921 // First RTP packet sent.
922 UpdateDataCounters(kFirstSsrc);
923
asapersson09f05612017-05-15 23:40:18 -0700924 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200925 VideoAdaptationCounters cpu_counts;
926 VideoAdaptationCounters quality_counts;
927 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
928 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700929 fake_clock_.AdvanceTimeMilliseconds(10000);
930
asapersson09f05612017-05-15 23:40:18 -0700931 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700932 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200933 quality_counts.fps_adaptations = 0;
934 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
935 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700936 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200937 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
938 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700939 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200940 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
941 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700942 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200943 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
944 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700945
asapersson09f05612017-05-15 23:40:18 -0700946 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200947 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
948 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700949 fake_clock_.AdvanceTimeMilliseconds(30000);
950
asapersson09f05612017-05-15 23:40:18 -0700951 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700952 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200953 quality_counts.resolution_adaptations = 0;
954 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
955 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200956 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
957 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700958 fake_clock_.AdvanceTimeMilliseconds(10000);
959
asapersson09f05612017-05-15 23:40:18 -0700960 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200961 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
962 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700963 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200964 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
965 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700966 fake_clock_.AdvanceTimeMilliseconds(20000);
967
asapersson0944a802017-04-07 00:57:58 -0700968 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700969 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100970 EXPECT_METRIC_EQ(
971 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
972 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700973 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
974}
975
asapersson0944a802017-04-07 00:57:58 -0700976TEST_F(SendStatisticsProxyTest,
977 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
978 // First RTP packet sent.
979 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700980
asapersson0944a802017-04-07 00:57:58 -0700981 // Suspend and resume video.
982 statistics_proxy_->OnSuspendChange(true);
983 fake_clock_.AdvanceTimeMilliseconds(5000);
984 statistics_proxy_->OnSuspendChange(false);
985
986 // Min runtime has passed but scaling not enabled.
987 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
988 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100989 EXPECT_METRIC_EQ(
990 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
991 EXPECT_METRIC_EQ(
992 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700993}
994
995TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
996 // First RTP packet sent.
997 UpdateDataCounters(kFirstSsrc);
998
asapersson09f05612017-05-15 23:40:18 -0700999 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001000 VideoAdaptationCounters cpu_counts;
1001 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -07001002 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001003 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001004 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001005 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1006 cpu_counts, quality_counts);
1007 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1008 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001009
1010 // Suspend and resume video.
1011 statistics_proxy_->OnSuspendChange(true);
1012 fake_clock_.AdvanceTimeMilliseconds(30000);
1013 statistics_proxy_->OnSuspendChange(false);
1014
1015 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001016 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1017 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001018 fake_clock_.AdvanceTimeMilliseconds(10000);
1019
1020 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
1021 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001022 EXPECT_METRIC_EQ(
1023 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1024 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -07001025 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1026}
1027
1028TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
1029 // First RTP packet sent.
1030 UpdateDataCounters(kFirstSsrc);
1031
1032 // Video not suspended.
1033 statistics_proxy_->OnSuspendChange(false);
1034 fake_clock_.AdvanceTimeMilliseconds(30000);
1035
asapersson09f05612017-05-15 23:40:18 -07001036 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001037 VideoAdaptationCounters cpu_counts;
1038 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -07001039 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001040 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001041 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001042 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1043 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001044
1045 // Video not suspended, stats time already started.
1046 statistics_proxy_->OnSuspendChange(false);
1047 fake_clock_.AdvanceTimeMilliseconds(10000);
1048
asapersson09f05612017-05-15 23:40:18 -07001049 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001050 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1051 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -07001052 fake_clock_.AdvanceTimeMilliseconds(30000);
1053
1054 // Suspend and resume video, stats time not started when scaling not enabled.
1055 statistics_proxy_->OnSuspendChange(true);
1056 fake_clock_.AdvanceTimeMilliseconds(30000);
1057 statistics_proxy_->OnSuspendChange(false);
1058 fake_clock_.AdvanceTimeMilliseconds(30000);
1059
asapersson09f05612017-05-15 23:40:18 -07001060 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -07001061 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001062 cpu_counts.fps_adaptations = 0;
1063 cpu_counts.resolution_adaptations = 0;
1064 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001065 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001066 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1067 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001068
1069 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
1070 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001071 EXPECT_METRIC_EQ(
1072 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1073 EXPECT_METRIC_EQ(
1074 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -07001075}
1076
1077TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
1078 // First RTP packet sent.
1079 UpdateDataCounters(kFirstSsrc);
1080
1081 // Video suspended.
1082 statistics_proxy_->OnSuspendChange(true);
1083
asapersson09f05612017-05-15 23:40:18 -07001084 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001085 VideoAdaptationCounters cpu_counts;
1086 VideoAdaptationCounters quality_counts;
1087 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001088 fake_clock_.AdvanceTimeMilliseconds(10000);
1089
1090 // Resume video, stats time started.
1091 // Adapt changes: 1, elapsed time: 10 sec.
1092 statistics_proxy_->OnSuspendChange(false);
1093 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001094 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1095 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001096
1097 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1098 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001099 EXPECT_METRIC_EQ(
1100 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1101 EXPECT_METRIC_EQ(
1102 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001103}
1104
1105TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001106 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001107 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001108 VideoAdaptationCounters cpu_counts;
1109 VideoAdaptationCounters quality_counts;
1110 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001111 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001112 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001113
asapersson0944a802017-04-07 00:57:58 -07001114 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001115 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001116 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1117 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001118 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001119
asapersson0944a802017-04-07 00:57:58 -07001120 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001121 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001122 EXPECT_METRIC_EQ(
1123 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1124 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001125 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1126}
1127
1128TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001129 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001130 VideoAdaptationCounters cpu_counts;
1131 VideoAdaptationCounters quality_counts;
1132 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001133 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001134 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1135 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001136
1137 // Send first packet, scaling disabled.
1138 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001139 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001140 fake_clock_.AdvanceTimeMilliseconds(60000);
1141
asapersson09f05612017-05-15 23:40:18 -07001142 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001143 cpu_counts.resolution_adaptations = 0;
1144 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1145 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001146 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001147 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001148
asapersson0944a802017-04-07 00:57:58 -07001149 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001150 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001151 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1152 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001153
asapersson0944a802017-04-07 00:57:58 -07001154 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001155 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001156 EXPECT_METRIC_EQ(
1157 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1158 EXPECT_METRIC_EQ(
1159 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001160}
1161
1162TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001163 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001164 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001165 VideoAdaptationCounters cpu_counts;
1166 VideoAdaptationCounters quality_counts;
1167 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1168 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001169
asapersson0944a802017-04-07 00:57:58 -07001170 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001171 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1172 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001173 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001174 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1175 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001176 fake_clock_.AdvanceTimeMilliseconds(9000);
1177
1178 // Switch content type, real-time stats should be updated.
1179 VideoEncoderConfig config;
1180 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001181 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001182 EXPECT_METRIC_EQ(
1183 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1184 EXPECT_METRIC_EQ(
1185 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1186 EXPECT_METRIC_EQ(
1187 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001188
asapersson0944a802017-04-07 00:57:58 -07001189 // First RTP packet sent, scaling enabled.
1190 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001191 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1192 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001193
asapersson0944a802017-04-07 00:57:58 -07001194 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001195 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1196 cpu_counts, quality_counts);
1197 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1198 cpu_counts, quality_counts);
1199 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1200 cpu_counts, quality_counts);
1201 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1202 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001203 fake_clock_.AdvanceTimeMilliseconds(120000);
1204
1205 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001206 EXPECT_METRIC_EQ(1,
1207 metrics::NumSamples(
1208 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1209 EXPECT_METRIC_EQ(
1210 1, metrics::NumEvents(
1211 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1212 EXPECT_METRIC_EQ(
1213 0, metrics::NumSamples(
1214 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001215}
1216
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001217TEST_F(SendStatisticsProxyTest,
1218 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001219 VideoAdaptationCounters cpu_counts;
1220 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001221
Evan Shrubsoledff79252020-04-16 11:34:32 +02001222 cpu_counts.resolution_adaptations = 1;
1223 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001224 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1225 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001226
1227 EXPECT_EQ(QualityLimitationReason::kCpu,
1228 statistics_proxy_->GetStats().quality_limitation_reason);
1229}
1230
1231TEST_F(SendStatisticsProxyTest,
1232 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001233 VideoAdaptationCounters cpu_counts;
1234 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001235
Evan Shrubsoledff79252020-04-16 11:34:32 +02001236 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001237
Evan Shrubsoledff79252020-04-16 11:34:32 +02001238 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001239 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1240 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001241
1242 EXPECT_EQ(QualityLimitationReason::kCpu,
1243 statistics_proxy_->GetStats().quality_limitation_reason);
1244}
1245
1246TEST_F(SendStatisticsProxyTest,
1247 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001248 VideoAdaptationCounters cpu_counts;
1249 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001250
Evan Shrubsoledff79252020-04-16 11:34:32 +02001251 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001252
Evan Shrubsoledff79252020-04-16 11:34:32 +02001253 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001254 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1255 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001256
1257 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1258 statistics_proxy_->GetStats().quality_limitation_reason);
1259}
1260
1261TEST_F(SendStatisticsProxyTest,
1262 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001263 VideoAdaptationCounters cpu_counts;
1264 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001265
Evan Shrubsoledff79252020-04-16 11:34:32 +02001266 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001267
Evan Shrubsoledff79252020-04-16 11:34:32 +02001268 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001269 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1270 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001271
1272 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1273 statistics_proxy_->GetStats().quality_limitation_reason);
1274}
1275
1276TEST_F(SendStatisticsProxyTest,
1277 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001278 VideoAdaptationCounters cpu_counts;
1279 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001280
Evan Shrubsoledff79252020-04-16 11:34:32 +02001281 cpu_counts.resolution_adaptations = 1;
1282 quality_counts.resolution_adaptations = 1;
1283 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001284
1285 // Even if the last adaptation reason is kCpu, if the counters indicate being
1286 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001287 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1288 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001289
1290 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1291 statistics_proxy_->GetStats().quality_limitation_reason);
1292}
1293
1294TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001295 VideoAdaptationCounters cpu_counts;
1296 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001297
1298 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1299 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001300 cpu_counts.resolution_adaptations = 1;
1301 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001302 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1303 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001304 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001305 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001306 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1307 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001308
1309 EXPECT_EQ(QualityLimitationReason::kNone,
1310 statistics_proxy_->GetStats().quality_limitation_reason);
1311}
1312
1313TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001314 VideoAdaptationCounters cpu_counts;
1315 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001316
Evan Shrubsoledff79252020-04-16 11:34:32 +02001317 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001318 // Not limited for 3000 ms
1319 fake_clock_.AdvanceTimeMilliseconds(3000);
1320 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001321 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001322 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1323 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001324 fake_clock_.AdvanceTimeMilliseconds(2000);
1325 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001326 cpu_counts.resolution_adaptations = 0;
1327 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001328 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1329 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001330 fake_clock_.AdvanceTimeMilliseconds(1000);
1331 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001332 cpu_counts.resolution_adaptations = 1;
1333 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001334 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1335 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001336 fake_clock_.AdvanceTimeMilliseconds(2000);
1337
1338 auto quality_limitation_durations_ms =
1339 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1340
1341 EXPECT_EQ(3000,
1342 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1343 EXPECT_EQ(4000,
1344 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1345 EXPECT_EQ(
1346 1000,
1347 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1348 EXPECT_EQ(0,
1349 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1350}
1351
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001352TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1353 EXPECT_EQ(
1354 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1355}
1356
1357TEST_F(SendStatisticsProxyTest,
1358 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1359 VideoCodec codec;
1360 VideoBitrateAllocation allocation;
1361 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1362 EXPECT_EQ(
1363 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1364}
1365
1366TEST_F(SendStatisticsProxyTest,
1367 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1368 VideoCodec codec;
1369 codec.simulcastStream[0].active = true;
1370 codec.simulcastStream[1].active = true;
1371 codec.simulcastStream[2].active = true;
1372 VideoBitrateAllocation allocation;
1373 allocation.SetBitrate(0, 0, 100);
1374 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1375 EXPECT_EQ(
1376 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1377}
1378
1379TEST_F(SendStatisticsProxyTest,
1380 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1381 VideoCodec codec;
1382 codec.simulcastStream[0].active = true;
1383 codec.simulcastStream[1].active = true;
1384 codec.simulcastStream[2].active = true;
1385 VideoBitrateAllocation allocation;
1386 allocation.SetBitrate(0, 0, 100);
1387 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1388 allocation.SetBitrate(1, 0, 100);
1389 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1390 EXPECT_EQ(
1391 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1392}
1393
1394TEST_F(SendStatisticsProxyTest,
1395 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1396 VideoCodec codec;
1397 codec.simulcastStream[0].active = true;
1398 VideoBitrateAllocation allocation;
1399 allocation.SetBitrate(0, 0, 100);
1400 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1401 // Layer 0 got more bandwidth, but still only one layer on
1402 allocation.SetBitrate(0, 0, 200);
1403 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1404 EXPECT_EQ(
1405 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1406}
1407
1408TEST_F(SendStatisticsProxyTest,
1409 QualityLimitationResolutionChangesWithTogglingLayers) {
1410 VideoCodec codec;
1411 codec.simulcastStream[0].active = true;
1412 codec.simulcastStream[1].active = true;
1413 codec.simulcastStream[2].active = true;
1414 VideoBitrateAllocation allocation;
1415 allocation.SetBitrate(0, 0, 100);
1416 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1417 EXPECT_EQ(
1418 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1419 allocation.SetBitrate(1, 0, 300);
1420 allocation.SetBitrate(2, 0, 500);
1421 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1422 EXPECT_EQ(
1423 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1424 // Layer 2 off
1425 allocation.SetBitrate(2, 0, 0);
1426 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1427 EXPECT_EQ(
1428 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1429 // Layer 2 back on
1430 allocation.SetBitrate(2, 0, 500);
1431 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1432 EXPECT_EQ(
1433 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1434 allocation.SetBitrate(0, 0, 0);
1435 allocation.SetBitrate(1, 0, 0);
1436 allocation.SetBitrate(2, 0, 0);
1437 // All layers off
1438 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1439 EXPECT_EQ(
1440 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1441}
1442
1443TEST_F(SendStatisticsProxyTest,
1444 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1445 VideoCodec codec;
1446 // 3 layers
1447 codec.simulcastStream[0].active = true;
1448 codec.simulcastStream[1].active = true;
1449 codec.simulcastStream[2].active = true;
1450 VideoBitrateAllocation allocation;
1451 allocation.SetBitrate(0, 0, 500);
1452 allocation.SetBitrate(1, 0, 500);
1453 allocation.SetBitrate(2, 0, 500);
1454 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1455 EXPECT_EQ(
1456 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1457
1458 // Down to one layer now, triggered by a config change
1459 codec.numberOfSimulcastStreams = 1;
1460 codec.simulcastStream[1].active = false;
1461 codec.simulcastStream[2].active = false;
1462 allocation.SetBitrate(0, 0, 100);
1463 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1464 EXPECT_EQ(
1465 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1466
1467 // Up to 3 layers again.
1468 codec.numberOfSimulcastStreams = 3;
1469 codec.simulcastStream[1].active = true;
1470 codec.simulcastStream[2].active = true;
1471 allocation.SetBitrate(0, 0, 500);
1472 allocation.SetBitrate(1, 0, 500);
1473 allocation.SetBitrate(2, 0, 500);
1474 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1475 EXPECT_EQ(
1476 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1477}
1478
1479TEST_F(SendStatisticsProxyTest,
1480 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1481 VideoCodec codec;
1482 codec.simulcastStream[0].active = true;
1483 codec.spatialLayers[0].active = true;
1484 codec.spatialLayers[1].active = true;
1485 codec.spatialLayers[2].active = true;
1486 VideoBitrateAllocation allocation;
1487 allocation.SetBitrate(0, 0, 500);
1488 allocation.SetBitrate(1, 0, 500);
1489 allocation.SetBitrate(2, 0, 500);
1490 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1491 EXPECT_EQ(
1492 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1493
1494 // Down to one layer now, triggered by a config change
1495 codec.spatialLayers[1].active = false;
1496 codec.spatialLayers[2].active = false;
1497 allocation.SetBitrate(0, 0, 100);
1498 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1499 EXPECT_EQ(
1500 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1501
1502 // Up to 3 layers again.
1503 codec.spatialLayers[1].active = true;
1504 codec.spatialLayers[2].active = true;
1505 allocation.SetBitrate(0, 0, 500);
1506 allocation.SetBitrate(1, 0, 500);
1507 allocation.SetBitrate(2, 0, 500);
1508 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1509 EXPECT_EQ(
1510 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1511}
1512
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001513TEST_F(SendStatisticsProxyTest,
1514 QualityLimitationReasonsAreCorrectForContentType) {
1515 // Realtime case.
1516 // Configure two streams.
1517 VideoEncoderConfig config;
1518 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1519 config.number_of_streams = 2;
1520 VideoStream stream1;
1521 stream1.width = kWidth / 2;
1522 stream1.height = kHeight / 2;
1523 VideoStream stream2;
1524 stream2.width = kWidth;
1525 stream2.height = kHeight;
1526 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1527 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1528 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1529 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1530 QualityLimitationReason::kNone);
1531 // Bw disabled one layer.
1532 VideoCodec codec;
1533 codec.numberOfSimulcastStreams = 2;
1534 codec.simulcastStream[0].active = true;
1535 codec.simulcastStream[1].active = true;
1536 VideoBitrateAllocation allocation;
1537 // Some positive bitrate only on the first stream.
1538 allocation.SetBitrate(0, 0, 10000);
1539 allocation.SetBitrate(1, 0, 0);
1540 allocation.set_bw_limited(true);
1541 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1542 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1543 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1544 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1545 QualityLimitationReason::kBandwidth);
1546 // Bw enabled all layers.
1547 allocation.SetBitrate(1, 0, 10000);
1548 allocation.set_bw_limited(false);
1549 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1550 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1551 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1552 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1553 QualityLimitationReason::kNone);
1554
1555 // Screencast case
1556 // Configure two streams.
1557 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1558 config.number_of_streams = 2;
1559 stream1.width = kWidth;
1560 stream1.height = kHeight;
1561 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1562 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1563 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1564 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1565 QualityLimitationReason::kNone);
1566 // Bw disabled one layer.
1567 // Some positive bitrate only on the second stream.
1568 allocation.SetBitrate(0, 0, 10000);
1569 allocation.SetBitrate(1, 0, 0);
1570 allocation.set_bw_limited(true);
1571 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1572 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1573 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1574 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1575 QualityLimitationReason::kBandwidth);
1576 // Bw enabled all layers.
1577 allocation.SetBitrate(1, 0, 10000);
1578 allocation.set_bw_limited(false);
1579 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1580 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1581 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1582 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1583 QualityLimitationReason::kNone);
1584}
1585
asapersson59bac1a2016-01-07 23:36:00 -08001586TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001587 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001588 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1589
Pera48ddb72016-09-29 11:48:50 +02001590 // No switch, stats should not be updated.
1591 VideoEncoderConfig config;
1592 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001593 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001594 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001595
1596 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001597 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001598 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001599 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001600}
1601
asapersson320e45a2016-11-29 01:40:35 -08001602TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1603 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1604 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001605
asapersson320e45a2016-11-29 01:40:35 -08001606 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001607 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1608 EXPECT_METRIC_EQ(
1609 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1610 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1611 EXPECT_METRIC_EQ(
1612 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001613}
1614
1615TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001616 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001617 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001618 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1619 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1620 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001621 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001622
1623 // Not enough samples, stats should not be updated.
1624 for (int i = 0; i < kMinSamples - 1; ++i) {
1625 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001626 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001627 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1628 }
Åsa Persson0122e842017-10-16 12:19:23 +02001629 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001630 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1631 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001632
1633 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001634 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001635 for (int i = 0; i < kMinSamples; ++i) {
1636 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001637 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001638 encoded_image._encodedWidth = kWidth;
1639 encoded_image._encodedHeight = kHeight;
1640 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1641 encoded_image._encodedWidth = kWidth / 2;
1642 encoded_image._encodedHeight = kHeight / 2;
1643 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1644 }
1645
asapersson320e45a2016-11-29 01:40:35 -08001646 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001647 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1648 EXPECT_METRIC_EQ(
1649 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1650 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1651 EXPECT_METRIC_EQ(
1652 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001653}
1654
1655TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1656 const int kFps = 20;
1657 const int kMinPeriodicSamples = 6;
1658 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1659 for (int i = 0; i <= frames; ++i) {
1660 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1661 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1662 }
1663 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001664 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1665 EXPECT_METRIC_EQ(
1666 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001667}
1668
1669TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1670 EncodedImage encoded_image;
1671 const int kFps = 20;
1672 const int kMinPeriodicSamples = 6;
1673 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001674 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001675 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001676 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001677 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1678 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001679 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1680 }
1681 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001682 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1683 EXPECT_METRIC_EQ(
1684 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001685}
1686
1687TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1688 const int kFps = 20;
1689 const int kSuspendTimeMs = 10000;
1690 const int kMinPeriodicSamples = 6;
1691 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1692 for (int i = 0; i < frames; ++i) {
1693 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1694 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1695 }
1696 // Suspend.
1697 statistics_proxy_->OnSuspendChange(true);
1698 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1699
1700 for (int i = 0; i < frames; ++i) {
1701 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1702 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1703 }
1704 // Suspended time interval should not affect the framerate.
1705 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001706 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1707 EXPECT_METRIC_EQ(
1708 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001709}
1710
1711TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1712 EncodedImage encoded_image;
1713 const int kFps = 20;
1714 const int kSuspendTimeMs = 10000;
1715 const int kMinPeriodicSamples = 6;
1716 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001717 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001718 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001719 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001720 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1721 }
1722 // Suspend.
1723 statistics_proxy_->OnSuspendChange(true);
1724 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1725
Åsa Persson0122e842017-10-16 12:19:23 +02001726 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001727 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001728 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001729 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1730 }
1731 // Suspended time interval should not affect the framerate.
1732 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001733 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1734 EXPECT_METRIC_EQ(
1735 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001736}
1737
asaperssonf4e44af2017-04-19 02:01:06 -07001738TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001739 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1740 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001741
1742 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1743 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1744
1745 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001746 EXPECT_METRIC_EQ(
1747 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001748}
1749
1750TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001751 VideoAdaptationCounters cpu_counts;
1752 VideoAdaptationCounters quality_counts;
1753 cpu_counts.resolution_adaptations = 0;
1754 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001755
perkj803d97f2016-11-01 11:45:46 -07001756 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1757 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1758
Evan Shrubsoledff79252020-04-16 11:34:32 +02001759 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001760 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1761 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001762
1763 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1764 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1765
1766 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001767 EXPECT_METRIC_EQ(
1768 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1769 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001770 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1771}
1772
asapersson4374a092016-07-27 00:39:09 -07001773TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1774 const int64_t kTimeSec = 3;
1775 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1776 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001777 EXPECT_METRIC_EQ(
1778 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1779 EXPECT_METRIC_EQ(
1780 1,
1781 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001782}
1783
1784TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1785 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1786 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001787 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001788}
1789
asapersson66d4b372016-12-19 06:50:53 -08001790TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1791 // First RTP packet sent.
1792 UpdateDataCounters(kFirstSsrc);
1793
1794 // Min runtime has passed.
1795 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1796 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001797 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1798 EXPECT_METRIC_EQ(1,
1799 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001800}
1801
1802TEST_F(SendStatisticsProxyTest,
1803 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1804 // First RTP packet sent.
1805 UpdateDataCounters(kFirstSsrc);
1806
1807 // Min runtime has not passed.
1808 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1809 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001810 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1811 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001812}
1813
1814TEST_F(SendStatisticsProxyTest,
1815 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1816 // First RTP packet not sent.
1817 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1818 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001819 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001820}
1821
1822TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1823 // First RTP packet sent and min runtime passed.
1824 UpdateDataCounters(kFirstSsrc);
1825
1826 // No change. Video: 10000 ms, paused: 0 ms (0%).
1827 statistics_proxy_->OnSetEncoderTargetRate(50000);
1828 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1829 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1830
1831 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001832 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1833 EXPECT_METRIC_EQ(1,
1834 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1835 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1836 EXPECT_METRIC_EQ(1,
1837 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001838}
1839
1840TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1841 // First RTP packet sent and min runtime passed.
1842 UpdateDataCounters(kFirstSsrc);
1843
1844 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1845 statistics_proxy_->OnSetEncoderTargetRate(50000);
1846 fake_clock_.AdvanceTimeMilliseconds(7000);
1847 statistics_proxy_->OnSetEncoderTargetRate(0);
1848 fake_clock_.AdvanceTimeMilliseconds(3000);
1849 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1850
1851 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001852 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1853 EXPECT_METRIC_EQ(1,
1854 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1855 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1856 EXPECT_METRIC_EQ(1,
1857 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001858}
1859
1860TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1861 // First RTP packet sent.
1862 UpdateDataCounters(kFirstSsrc);
1863
1864 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1865 statistics_proxy_->OnSetEncoderTargetRate(0);
1866 fake_clock_.AdvanceTimeMilliseconds(1000);
1867 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1868 fake_clock_.AdvanceTimeMilliseconds(7000);
1869 statistics_proxy_->OnSetEncoderTargetRate(60000);
1870 fake_clock_.AdvanceTimeMilliseconds(3000);
1871 statistics_proxy_->OnSetEncoderTargetRate(0);
1872 fake_clock_.AdvanceTimeMilliseconds(250);
1873 statistics_proxy_->OnSetEncoderTargetRate(0);
1874 fake_clock_.AdvanceTimeMilliseconds(750);
1875 statistics_proxy_->OnSetEncoderTargetRate(60000);
1876 fake_clock_.AdvanceTimeMilliseconds(5000);
1877 statistics_proxy_->OnSetEncoderTargetRate(50000);
1878 fake_clock_.AdvanceTimeMilliseconds(4000);
1879 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1880
1881 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001882 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1883 EXPECT_METRIC_EQ(1,
1884 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1885 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1886 EXPECT_METRIC_EQ(1,
1887 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001888}
1889
1890TEST_F(SendStatisticsProxyTest,
1891 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1892 // First RTP packet sent.
1893 UpdateDataCounters(kFirstSsrc);
1894 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1895
1896 // Min runtime has not passed.
1897 statistics_proxy_->OnSetEncoderTargetRate(50000);
1898 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1899 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1900
1901 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001902 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001903}
1904
asapersson118ef002016-03-31 00:00:19 -07001905TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001906 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001907 CodecSpecificInfo codec_info;
1908 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001909
perkj803d97f2016-11-01 11:45:46 -07001910 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001911 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001912 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001913 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001914 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001915 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001916 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001917 }
1918 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001919 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1920 EXPECT_METRIC_EQ(
1921 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1922 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1923 EXPECT_METRIC_EQ(
1924 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001925}
1926
1927TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1928 VideoSendStream::Config config(nullptr);
1929 config.rtp.ssrcs.push_back(kFirstSsrc);
1930 statistics_proxy_.reset(new SendStatisticsProxy(
1931 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1932
asapersson118ef002016-03-31 00:00:19 -07001933 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001934 CodecSpecificInfo codec_info;
1935 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001936
perkj803d97f2016-11-01 11:45:46 -07001937 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001938 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001939 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001940 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001941 }
1942 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001943 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1944 EXPECT_METRIC_EQ(1,
1945 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001946}
1947
asapersson5265fed2016-04-18 02:58:47 -07001948TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001949 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001950 CodecSpecificInfo codec_info;
1951 codec_info.codecType = kVideoCodecVP9;
1952 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001953
perkj803d97f2016-11-01 11:45:46 -07001954 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001955 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001956 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001957 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001958 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001959 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001960 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001961 }
1962 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001963 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1964 EXPECT_METRIC_EQ(
1965 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1966 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1967 EXPECT_METRIC_EQ(
1968 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001969}
1970
1971TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1972 VideoSendStream::Config config(nullptr);
1973 config.rtp.ssrcs.push_back(kFirstSsrc);
1974 statistics_proxy_.reset(new SendStatisticsProxy(
1975 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1976
asapersson5265fed2016-04-18 02:58:47 -07001977 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001978 CodecSpecificInfo codec_info;
1979 codec_info.codecType = kVideoCodecVP9;
1980 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001981
perkj803d97f2016-11-01 11:45:46 -07001982 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001983 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001984 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001985 }
1986 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001987 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1988 EXPECT_METRIC_EQ(1,
1989 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001990}
1991
asapersson827cab32016-11-02 09:08:47 -07001992TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1993 EncodedImage encoded_image;
1994 CodecSpecificInfo codec_info;
1995 codec_info.codecType = kVideoCodecH264;
1996
1997 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001998 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001999 encoded_image.qp_ = kQpIdx0;
2000 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002001 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02002002 encoded_image.qp_ = kQpIdx1;
2003 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07002004 }
2005 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002006 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
2007 EXPECT_METRIC_EQ(
2008 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
2009 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
2010 EXPECT_METRIC_EQ(
2011 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07002012}
2013
asapersson4ee70462016-10-31 04:05:12 -07002014TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002015 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
2016 // Configure one stream.
2017 VideoEncoderConfig config;
2018 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2019 VideoStream stream1;
2020 stream1.width = kWidth;
2021 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002022 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002023
2024 const int64_t kMaxEncodedFrameWindowMs = 800;
2025 const int kFps = 20;
2026 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2027 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2028 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2029
2030 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002031 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002032 encoded_image._encodedWidth = kWidth;
2033 encoded_image._encodedHeight = kHeight;
2034 for (int i = 0; i < kMinSamples; ++i) {
2035 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002036 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2037 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002038 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002039 }
asapersson4ee70462016-10-31 04:05:12 -07002040
2041 // Histograms are updated when the statistics_proxy_ is deleted.
2042 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002043 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2044 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2045 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2046 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002047}
2048
2049TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002050 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
2051 // Configure two streams.
2052 VideoEncoderConfig config;
2053 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2054 VideoStream stream1;
2055 stream1.width = kWidth / 2;
2056 stream1.height = kHeight / 2;
2057 VideoStream stream2;
2058 stream2.width = kWidth;
2059 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002060 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002061
2062 const int64_t kMaxEncodedFrameWindowMs = 800;
2063 const int kFps = 20;
2064 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2065 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2066 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2067
2068 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07002069 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002070 for (int i = 0; i < kMinSamples; ++i) {
2071 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002072 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2073 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002074 encoded_image._encodedWidth = kWidth;
2075 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07002076 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002077 encoded_image._encodedWidth = kWidth / 2;
2078 encoded_image._encodedHeight = kHeight / 2;
2079 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2080 }
asapersson4ee70462016-10-31 04:05:12 -07002081
2082 // Histograms are updated when the statistics_proxy_ is deleted.
2083 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002084 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2085 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2086 EXPECT_METRIC_EQ(
2087 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2088 0));
asapersson4ee70462016-10-31 04:05:12 -07002089 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002090 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2091 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002092}
2093
2094TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002095 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2096 // Configure two streams.
2097 VideoEncoderConfig config;
2098 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2099 VideoStream stream1;
2100 stream1.width = kWidth / 2;
2101 stream1.height = kHeight / 2;
2102 VideoStream stream2;
2103 stream2.width = kWidth;
2104 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002105 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002106
2107 const int64_t kMaxEncodedFrameWindowMs = 800;
2108 const int kFps = 20;
2109 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2110 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2111 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2112
2113 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002114 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002115 encoded_image._encodedWidth = kWidth / 2;
2116 encoded_image._encodedHeight = kHeight / 2;
2117 for (int i = 0; i < kMinSamples; ++i) {
2118 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002119 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2120 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002121 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002122 }
asapersson4ee70462016-10-31 04:05:12 -07002123
2124 // Histograms are updated when the statistics_proxy_ is deleted.
2125 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002126 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2127 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2128 EXPECT_METRIC_EQ(
2129 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2130 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002131 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002132 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2133 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2134 EXPECT_METRIC_EQ(
2135 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2136 1));
asapersson4ee70462016-10-31 04:05:12 -07002137}
2138
2139TEST_F(SendStatisticsProxyTest,
2140 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002141 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2142 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002143 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002144 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002145 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002146 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002147
2148 // Histograms are updated when the statistics_proxy_ is deleted.
2149 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002150 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002151 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002152 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2153 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002154}
2155
2156TEST_F(SendStatisticsProxyTest,
2157 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002158 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002159 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002160 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002161 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002162 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002163
2164 // Histograms are updated when the statistics_proxy_ is deleted.
2165 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002166 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002167 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002168 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2169 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002170 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002171 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2172 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002173}
2174
2175TEST_F(SendStatisticsProxyTest,
2176 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2177 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002178 VideoAdaptationCounters cpu_counts;
2179 VideoAdaptationCounters quality_counts;
2180 quality_counts.resolution_adaptations = kDownscales;
2181 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002182 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2183 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002184 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002185 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002186 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002187 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002188 // Histograms are updated when the statistics_proxy_ is deleted.
2189 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002190 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002191 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002192 EXPECT_METRIC_EQ(
2193 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2194 100));
asapersson4ee70462016-10-31 04:05:12 -07002195 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002196 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2197 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2198 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002199 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2200 kDownscales));
2201}
2202
2203TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2204 // Initially false.
2205 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002206
Åsa Perssonaa329e72017-12-15 15:54:44 +01002207 // Configure two streams.
2208 VideoEncoderConfig config;
2209 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002210 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002211 VideoStream stream1;
2212 stream1.width = kWidth / 2;
2213 stream1.height = kHeight / 2;
2214 VideoStream stream2;
2215 stream2.width = kWidth;
2216 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002217 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002218
Åsa Perssonaa329e72017-12-15 15:54:44 +01002219 // One stream encoded.
2220 EncodedImage encoded_image;
2221 encoded_image._encodedWidth = kWidth / 2;
2222 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002223
2224 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002225 VideoAdaptationCounters cpu_counts;
2226 VideoAdaptationCounters quality_counts;
2227 quality_counts.resolution_adaptations = 1;
2228 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2229 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002230 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2231 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002232 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2233 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002234
2235 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002236 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002237 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2238 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002239 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2240 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2241
2242 // Bw disabled one layer.
2243 VideoCodec codec;
2244 codec.numberOfSimulcastStreams = 2;
2245 codec.simulcastStream[0].active = true;
2246 codec.simulcastStream[1].active = true;
2247 VideoBitrateAllocation allocation;
2248 // Some positive bitrate only on the second stream.
2249 allocation.SetBitrate(1, 0, 10000);
2250 allocation.set_bw_limited(true);
2251 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2252 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002253
2254 // Revert for the next test.
2255 allocation.set_bw_limited(false);
2256 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2257 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2258
2259 // Internal encoder scaler reduced resolution.
2260 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2261 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002262}
2263
asapersson66d4b372016-12-19 06:50:53 -08002264TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2265 // Initially zero.
2266 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2267
2268 const int kBitrate = 100000;
2269 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2270 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2271
2272 statistics_proxy_->OnSetEncoderTargetRate(0);
2273 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2274}
2275
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002276TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002277 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002278 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2279 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002280 1;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002281 // From ReportBlockDataObserver.
2282 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2283 RTCPReportBlock report_block;
2284 report_block.source_ssrc = excluded_ssrc;
2285 ReportBlockData data;
2286 data.SetReportBlock(report_block, 0);
2287 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002288
2289 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002290 uint32_t total = 0;
2291 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002292 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002293 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002294
2295 // From FrameCountObserver.
2296 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002297 FrameCounts frame_counts;
2298 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002299 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002300
2301 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2302 EXPECT_TRUE(stats.substreams.empty());
2303}
2304
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002305TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2306 static const int kEncodedWidth = 123;
2307 static const int kEncodedHeight = 81;
2308 EncodedImage encoded_image;
2309 encoded_image._encodedWidth = kEncodedWidth;
2310 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002311 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002312
kjellander02b3d272016-04-20 05:05:54 -07002313 CodecSpecificInfo codec_info;
2314 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002315
kjellander02b3d272016-04-20 05:05:54 -07002316 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002317 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002318 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002319
2320 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002321 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2322 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2323 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2324 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002325
2326 // Forward almost to timeout, this should not have removed stats.
2327 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2328 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002329 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2330 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002331
2332 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2333 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002334 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2335 RTCPReportBlock report_block;
2336 report_block.source_ssrc = config_.rtp.ssrcs[0];
2337 ReportBlockData data;
2338 data.SetReportBlock(report_block, 0);
2339 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002340
2341 // Report stats for second SSRC to make sure it's not outdated along with the
2342 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002343 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002344
2345 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2346 // reported, but substream 1 should.
2347 fake_clock_.AdvanceTimeMilliseconds(1);
2348 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002349 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2350 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2351 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2352 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002353}
2354
Peter Boström20f3f942015-05-15 11:33:39 +02002355TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2356 static const int kEncodedWidth = 123;
2357 static const int kEncodedHeight = 81;
2358 EncodedImage encoded_image;
2359 encoded_image._encodedWidth = kEncodedWidth;
2360 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002361 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002362
kjellander02b3d272016-04-20 05:05:54 -07002363 CodecSpecificInfo codec_info;
2364 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002365
kjellander02b3d272016-04-20 05:05:54 -07002366 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002367 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002368 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002369
2370 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2371 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2372 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2373 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2374 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2375 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2376}
2377
2378TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002379 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002380 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2381 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2382 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2383
2384 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2385
2386 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002387 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002388 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002389 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002390 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2391 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2392 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2393}
2394
sprang07fb9be2016-02-24 07:55:00 -08002395TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2396 RtcpPacketTypeCounterObserver* proxy =
2397 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2398 RtcpPacketTypeCounter counters;
2399 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2400 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2401 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2402
2403 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2404
2405 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2406 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2407 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2408 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2409 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2410
2411 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2412 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2413
2414 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002415 VideoEncoderConfig config;
2416 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002417 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002418
Ying Wangef3998f2019-12-09 13:06:53 +01002419 EXPECT_METRIC_EQ(
2420 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2421 EXPECT_METRIC_EQ(
2422 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2423 EXPECT_METRIC_EQ(
2424 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2425 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2426 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002427
2428 const int kRate = 60 * 2; // Packets per minute with two streams.
2429
Ying Wangef3998f2019-12-09 13:06:53 +01002430 EXPECT_METRIC_EQ(
2431 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2432 1 * kRate));
2433 EXPECT_METRIC_EQ(
2434 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2435 2 * kRate));
2436 EXPECT_METRIC_EQ(
2437 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2438 3 * kRate));
2439 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002440 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2441 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002442
2443 // New start time but same counter values.
2444 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2445 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2446
2447 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2448
2449 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2450 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2451 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2452 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2453 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2454
2455 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2456 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2457
2458 SetUp(); // Reset stats proxy also causes histograms to be reported.
2459
Ying Wangef3998f2019-12-09 13:06:53 +01002460 EXPECT_METRIC_EQ(
2461 1, metrics::NumSamples(
2462 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2463 EXPECT_METRIC_EQ(1,
2464 metrics::NumSamples(
2465 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2466 EXPECT_METRIC_EQ(1,
2467 metrics::NumSamples(
2468 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2469 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002470 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002471 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2472
Ying Wangef3998f2019-12-09 13:06:53 +01002473 EXPECT_METRIC_EQ(
2474 1,
2475 metrics::NumEvents(
2476 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2477 EXPECT_METRIC_EQ(
2478 1,
2479 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2480 2 * kRate));
2481 EXPECT_METRIC_EQ(
2482 1,
2483 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2484 3 * kRate));
2485 EXPECT_METRIC_EQ(
2486 1, metrics::NumEvents(
2487 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2488 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002489}
2490
Henrik Boströmf45ca372020-03-24 13:30:50 +01002491TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2492 StreamDataCountersCallback* proxy =
2493 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2494 StreamDataCounters counters;
2495 proxy->DataCountersUpdated(counters, kFirstSsrc);
2496 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2497
2498 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2499 VideoSendStream::StreamStats::StreamType::kRtx);
2500 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2501 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2502 VideoSendStream::StreamStats::StreamType::kRtx);
2503 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2504}
2505
asaperssona6a699a2016-11-25 03:52:46 -08002506TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2507 statistics_proxy_.reset(
2508 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2509 VideoEncoderConfig::ContentType::kRealtimeVideo));
2510
2511 StreamDataCountersCallback* proxy =
2512 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2513 StreamDataCounters counters;
2514 proxy->DataCountersUpdated(counters, kFirstSsrc);
2515 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2516
Henrik Boströmf45ca372020-03-24 13:30:50 +01002517 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2518 VideoSendStream::StreamStats::StreamType::kFlexfec);
2519 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2520 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2521 VideoSendStream::StreamStats::StreamType::kFlexfec);
2522 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002523}
2524
2525TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2526 statistics_proxy_.reset(
2527 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2528 VideoEncoderConfig::ContentType::kRealtimeVideo));
2529
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) {
2733 VideoSendStream::Config config(nullptr);
2734 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2735 statistics_proxy_.reset(new SendStatisticsProxy(
2736 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2737
2738 StreamDataCountersCallback* proxy =
2739 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2740 StreamDataCounters counters;
2741
2742 const int kMinRequiredPeriodSamples = 8;
2743 const int kPeriodIntervalMs = 2000;
2744 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2745 counters.transmitted.packets += 20;
2746 counters.transmitted.header_bytes += 500;
2747 counters.transmitted.payload_bytes += 2000;
2748 counters.fec = counters.retransmitted;
2749 // Advance one interval and update counters.
2750 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2751 proxy->DataCountersUpdated(counters, kFirstSsrc);
2752 }
2753
2754 // RTX not enabled.
2755 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002756 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002757}
2758
2759TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2760 StreamDataCountersCallback* proxy =
2761 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2762 StreamDataCounters counters;
2763 StreamDataCounters rtx_counters;
2764
2765 const int kMinRequiredPeriodSamples = 8;
2766 const int kPeriodIntervalMs = 2000;
2767 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2768 counters.transmitted.packets += 20;
2769 counters.transmitted.header_bytes += 500;
2770 counters.transmitted.payload_bytes += 2000;
2771 // Advance one interval and update counters.
2772 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2773 proxy->DataCountersUpdated(counters, kFirstSsrc);
2774 }
2775
2776 // FEC enabled. No FEC data sent.
2777 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002778 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2779 EXPECT_METRIC_EQ(1,
2780 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002781}
2782
2783TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2784 VideoSendStream::Config config(nullptr);
2785 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2786 statistics_proxy_.reset(new SendStatisticsProxy(
2787 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2788
2789 StreamDataCountersCallback* proxy =
2790 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2791 StreamDataCounters counters;
2792
2793 const int kMinRequiredPeriodSamples = 8;
2794 const int kPeriodIntervalMs = 2000;
2795 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2796 counters.transmitted.packets += 20;
2797 counters.transmitted.header_bytes += 500;
2798 counters.transmitted.payload_bytes += 2000;
2799 counters.fec = counters.retransmitted;
2800 // Advance one interval and update counters.
2801 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2802 proxy->DataCountersUpdated(counters, kFirstSsrc);
2803 }
2804
2805 // FEC not enabled.
2806 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002807 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002808}
2809
asapersson8d75ac72017-09-15 06:41:15 -07002810TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002811 const std::string kName = "encoderName";
2812 statistics_proxy_->OnEncoderImplementationChanged(kName);
2813 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002814}
2815
Sergey Silkinbb081a62018-09-04 18:34:22 +02002816TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2817 static const int kEncodedWidth = 123;
2818 static const int kEncodedHeight = 81;
2819 EncodedImage encoded_image;
2820 encoded_image._encodedWidth = kEncodedWidth;
2821 encoded_image._encodedHeight = kEncodedHeight;
2822 encoded_image.SetSpatialIndex(0);
2823
2824 CodecSpecificInfo codec_info;
2825 codec_info.codecType = kVideoCodecVP9;
2826
2827 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002828 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002829 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2830 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2831 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2832 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2833
2834 // Top layer updates resolution.
2835 encoded_image._encodedWidth = kEncodedWidth * 2;
2836 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002837 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002838 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2839 stats = statistics_proxy_->GetStats();
2840 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2841 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2842
2843 // Low layer of next frame doesn't update resolution.
2844 encoded_image._encodedWidth = kEncodedWidth;
2845 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002846 codec_info.end_of_picture = false;
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
asapersson8d75ac72017-09-15 06:41:15 -07002853class ForcedFallbackTest : public SendStatisticsProxyTest {
2854 public:
2855 explicit ForcedFallbackTest(const std::string& field_trials)
2856 : SendStatisticsProxyTest(field_trials) {
2857 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002858 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002859 encoded_image_._encodedWidth = kWidth;
2860 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002861 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002862 }
2863
2864 ~ForcedFallbackTest() override {}
2865
2866 protected:
2867 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002868 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2869
asapersson8d75ac72017-09-15 06:41:15 -07002870 // First frame is not updating stats, insert initial frame.
2871 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2872 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2873 }
2874 for (int i = 0; i < num_frames; ++i) {
2875 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2876 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2877 }
2878 // Add frame to include last time interval.
2879 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2880 }
2881
2882 EncodedImage encoded_image_;
2883 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002884 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002885 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2886 const int kFrameIntervalMs = 1000;
2887 const int kMinFrames = 20; // Min run time 20 sec.
2888};
2889
2890class ForcedFallbackDisabled : public ForcedFallbackTest {
2891 public:
2892 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002893 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2894 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002895};
2896
2897class ForcedFallbackEnabled : public ForcedFallbackTest {
2898 public:
2899 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002900 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2901 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002902};
2903
2904TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2905 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2906 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002907 EXPECT_METRIC_EQ(0,
2908 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2909 EXPECT_METRIC_EQ(
2910 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002911}
2912
2913TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2914 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002915 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002916 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002917 EXPECT_METRIC_EQ(1,
2918 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2919 EXPECT_METRIC_EQ(
2920 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2921 EXPECT_METRIC_EQ(
2922 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2923 EXPECT_METRIC_EQ(
2924 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002925}
2926
2927TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2928 codec_info_.codecType = kVideoCodecVP9;
2929 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2930 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002931 EXPECT_METRIC_EQ(0,
2932 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2933 EXPECT_METRIC_EQ(
2934 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002935}
2936
2937TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2938 codec_info_.codecSpecific.VP8.temporalIdx = 1;
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, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002948 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002949 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(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2958 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2959 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002960 EXPECT_METRIC_EQ(0,
2961 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2962 EXPECT_METRIC_EQ(
2963 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002964}
2965
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002966TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2967 InsertEncodedFrames(1, kFrameIntervalMs);
2968 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2969}
2970
2971TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2972 InsertEncodedFrames(1, kFrameIntervalMs);
2973 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2974}
2975
2976TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002977 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002978 InsertEncodedFrames(1, kFrameIntervalMs);
2979 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2980}
2981
2982TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2983 encoded_image_._encodedWidth = kWidth + 1;
2984 InsertEncodedFrames(1, kFrameIntervalMs);
2985 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2986}
2987
2988TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002989 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002990 InsertEncodedFrames(1, kFrameIntervalMs);
2991 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2992}
2993
2994TEST_F(ForcedFallbackDisabled,
2995 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2996 encoded_image_._encodedWidth = kWidth + 1;
2997 statistics_proxy_->OnMinPixelLimitReached();
2998 InsertEncodedFrames(1, kFrameIntervalMs);
2999 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3000}
3001
asapersson8d75ac72017-09-15 06:41:15 -07003002TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
3003 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003004 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003005 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003006 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003007 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003008 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003009 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003010
3011 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003012 EXPECT_METRIC_EQ(1,
3013 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3014 EXPECT_METRIC_EQ(
3015 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3016 EXPECT_METRIC_EQ(
3017 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3018 EXPECT_METRIC_EQ(
3019 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003020}
3021
3022TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
3023 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
3024 const int kMaxFrameDiffMs = 2000;
3025
3026 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
3027 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003028 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003029 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003030 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003031 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003032 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003033 InsertEncodedFrames(20, 1000);
3034 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
3035 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003036 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003037 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07003038 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003039 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003040 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003041 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003042 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003043
3044 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003045 EXPECT_METRIC_EQ(1,
3046 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3047 EXPECT_METRIC_EQ(
3048 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3049 EXPECT_METRIC_EQ(
3050 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3051 EXPECT_METRIC_EQ(
3052 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003053}
3054
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003055TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
3056 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003057 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003058 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3059
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003060 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003061 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003062 EXPECT_METRIC_EQ(0,
3063 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3064 EXPECT_METRIC_EQ(
3065 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003066}
3067
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003068TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
3069 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003070 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003071 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3072
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003073 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003074 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003075 EXPECT_METRIC_EQ(1,
3076 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3077 EXPECT_METRIC_EQ(
3078 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003079}
3080
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00003081} // namespace webrtc