blob: d4a7a49e39165ef525db83e9ef8a4ca140c8e983 [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
414 // increment by a full |kTargetBytesPerSecond|.
415 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
425 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
426 // 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
450 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
451 // 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;
459 auto ssrc = config_.rtp.ssrcs[0];
460 rtc::ScopedFakeClock fake_global_clock;
461 fake_global_clock.SetTime(
462 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
463
464 EncodedImage encoded_image;
465
466 // First frame
467 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
468 // Second frame
469 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
470 fake_global_clock.SetTime(
471 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
472 encoded_image.SetTimestamp(encoded_image.Timestamp() +
473 90 * kInterframeDelayMs);
474 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
475
476 auto stats = statistics_proxy_->GetStats();
477 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
478}
479
asapersson09f05612017-05-15 23:40:18 -0700480TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200481 VideoAdaptationCounters cpu_counts;
482 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700483 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700484 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200485 cpu_counts.fps_adaptations = 1;
486 cpu_counts.resolution_adaptations = 0;
487 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200488 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
489 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700490 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700491 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200492 cpu_counts.fps_adaptations = 0;
493 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200494 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
495 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700496 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700497 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200498 cpu_counts.fps_adaptations = 1;
499 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
500 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200501 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
502 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700503 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700504 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200505 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
506 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200507 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
508 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700509 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
510 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
511}
512
513TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200514 VideoAdaptationCounters cpu_counts;
515 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700516 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
517 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200518 quality_counts.fps_adaptations = 1;
519 quality_counts.resolution_adaptations = 0;
520 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200521 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
522 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700523 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
524 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200525 quality_counts.fps_adaptations = 0;
526 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200527 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
528 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700529 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
530 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200531 quality_counts.fps_adaptations = 1;
532 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
533 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200534 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
535 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700536 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
537 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200538 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
539 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200540 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
541 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700542 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
543 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
544}
545
546TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200547 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
548 VideoAdaptationCounters cpu_counts;
549 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700550 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
551
Evan Shrubsoledff79252020-04-16 11:34:32 +0200552 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200553 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
554 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700555 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700556 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
557 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
558
Evan Shrubsoledff79252020-04-16 11:34:32 +0200559 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200560 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
561 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700562 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
563 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700564 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700565 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700566}
567
asapersson09f05612017-05-15 23:40:18 -0700568TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200569 VideoAdaptationCounters cpu_counts;
570 VideoAdaptationCounters quality_counts;
571 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700572 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
573
Evan Shrubsoledff79252020-04-16 11:34:32 +0200574 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200575 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
576 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700577 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
578 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700579 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
580
Evan Shrubsoledff79252020-04-16 11:34:32 +0200581 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200582 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
583 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700584 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700585 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700586 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
587 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700588}
589
Evan Shrubsoledff79252020-04-16 11:34:32 +0200590TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
591 VideoAdaptationCounters cpu_counts;
592 VideoAdaptationCounters quality_counts;
593 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
594 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
595 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
596
597 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200598 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
599 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200600 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200601 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
602 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200603 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200604 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
605 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200606 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200607 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
608 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200609 // We have 1 fps and resolution reduction for both cpu and quality
610 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
611 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
612 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
613 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
614 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
615 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
616
617 // Disable quality scaling. Expect quality scaling not limited.
618 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
619 kScalingDisabled);
620 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
621 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
622 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
623 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
624 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
625 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
626
627 // Disable framerate scaling.
628 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
629 kFramerateScalingDisabled);
630 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
631 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
632 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
633 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
634 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
635 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
636
637 // Disable resolution scaling.
638 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
639 kResolutionScalingDisabled);
640 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
641 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
642 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
643 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
644 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
645 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
646
647 // Enable all
648 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
649 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
650 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
651 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
652 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
653 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
654 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
655}
656
asapersson09f05612017-05-15 23:40:18 -0700657TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700658 // First RTP packet sent.
659 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700660 // Min runtime has passed.
661 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
662 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100663 EXPECT_METRIC_EQ(
664 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
665 EXPECT_METRIC_EQ(
666 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700667}
668
669TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700670 // First RTP packet sent.
671 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700672 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200673 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700674 // Min runtime has not passed.
675 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
676 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100677 EXPECT_METRIC_EQ(
678 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
679 EXPECT_METRIC_EQ(
680 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700681}
682
asapersson09f05612017-05-15 23:40:18 -0700683TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700684 // First RTP packet sent.
685 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700686 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200687 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700688 // Min runtime has passed.
689 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
690 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100691 EXPECT_METRIC_EQ(
692 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
693 EXPECT_METRIC_EQ(
694 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
695 EXPECT_METRIC_EQ(
696 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
697 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700698 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
699}
700
701TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700702 // First RTP packet sent.
703 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700704 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200705 VideoAdaptationCounters cpu_counts;
706 VideoAdaptationCounters quality_counts;
707 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700708 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200709 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
710 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700711 fake_clock_.AdvanceTimeMilliseconds(10000);
712 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100713 EXPECT_METRIC_EQ(
714 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
715 EXPECT_METRIC_EQ(
716 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700717}
718
Åsa Persson875841d2018-01-08 08:49:53 +0100719TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
720 // First RTP packet sent.
721 UpdateDataCounters(kFirstSsrc);
722 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200723 VideoAdaptationCounters cpu_counts;
724 VideoAdaptationCounters quality_counts;
725 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100726 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200727 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
728 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100729 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
730 fake_clock_.AdvanceTimeMilliseconds(10000);
731 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100732 EXPECT_METRIC_EQ(
733 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
734 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100735 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
736}
737
738TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
739 // First RTP packet sent.
740 UpdateDataCounters(kFirstSsrc);
741 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200742 VideoAdaptationCounters cpu_counts;
743 VideoAdaptationCounters quality_counts;
744 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100745 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200746 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200747 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
748 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100749 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200750 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200751 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
752 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100753 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200754 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200755 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
756 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100757 fake_clock_.AdvanceTimeMilliseconds(10000);
758 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100759 EXPECT_METRIC_EQ(
760 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
761 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100762 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
763}
764
765TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
766 // First RTP packet sent.
767 UpdateDataCounters(kFirstSsrc);
768 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200769 VideoAdaptationCounters cpu_counts;
770 VideoAdaptationCounters quality_counts;
771 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100772 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200773 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
774 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100775 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
776 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
777 fake_clock_.AdvanceTimeMilliseconds(10000);
778 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100779 EXPECT_METRIC_EQ(
780 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
781 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100782 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
783}
784
785TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
786 // First RTP packet sent.
787 UpdateDataCounters(kFirstSsrc);
788 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200789 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
790 VideoAdaptationCounters cpu_counts;
791 VideoAdaptationCounters quality_counts;
792 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100793 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200794 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200795 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
796 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100797 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200798 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200799 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
800 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100801 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200802 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200803 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
804 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200805 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200806 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
807 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200808 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200809 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
810 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200811 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200812 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
813 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200814 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200815 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
816 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200817 quality_counts.resolution_adaptations = 0;
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
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", 24));
827}
828
asapersson6eca98b2017-04-04 23:40:50 -0700829TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700830 // First RTP packet sent.
831 UpdateDataCounters(kFirstSsrc);
832
asapersson09f05612017-05-15 23:40:18 -0700833 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200834 VideoAdaptationCounters cpu_counts;
835 VideoAdaptationCounters quality_counts;
836 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
837 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700838 fake_clock_.AdvanceTimeMilliseconds(10000);
839
asapersson09f05612017-05-15 23:40:18 -0700840 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700841 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200842 quality_counts.fps_adaptations = 0;
843 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
844 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700845 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200846 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
847 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700848 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200849 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
850 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700851 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200852 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
853 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700854
asapersson09f05612017-05-15 23:40:18 -0700855 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200856 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
857 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700858 fake_clock_.AdvanceTimeMilliseconds(30000);
859
asapersson09f05612017-05-15 23:40:18 -0700860 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700861 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200862 quality_counts.resolution_adaptations = 0;
863 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
864 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200865 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
866 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700867 fake_clock_.AdvanceTimeMilliseconds(10000);
868
asapersson09f05612017-05-15 23:40:18 -0700869 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200870 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
871 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700872 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200873 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
874 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700875 fake_clock_.AdvanceTimeMilliseconds(20000);
876
asapersson0944a802017-04-07 00:57:58 -0700877 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700878 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100879 EXPECT_METRIC_EQ(
880 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
881 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700882 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
883}
884
asapersson0944a802017-04-07 00:57:58 -0700885TEST_F(SendStatisticsProxyTest,
886 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
887 // First RTP packet sent.
888 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700889
asapersson0944a802017-04-07 00:57:58 -0700890 // Suspend and resume video.
891 statistics_proxy_->OnSuspendChange(true);
892 fake_clock_.AdvanceTimeMilliseconds(5000);
893 statistics_proxy_->OnSuspendChange(false);
894
895 // Min runtime has passed but scaling not enabled.
896 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
897 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100898 EXPECT_METRIC_EQ(
899 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
900 EXPECT_METRIC_EQ(
901 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700902}
903
904TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
905 // First RTP packet sent.
906 UpdateDataCounters(kFirstSsrc);
907
asapersson09f05612017-05-15 23:40:18 -0700908 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200909 VideoAdaptationCounters cpu_counts;
910 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700911 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200912 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700913 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200914 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
915 cpu_counts, quality_counts);
916 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
917 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700918
919 // Suspend and resume video.
920 statistics_proxy_->OnSuspendChange(true);
921 fake_clock_.AdvanceTimeMilliseconds(30000);
922 statistics_proxy_->OnSuspendChange(false);
923
924 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200925 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
926 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700927 fake_clock_.AdvanceTimeMilliseconds(10000);
928
929 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
930 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100931 EXPECT_METRIC_EQ(
932 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
933 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700934 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
935}
936
937TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
938 // First RTP packet sent.
939 UpdateDataCounters(kFirstSsrc);
940
941 // Video not suspended.
942 statistics_proxy_->OnSuspendChange(false);
943 fake_clock_.AdvanceTimeMilliseconds(30000);
944
asapersson09f05612017-05-15 23:40:18 -0700945 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200946 VideoAdaptationCounters cpu_counts;
947 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700948 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200949 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700950 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200951 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
952 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700953
954 // Video not suspended, stats time already started.
955 statistics_proxy_->OnSuspendChange(false);
956 fake_clock_.AdvanceTimeMilliseconds(10000);
957
asapersson09f05612017-05-15 23:40:18 -0700958 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200959 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
960 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -0700961 fake_clock_.AdvanceTimeMilliseconds(30000);
962
963 // Suspend and resume video, stats time not started when scaling not enabled.
964 statistics_proxy_->OnSuspendChange(true);
965 fake_clock_.AdvanceTimeMilliseconds(30000);
966 statistics_proxy_->OnSuspendChange(false);
967 fake_clock_.AdvanceTimeMilliseconds(30000);
968
asapersson09f05612017-05-15 23:40:18 -0700969 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700970 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200971 cpu_counts.fps_adaptations = 0;
972 cpu_counts.resolution_adaptations = 0;
973 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700974 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200975 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
976 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700977
978 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
979 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100980 EXPECT_METRIC_EQ(
981 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
982 EXPECT_METRIC_EQ(
983 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700984}
985
986TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
987 // First RTP packet sent.
988 UpdateDataCounters(kFirstSsrc);
989
990 // Video suspended.
991 statistics_proxy_->OnSuspendChange(true);
992
asapersson09f05612017-05-15 23:40:18 -0700993 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200994 VideoAdaptationCounters cpu_counts;
995 VideoAdaptationCounters quality_counts;
996 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700997 fake_clock_.AdvanceTimeMilliseconds(10000);
998
999 // Resume video, stats time started.
1000 // Adapt changes: 1, elapsed time: 10 sec.
1001 statistics_proxy_->OnSuspendChange(false);
1002 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001003 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1004 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001005
1006 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1007 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001008 EXPECT_METRIC_EQ(
1009 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1010 EXPECT_METRIC_EQ(
1011 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001012}
1013
1014TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001015 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001016 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001017 VideoAdaptationCounters cpu_counts;
1018 VideoAdaptationCounters quality_counts;
1019 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001020 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001021 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001022
asapersson0944a802017-04-07 00:57:58 -07001023 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001024 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001025 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1026 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001027 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001028
asapersson0944a802017-04-07 00:57:58 -07001029 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001030 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001031 EXPECT_METRIC_EQ(
1032 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1033 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001034 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1035}
1036
1037TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001038 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001039 VideoAdaptationCounters cpu_counts;
1040 VideoAdaptationCounters quality_counts;
1041 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001042 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001043 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1044 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001045
1046 // Send first packet, scaling disabled.
1047 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001048 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001049 fake_clock_.AdvanceTimeMilliseconds(60000);
1050
asapersson09f05612017-05-15 23:40:18 -07001051 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001052 cpu_counts.resolution_adaptations = 0;
1053 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1054 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001055 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001056 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001057
asapersson0944a802017-04-07 00:57:58 -07001058 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001059 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001060 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1061 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001062
asapersson0944a802017-04-07 00:57:58 -07001063 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001064 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001065 EXPECT_METRIC_EQ(
1066 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1067 EXPECT_METRIC_EQ(
1068 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001069}
1070
1071TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001072 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001073 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001074 VideoAdaptationCounters cpu_counts;
1075 VideoAdaptationCounters quality_counts;
1076 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1077 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001078
asapersson0944a802017-04-07 00:57:58 -07001079 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001080 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1081 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001082 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001083 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1084 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001085 fake_clock_.AdvanceTimeMilliseconds(9000);
1086
1087 // Switch content type, real-time stats should be updated.
1088 VideoEncoderConfig config;
1089 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001090 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001091 EXPECT_METRIC_EQ(
1092 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1093 EXPECT_METRIC_EQ(
1094 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1095 EXPECT_METRIC_EQ(
1096 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001097
asapersson0944a802017-04-07 00:57:58 -07001098 // First RTP packet sent, scaling enabled.
1099 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001100 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1101 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001102
asapersson0944a802017-04-07 00:57:58 -07001103 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001104 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1105 cpu_counts, quality_counts);
1106 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1107 cpu_counts, quality_counts);
1108 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1109 cpu_counts, quality_counts);
1110 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1111 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001112 fake_clock_.AdvanceTimeMilliseconds(120000);
1113
1114 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001115 EXPECT_METRIC_EQ(1,
1116 metrics::NumSamples(
1117 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1118 EXPECT_METRIC_EQ(
1119 1, metrics::NumEvents(
1120 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1121 EXPECT_METRIC_EQ(
1122 0, metrics::NumSamples(
1123 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001124}
1125
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001126TEST_F(SendStatisticsProxyTest,
1127 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001128 VideoAdaptationCounters cpu_counts;
1129 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001130
Evan Shrubsoledff79252020-04-16 11:34:32 +02001131 cpu_counts.resolution_adaptations = 1;
1132 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001133 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1134 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001135
1136 EXPECT_EQ(QualityLimitationReason::kCpu,
1137 statistics_proxy_->GetStats().quality_limitation_reason);
1138}
1139
1140TEST_F(SendStatisticsProxyTest,
1141 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001142 VideoAdaptationCounters cpu_counts;
1143 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001144
Evan Shrubsoledff79252020-04-16 11:34:32 +02001145 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001146
Evan Shrubsoledff79252020-04-16 11:34:32 +02001147 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001148 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1149 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001150
1151 EXPECT_EQ(QualityLimitationReason::kCpu,
1152 statistics_proxy_->GetStats().quality_limitation_reason);
1153}
1154
1155TEST_F(SendStatisticsProxyTest,
1156 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001157 VideoAdaptationCounters cpu_counts;
1158 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001159
Evan Shrubsoledff79252020-04-16 11:34:32 +02001160 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001161
Evan Shrubsoledff79252020-04-16 11:34:32 +02001162 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001163 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1164 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001165
1166 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1167 statistics_proxy_->GetStats().quality_limitation_reason);
1168}
1169
1170TEST_F(SendStatisticsProxyTest,
1171 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001172 VideoAdaptationCounters cpu_counts;
1173 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001174
Evan Shrubsoledff79252020-04-16 11:34:32 +02001175 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001176
Evan Shrubsoledff79252020-04-16 11:34:32 +02001177 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001178 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1179 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001180
1181 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1182 statistics_proxy_->GetStats().quality_limitation_reason);
1183}
1184
1185TEST_F(SendStatisticsProxyTest,
1186 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001187 VideoAdaptationCounters cpu_counts;
1188 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001189
Evan Shrubsoledff79252020-04-16 11:34:32 +02001190 cpu_counts.resolution_adaptations = 1;
1191 quality_counts.resolution_adaptations = 1;
1192 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001193
1194 // Even if the last adaptation reason is kCpu, if the counters indicate being
1195 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001196 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1197 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001198
1199 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1200 statistics_proxy_->GetStats().quality_limitation_reason);
1201}
1202
1203TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001204 VideoAdaptationCounters cpu_counts;
1205 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001206
1207 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1208 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001209 cpu_counts.resolution_adaptations = 1;
1210 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001211 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1212 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001213 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001214 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001215 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1216 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001217
1218 EXPECT_EQ(QualityLimitationReason::kNone,
1219 statistics_proxy_->GetStats().quality_limitation_reason);
1220}
1221
1222TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001223 VideoAdaptationCounters cpu_counts;
1224 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001225
Evan Shrubsoledff79252020-04-16 11:34:32 +02001226 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001227 // Not limited for 3000 ms
1228 fake_clock_.AdvanceTimeMilliseconds(3000);
1229 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001230 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001231 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1232 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001233 fake_clock_.AdvanceTimeMilliseconds(2000);
1234 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001235 cpu_counts.resolution_adaptations = 0;
1236 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001237 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1238 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001239 fake_clock_.AdvanceTimeMilliseconds(1000);
1240 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001241 cpu_counts.resolution_adaptations = 1;
1242 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001243 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1244 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001245 fake_clock_.AdvanceTimeMilliseconds(2000);
1246
1247 auto quality_limitation_durations_ms =
1248 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1249
1250 EXPECT_EQ(3000,
1251 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1252 EXPECT_EQ(4000,
1253 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1254 EXPECT_EQ(
1255 1000,
1256 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1257 EXPECT_EQ(0,
1258 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1259}
1260
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001261TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1262 EXPECT_EQ(
1263 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1264}
1265
1266TEST_F(SendStatisticsProxyTest,
1267 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1268 VideoCodec codec;
1269 VideoBitrateAllocation allocation;
1270 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1271 EXPECT_EQ(
1272 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1273}
1274
1275TEST_F(SendStatisticsProxyTest,
1276 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1277 VideoCodec codec;
1278 codec.simulcastStream[0].active = true;
1279 codec.simulcastStream[1].active = true;
1280 codec.simulcastStream[2].active = true;
1281 VideoBitrateAllocation allocation;
1282 allocation.SetBitrate(0, 0, 100);
1283 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1284 EXPECT_EQ(
1285 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1286}
1287
1288TEST_F(SendStatisticsProxyTest,
1289 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1290 VideoCodec codec;
1291 codec.simulcastStream[0].active = true;
1292 codec.simulcastStream[1].active = true;
1293 codec.simulcastStream[2].active = true;
1294 VideoBitrateAllocation allocation;
1295 allocation.SetBitrate(0, 0, 100);
1296 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1297 allocation.SetBitrate(1, 0, 100);
1298 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1299 EXPECT_EQ(
1300 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1301}
1302
1303TEST_F(SendStatisticsProxyTest,
1304 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1305 VideoCodec codec;
1306 codec.simulcastStream[0].active = true;
1307 VideoBitrateAllocation allocation;
1308 allocation.SetBitrate(0, 0, 100);
1309 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1310 // Layer 0 got more bandwidth, but still only one layer on
1311 allocation.SetBitrate(0, 0, 200);
1312 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1313 EXPECT_EQ(
1314 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1315}
1316
1317TEST_F(SendStatisticsProxyTest,
1318 QualityLimitationResolutionChangesWithTogglingLayers) {
1319 VideoCodec codec;
1320 codec.simulcastStream[0].active = true;
1321 codec.simulcastStream[1].active = true;
1322 codec.simulcastStream[2].active = true;
1323 VideoBitrateAllocation allocation;
1324 allocation.SetBitrate(0, 0, 100);
1325 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1326 EXPECT_EQ(
1327 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1328 allocation.SetBitrate(1, 0, 300);
1329 allocation.SetBitrate(2, 0, 500);
1330 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1331 EXPECT_EQ(
1332 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1333 // Layer 2 off
1334 allocation.SetBitrate(2, 0, 0);
1335 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1336 EXPECT_EQ(
1337 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1338 // Layer 2 back on
1339 allocation.SetBitrate(2, 0, 500);
1340 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1341 EXPECT_EQ(
1342 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1343 allocation.SetBitrate(0, 0, 0);
1344 allocation.SetBitrate(1, 0, 0);
1345 allocation.SetBitrate(2, 0, 0);
1346 // All layers off
1347 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1348 EXPECT_EQ(
1349 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1350}
1351
1352TEST_F(SendStatisticsProxyTest,
1353 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1354 VideoCodec codec;
1355 // 3 layers
1356 codec.simulcastStream[0].active = true;
1357 codec.simulcastStream[1].active = true;
1358 codec.simulcastStream[2].active = true;
1359 VideoBitrateAllocation allocation;
1360 allocation.SetBitrate(0, 0, 500);
1361 allocation.SetBitrate(1, 0, 500);
1362 allocation.SetBitrate(2, 0, 500);
1363 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1364 EXPECT_EQ(
1365 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1366
1367 // Down to one layer now, triggered by a config change
1368 codec.numberOfSimulcastStreams = 1;
1369 codec.simulcastStream[1].active = false;
1370 codec.simulcastStream[2].active = false;
1371 allocation.SetBitrate(0, 0, 100);
1372 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1373 EXPECT_EQ(
1374 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1375
1376 // Up to 3 layers again.
1377 codec.numberOfSimulcastStreams = 3;
1378 codec.simulcastStream[1].active = true;
1379 codec.simulcastStream[2].active = true;
1380 allocation.SetBitrate(0, 0, 500);
1381 allocation.SetBitrate(1, 0, 500);
1382 allocation.SetBitrate(2, 0, 500);
1383 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1384 EXPECT_EQ(
1385 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1386}
1387
1388TEST_F(SendStatisticsProxyTest,
1389 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1390 VideoCodec codec;
1391 codec.simulcastStream[0].active = true;
1392 codec.spatialLayers[0].active = true;
1393 codec.spatialLayers[1].active = true;
1394 codec.spatialLayers[2].active = true;
1395 VideoBitrateAllocation allocation;
1396 allocation.SetBitrate(0, 0, 500);
1397 allocation.SetBitrate(1, 0, 500);
1398 allocation.SetBitrate(2, 0, 500);
1399 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1400 EXPECT_EQ(
1401 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1402
1403 // Down to one layer now, triggered by a config change
1404 codec.spatialLayers[1].active = false;
1405 codec.spatialLayers[2].active = false;
1406 allocation.SetBitrate(0, 0, 100);
1407 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1408 EXPECT_EQ(
1409 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1410
1411 // Up to 3 layers again.
1412 codec.spatialLayers[1].active = true;
1413 codec.spatialLayers[2].active = true;
1414 allocation.SetBitrate(0, 0, 500);
1415 allocation.SetBitrate(1, 0, 500);
1416 allocation.SetBitrate(2, 0, 500);
1417 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1418 EXPECT_EQ(
1419 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1420}
1421
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001422TEST_F(SendStatisticsProxyTest,
1423 QualityLimitationReasonsAreCorrectForContentType) {
1424 // Realtime case.
1425 // Configure two streams.
1426 VideoEncoderConfig config;
1427 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1428 config.number_of_streams = 2;
1429 VideoStream stream1;
1430 stream1.width = kWidth / 2;
1431 stream1.height = kHeight / 2;
1432 VideoStream stream2;
1433 stream2.width = kWidth;
1434 stream2.height = kHeight;
1435 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1436 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1437 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1438 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1439 QualityLimitationReason::kNone);
1440 // Bw disabled one layer.
1441 VideoCodec codec;
1442 codec.numberOfSimulcastStreams = 2;
1443 codec.simulcastStream[0].active = true;
1444 codec.simulcastStream[1].active = true;
1445 VideoBitrateAllocation allocation;
1446 // Some positive bitrate only on the first stream.
1447 allocation.SetBitrate(0, 0, 10000);
1448 allocation.SetBitrate(1, 0, 0);
1449 allocation.set_bw_limited(true);
1450 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1451 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1452 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1453 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1454 QualityLimitationReason::kBandwidth);
1455 // Bw enabled all layers.
1456 allocation.SetBitrate(1, 0, 10000);
1457 allocation.set_bw_limited(false);
1458 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1459 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1460 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1461 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1462 QualityLimitationReason::kNone);
1463
1464 // Screencast case
1465 // Configure two streams.
1466 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1467 config.number_of_streams = 2;
1468 stream1.width = kWidth;
1469 stream1.height = kHeight;
1470 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1471 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1472 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1473 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1474 QualityLimitationReason::kNone);
1475 // Bw disabled one layer.
1476 // Some positive bitrate only on the second stream.
1477 allocation.SetBitrate(0, 0, 10000);
1478 allocation.SetBitrate(1, 0, 0);
1479 allocation.set_bw_limited(true);
1480 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1481 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1482 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1483 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1484 QualityLimitationReason::kBandwidth);
1485 // Bw enabled all layers.
1486 allocation.SetBitrate(1, 0, 10000);
1487 allocation.set_bw_limited(false);
1488 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1489 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1490 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1491 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1492 QualityLimitationReason::kNone);
1493}
1494
asapersson59bac1a2016-01-07 23:36:00 -08001495TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001496 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001497 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1498
Pera48ddb72016-09-29 11:48:50 +02001499 // No switch, stats should not be updated.
1500 VideoEncoderConfig config;
1501 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001502 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001503 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001504
1505 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001506 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001507 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001508 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001509}
1510
asapersson320e45a2016-11-29 01:40:35 -08001511TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1512 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1513 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001514
asapersson320e45a2016-11-29 01:40:35 -08001515 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001516 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1517 EXPECT_METRIC_EQ(
1518 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1519 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1520 EXPECT_METRIC_EQ(
1521 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001522}
1523
1524TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001525 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001526 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001527 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1528 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1529 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001530 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001531
1532 // Not enough samples, stats should not be updated.
1533 for (int i = 0; i < kMinSamples - 1; ++i) {
1534 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001535 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001536 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1537 }
Åsa Persson0122e842017-10-16 12:19:23 +02001538 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001539 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1540 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001541
1542 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001543 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001544 for (int i = 0; i < kMinSamples; ++i) {
1545 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001546 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001547 encoded_image._encodedWidth = kWidth;
1548 encoded_image._encodedHeight = kHeight;
1549 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1550 encoded_image._encodedWidth = kWidth / 2;
1551 encoded_image._encodedHeight = kHeight / 2;
1552 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1553 }
1554
asapersson320e45a2016-11-29 01:40:35 -08001555 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001556 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1557 EXPECT_METRIC_EQ(
1558 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1559 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1560 EXPECT_METRIC_EQ(
1561 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001562}
1563
1564TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1565 const int kFps = 20;
1566 const int kMinPeriodicSamples = 6;
1567 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1568 for (int i = 0; i <= frames; ++i) {
1569 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1570 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1571 }
1572 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001573 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1574 EXPECT_METRIC_EQ(
1575 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001576}
1577
1578TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1579 EncodedImage encoded_image;
1580 const int kFps = 20;
1581 const int kMinPeriodicSamples = 6;
1582 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001583 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001584 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001585 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001586 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1587 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001588 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1589 }
1590 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001591 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1592 EXPECT_METRIC_EQ(
1593 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001594}
1595
1596TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1597 const int kFps = 20;
1598 const int kSuspendTimeMs = 10000;
1599 const int kMinPeriodicSamples = 6;
1600 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1601 for (int i = 0; i < frames; ++i) {
1602 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1603 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1604 }
1605 // Suspend.
1606 statistics_proxy_->OnSuspendChange(true);
1607 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1608
1609 for (int i = 0; i < frames; ++i) {
1610 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1611 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1612 }
1613 // Suspended time interval should not affect the framerate.
1614 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001615 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1616 EXPECT_METRIC_EQ(
1617 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001618}
1619
1620TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1621 EncodedImage encoded_image;
1622 const int kFps = 20;
1623 const int kSuspendTimeMs = 10000;
1624 const int kMinPeriodicSamples = 6;
1625 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001626 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001627 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001628 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001629 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1630 }
1631 // Suspend.
1632 statistics_proxy_->OnSuspendChange(true);
1633 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1634
Åsa Persson0122e842017-10-16 12:19:23 +02001635 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001636 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001637 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001638 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1639 }
1640 // Suspended time interval should not affect the framerate.
1641 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001642 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1643 EXPECT_METRIC_EQ(
1644 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001645}
1646
asaperssonf4e44af2017-04-19 02:01:06 -07001647TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001648 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1649 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001650
1651 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1652 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1653
1654 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001655 EXPECT_METRIC_EQ(
1656 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001657}
1658
1659TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001660 VideoAdaptationCounters cpu_counts;
1661 VideoAdaptationCounters quality_counts;
1662 cpu_counts.resolution_adaptations = 0;
1663 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001664
perkj803d97f2016-11-01 11:45:46 -07001665 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1666 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1667
Evan Shrubsoledff79252020-04-16 11:34:32 +02001668 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001669 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1670 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001671
1672 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1673 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1674
1675 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001676 EXPECT_METRIC_EQ(
1677 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1678 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001679 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1680}
1681
asapersson4374a092016-07-27 00:39:09 -07001682TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1683 const int64_t kTimeSec = 3;
1684 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1685 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001686 EXPECT_METRIC_EQ(
1687 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1688 EXPECT_METRIC_EQ(
1689 1,
1690 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001691}
1692
1693TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1694 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1695 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001696 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001697}
1698
asapersson66d4b372016-12-19 06:50:53 -08001699TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1700 // First RTP packet sent.
1701 UpdateDataCounters(kFirstSsrc);
1702
1703 // Min runtime has passed.
1704 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1705 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001706 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1707 EXPECT_METRIC_EQ(1,
1708 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001709}
1710
1711TEST_F(SendStatisticsProxyTest,
1712 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1713 // First RTP packet sent.
1714 UpdateDataCounters(kFirstSsrc);
1715
1716 // Min runtime has not passed.
1717 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1718 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001719 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1720 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001721}
1722
1723TEST_F(SendStatisticsProxyTest,
1724 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1725 // First RTP packet not sent.
1726 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1727 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001728 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001729}
1730
1731TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1732 // First RTP packet sent and min runtime passed.
1733 UpdateDataCounters(kFirstSsrc);
1734
1735 // No change. Video: 10000 ms, paused: 0 ms (0%).
1736 statistics_proxy_->OnSetEncoderTargetRate(50000);
1737 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1738 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1739
1740 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001741 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1742 EXPECT_METRIC_EQ(1,
1743 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1744 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1745 EXPECT_METRIC_EQ(1,
1746 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001747}
1748
1749TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1750 // First RTP packet sent and min runtime passed.
1751 UpdateDataCounters(kFirstSsrc);
1752
1753 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1754 statistics_proxy_->OnSetEncoderTargetRate(50000);
1755 fake_clock_.AdvanceTimeMilliseconds(7000);
1756 statistics_proxy_->OnSetEncoderTargetRate(0);
1757 fake_clock_.AdvanceTimeMilliseconds(3000);
1758 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1759
1760 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001761 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1762 EXPECT_METRIC_EQ(1,
1763 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1764 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1765 EXPECT_METRIC_EQ(1,
1766 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001767}
1768
1769TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1770 // First RTP packet sent.
1771 UpdateDataCounters(kFirstSsrc);
1772
1773 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1774 statistics_proxy_->OnSetEncoderTargetRate(0);
1775 fake_clock_.AdvanceTimeMilliseconds(1000);
1776 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1777 fake_clock_.AdvanceTimeMilliseconds(7000);
1778 statistics_proxy_->OnSetEncoderTargetRate(60000);
1779 fake_clock_.AdvanceTimeMilliseconds(3000);
1780 statistics_proxy_->OnSetEncoderTargetRate(0);
1781 fake_clock_.AdvanceTimeMilliseconds(250);
1782 statistics_proxy_->OnSetEncoderTargetRate(0);
1783 fake_clock_.AdvanceTimeMilliseconds(750);
1784 statistics_proxy_->OnSetEncoderTargetRate(60000);
1785 fake_clock_.AdvanceTimeMilliseconds(5000);
1786 statistics_proxy_->OnSetEncoderTargetRate(50000);
1787 fake_clock_.AdvanceTimeMilliseconds(4000);
1788 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1789
1790 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001791 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1792 EXPECT_METRIC_EQ(1,
1793 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1794 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1795 EXPECT_METRIC_EQ(1,
1796 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001797}
1798
1799TEST_F(SendStatisticsProxyTest,
1800 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1801 // First RTP packet sent.
1802 UpdateDataCounters(kFirstSsrc);
1803 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1804
1805 // Min runtime has not passed.
1806 statistics_proxy_->OnSetEncoderTargetRate(50000);
1807 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1808 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1809
1810 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001811 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001812}
1813
asapersson118ef002016-03-31 00:00:19 -07001814TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001815 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001816 CodecSpecificInfo codec_info;
1817 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001818
perkj803d97f2016-11-01 11:45:46 -07001819 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001820 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001821 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001822 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001823 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001824 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001825 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001826 }
1827 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001828 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1829 EXPECT_METRIC_EQ(
1830 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1831 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1832 EXPECT_METRIC_EQ(
1833 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001834}
1835
1836TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1837 VideoSendStream::Config config(nullptr);
1838 config.rtp.ssrcs.push_back(kFirstSsrc);
1839 statistics_proxy_.reset(new SendStatisticsProxy(
1840 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1841
asapersson118ef002016-03-31 00:00:19 -07001842 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001843 CodecSpecificInfo codec_info;
1844 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001845
perkj803d97f2016-11-01 11:45:46 -07001846 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001847 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001848 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001849 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001850 }
1851 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001852 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1853 EXPECT_METRIC_EQ(1,
1854 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001855}
1856
asapersson5265fed2016-04-18 02:58:47 -07001857TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001858 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001859 CodecSpecificInfo codec_info;
1860 codec_info.codecType = kVideoCodecVP9;
1861 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001862
perkj803d97f2016-11-01 11:45:46 -07001863 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001864 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001865 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001866 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001867 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001868 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001869 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001870 }
1871 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001872 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1873 EXPECT_METRIC_EQ(
1874 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1875 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1876 EXPECT_METRIC_EQ(
1877 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001878}
1879
1880TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1881 VideoSendStream::Config config(nullptr);
1882 config.rtp.ssrcs.push_back(kFirstSsrc);
1883 statistics_proxy_.reset(new SendStatisticsProxy(
1884 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1885
asapersson5265fed2016-04-18 02:58:47 -07001886 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001887 CodecSpecificInfo codec_info;
1888 codec_info.codecType = kVideoCodecVP9;
1889 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001890
perkj803d97f2016-11-01 11:45:46 -07001891 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001892 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001893 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001894 }
1895 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001896 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1897 EXPECT_METRIC_EQ(1,
1898 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001899}
1900
asapersson827cab32016-11-02 09:08:47 -07001901TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1902 EncodedImage encoded_image;
1903 CodecSpecificInfo codec_info;
1904 codec_info.codecType = kVideoCodecH264;
1905
1906 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001907 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001908 encoded_image.qp_ = kQpIdx0;
1909 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001910 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001911 encoded_image.qp_ = kQpIdx1;
1912 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001913 }
1914 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001915 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1916 EXPECT_METRIC_EQ(
1917 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1918 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1919 EXPECT_METRIC_EQ(
1920 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001921}
1922
asapersson4ee70462016-10-31 04:05:12 -07001923TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001924 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1925 // Configure one stream.
1926 VideoEncoderConfig config;
1927 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1928 VideoStream stream1;
1929 stream1.width = kWidth;
1930 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001931 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001932
1933 const int64_t kMaxEncodedFrameWindowMs = 800;
1934 const int kFps = 20;
1935 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1936 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1937 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1938
1939 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001940 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001941 encoded_image._encodedWidth = kWidth;
1942 encoded_image._encodedHeight = kHeight;
1943 for (int i = 0; i < kMinSamples; ++i) {
1944 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001945 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1946 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001947 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001948 }
asapersson4ee70462016-10-31 04:05:12 -07001949
1950 // Histograms are updated when the statistics_proxy_ is deleted.
1951 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001952 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1953 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1954 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1955 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001956}
1957
1958TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001959 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1960 // Configure two streams.
1961 VideoEncoderConfig config;
1962 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1963 VideoStream stream1;
1964 stream1.width = kWidth / 2;
1965 stream1.height = kHeight / 2;
1966 VideoStream stream2;
1967 stream2.width = kWidth;
1968 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001969 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001970
1971 const int64_t kMaxEncodedFrameWindowMs = 800;
1972 const int kFps = 20;
1973 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1974 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1975 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1976
1977 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001978 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001979 for (int i = 0; i < kMinSamples; ++i) {
1980 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001981 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1982 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001983 encoded_image._encodedWidth = kWidth;
1984 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001985 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001986 encoded_image._encodedWidth = kWidth / 2;
1987 encoded_image._encodedHeight = kHeight / 2;
1988 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1989 }
asapersson4ee70462016-10-31 04:05:12 -07001990
1991 // Histograms are updated when the statistics_proxy_ is deleted.
1992 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001993 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1994 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1995 EXPECT_METRIC_EQ(
1996 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
1997 0));
asapersson4ee70462016-10-31 04:05:12 -07001998 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01001999 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2000 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002001}
2002
2003TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002004 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2005 // Configure two streams.
2006 VideoEncoderConfig config;
2007 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2008 VideoStream stream1;
2009 stream1.width = kWidth / 2;
2010 stream1.height = kHeight / 2;
2011 VideoStream stream2;
2012 stream2.width = kWidth;
2013 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002014 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002015
2016 const int64_t kMaxEncodedFrameWindowMs = 800;
2017 const int kFps = 20;
2018 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2019 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2020 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2021
2022 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002023 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002024 encoded_image._encodedWidth = kWidth / 2;
2025 encoded_image._encodedHeight = kHeight / 2;
2026 for (int i = 0; i < kMinSamples; ++i) {
2027 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002028 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2029 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002030 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002031 }
asapersson4ee70462016-10-31 04:05:12 -07002032
2033 // Histograms are updated when the statistics_proxy_ is deleted.
2034 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002035 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2036 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2037 EXPECT_METRIC_EQ(
2038 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2039 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002040 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002041 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2042 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2043 EXPECT_METRIC_EQ(
2044 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2045 1));
asapersson4ee70462016-10-31 04:05:12 -07002046}
2047
2048TEST_F(SendStatisticsProxyTest,
2049 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002050 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2051 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002052 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002053 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002054 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002055 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002056
2057 // Histograms are updated when the statistics_proxy_ is deleted.
2058 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002059 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002060 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002061 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2062 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002063}
2064
2065TEST_F(SendStatisticsProxyTest,
2066 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002067 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002068 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002069 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002070 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002071 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002072
2073 // Histograms are updated when the statistics_proxy_ is deleted.
2074 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002075 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002076 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002077 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2078 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002079 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002080 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2081 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002082}
2083
2084TEST_F(SendStatisticsProxyTest,
2085 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2086 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002087 VideoAdaptationCounters cpu_counts;
2088 VideoAdaptationCounters quality_counts;
2089 quality_counts.resolution_adaptations = kDownscales;
2090 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002091 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2092 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002093 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002094 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002095 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002096 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002097 // Histograms are updated when the statistics_proxy_ is deleted.
2098 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002099 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002100 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002101 EXPECT_METRIC_EQ(
2102 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2103 100));
asapersson4ee70462016-10-31 04:05:12 -07002104 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002105 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2106 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2107 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002108 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2109 kDownscales));
2110}
2111
2112TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2113 // Initially false.
2114 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002115
Åsa Perssonaa329e72017-12-15 15:54:44 +01002116 // Configure two streams.
2117 VideoEncoderConfig config;
2118 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002119 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002120 VideoStream stream1;
2121 stream1.width = kWidth / 2;
2122 stream1.height = kHeight / 2;
2123 VideoStream stream2;
2124 stream2.width = kWidth;
2125 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002126 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002127
Åsa Perssonaa329e72017-12-15 15:54:44 +01002128 // One stream encoded.
2129 EncodedImage encoded_image;
2130 encoded_image._encodedWidth = kWidth / 2;
2131 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002132
2133 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002134 VideoAdaptationCounters cpu_counts;
2135 VideoAdaptationCounters quality_counts;
2136 quality_counts.resolution_adaptations = 1;
2137 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2138 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002139 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2140 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002141 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2142 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002143
2144 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002145 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002146 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2147 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002148 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2149 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2150
2151 // Bw disabled one layer.
2152 VideoCodec codec;
2153 codec.numberOfSimulcastStreams = 2;
2154 codec.simulcastStream[0].active = true;
2155 codec.simulcastStream[1].active = true;
2156 VideoBitrateAllocation allocation;
2157 // Some positive bitrate only on the second stream.
2158 allocation.SetBitrate(1, 0, 10000);
2159 allocation.set_bw_limited(true);
2160 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2161 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002162
2163 // Revert for the next test.
2164 allocation.set_bw_limited(false);
2165 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2166 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2167
2168 // Internal encoder scaler reduced resolution.
2169 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2170 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002171}
2172
asapersson66d4b372016-12-19 06:50:53 -08002173TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2174 // Initially zero.
2175 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2176
2177 const int kBitrate = 100000;
2178 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2179 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2180
2181 statistics_proxy_->OnSetEncoderTargetRate(0);
2182 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2183}
2184
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002185TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002186 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002187 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2188 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002189 1;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002190 // From ReportBlockDataObserver.
2191 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2192 RTCPReportBlock report_block;
2193 report_block.source_ssrc = excluded_ssrc;
2194 ReportBlockData data;
2195 data.SetReportBlock(report_block, 0);
2196 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002197
2198 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002199 uint32_t total = 0;
2200 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002201 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002202 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002203
2204 // From FrameCountObserver.
2205 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002206 FrameCounts frame_counts;
2207 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002208 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002209
2210 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2211 EXPECT_TRUE(stats.substreams.empty());
2212}
2213
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002214TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2215 static const int kEncodedWidth = 123;
2216 static const int kEncodedHeight = 81;
2217 EncodedImage encoded_image;
2218 encoded_image._encodedWidth = kEncodedWidth;
2219 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002220 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002221
kjellander02b3d272016-04-20 05:05:54 -07002222 CodecSpecificInfo codec_info;
2223 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002224
kjellander02b3d272016-04-20 05:05:54 -07002225 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002226 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002227 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002228
2229 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002230 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2231 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2232 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2233 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002234
2235 // Forward almost to timeout, this should not have removed stats.
2236 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2237 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002238 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2239 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002240
2241 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2242 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002243 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2244 RTCPReportBlock report_block;
2245 report_block.source_ssrc = config_.rtp.ssrcs[0];
2246 ReportBlockData data;
2247 data.SetReportBlock(report_block, 0);
2248 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002249
2250 // Report stats for second SSRC to make sure it's not outdated along with the
2251 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002252 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002253
2254 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2255 // reported, but substream 1 should.
2256 fake_clock_.AdvanceTimeMilliseconds(1);
2257 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002258 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2259 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2260 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2261 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002262}
2263
Peter Boström20f3f942015-05-15 11:33:39 +02002264TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2265 static const int kEncodedWidth = 123;
2266 static const int kEncodedHeight = 81;
2267 EncodedImage encoded_image;
2268 encoded_image._encodedWidth = kEncodedWidth;
2269 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002270 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002271
kjellander02b3d272016-04-20 05:05:54 -07002272 CodecSpecificInfo codec_info;
2273 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002274
kjellander02b3d272016-04-20 05:05:54 -07002275 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002276 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002277 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002278
2279 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2280 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2281 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2282 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2283 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2284 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2285}
2286
2287TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002288 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002289 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2290 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2291 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2292
2293 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2294
2295 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002296 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002297 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002298 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002299 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2300 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2301 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2302}
2303
sprang07fb9be2016-02-24 07:55:00 -08002304TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2305 RtcpPacketTypeCounterObserver* proxy =
2306 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2307 RtcpPacketTypeCounter counters;
2308 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2309 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2310 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2311
2312 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2313
2314 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2315 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2316 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2317 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2318 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2319
2320 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2321 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2322
2323 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002324 VideoEncoderConfig config;
2325 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002326 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002327
Ying Wangef3998f2019-12-09 13:06:53 +01002328 EXPECT_METRIC_EQ(
2329 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2330 EXPECT_METRIC_EQ(
2331 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2332 EXPECT_METRIC_EQ(
2333 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2334 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2335 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002336
2337 const int kRate = 60 * 2; // Packets per minute with two streams.
2338
Ying Wangef3998f2019-12-09 13:06:53 +01002339 EXPECT_METRIC_EQ(
2340 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2341 1 * kRate));
2342 EXPECT_METRIC_EQ(
2343 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2344 2 * kRate));
2345 EXPECT_METRIC_EQ(
2346 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2347 3 * kRate));
2348 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002349 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2350 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002351
2352 // New start time but same counter values.
2353 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2354 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2355
2356 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2357
2358 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2359 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2360 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2361 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2362 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2363
2364 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2365 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2366
2367 SetUp(); // Reset stats proxy also causes histograms to be reported.
2368
Ying Wangef3998f2019-12-09 13:06:53 +01002369 EXPECT_METRIC_EQ(
2370 1, metrics::NumSamples(
2371 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2372 EXPECT_METRIC_EQ(1,
2373 metrics::NumSamples(
2374 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2375 EXPECT_METRIC_EQ(1,
2376 metrics::NumSamples(
2377 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2378 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002379 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002380 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2381
Ying Wangef3998f2019-12-09 13:06:53 +01002382 EXPECT_METRIC_EQ(
2383 1,
2384 metrics::NumEvents(
2385 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2386 EXPECT_METRIC_EQ(
2387 1,
2388 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2389 2 * kRate));
2390 EXPECT_METRIC_EQ(
2391 1,
2392 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2393 3 * kRate));
2394 EXPECT_METRIC_EQ(
2395 1, metrics::NumEvents(
2396 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2397 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002398}
2399
Henrik Boströmf45ca372020-03-24 13:30:50 +01002400TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2401 StreamDataCountersCallback* proxy =
2402 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2403 StreamDataCounters counters;
2404 proxy->DataCountersUpdated(counters, kFirstSsrc);
2405 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2406
2407 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2408 VideoSendStream::StreamStats::StreamType::kRtx);
2409 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2410 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2411 VideoSendStream::StreamStats::StreamType::kRtx);
2412 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2413}
2414
asaperssona6a699a2016-11-25 03:52:46 -08002415TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2416 statistics_proxy_.reset(
2417 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2418 VideoEncoderConfig::ContentType::kRealtimeVideo));
2419
2420 StreamDataCountersCallback* proxy =
2421 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2422 StreamDataCounters counters;
2423 proxy->DataCountersUpdated(counters, kFirstSsrc);
2424 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2425
Henrik Boströmf45ca372020-03-24 13:30:50 +01002426 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2427 VideoSendStream::StreamStats::StreamType::kFlexfec);
2428 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2429 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2430 VideoSendStream::StreamStats::StreamType::kFlexfec);
2431 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002432}
2433
2434TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2435 statistics_proxy_.reset(
2436 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2437 VideoEncoderConfig::ContentType::kRealtimeVideo));
2438
2439 StreamDataCountersCallback* proxy =
2440 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002441 StreamDataCounters counters;
2442 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002443
asapersson93e1e232017-02-06 05:18:35 -08002444 const int kMinRequiredPeriodSamples = 8;
2445 const int kPeriodIntervalMs = 2000;
2446 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2447 counters.transmitted.packets += 20;
2448 counters.transmitted.header_bytes += 500;
2449 counters.transmitted.padding_bytes += 1000;
2450 counters.transmitted.payload_bytes += 2000;
2451 counters.retransmitted.packets += 2;
2452 counters.retransmitted.header_bytes += 25;
2453 counters.retransmitted.padding_bytes += 100;
2454 counters.retransmitted.payload_bytes += 250;
2455 counters.fec = counters.retransmitted;
2456 rtx_counters.transmitted = counters.transmitted;
2457 // Advance one interval and update counters.
2458 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2459 proxy->DataCountersUpdated(counters, kFirstSsrc);
2460 proxy->DataCountersUpdated(counters, kSecondSsrc);
2461 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2462 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2463 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2464 }
asaperssona6a699a2016-11-25 03:52:46 -08002465
asaperssona6a699a2016-11-25 03:52:46 -08002466 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002467 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002468 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2469 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002470 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002471 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2472 EXPECT_METRIC_EQ(1,
2473 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002474 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002475 EXPECT_METRIC_EQ(1,
2476 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2477 EXPECT_METRIC_EQ(
2478 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002479 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002480 EXPECT_METRIC_EQ(
2481 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2482 EXPECT_METRIC_EQ(
2483 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002484 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002485 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2486 EXPECT_METRIC_EQ(1,
2487 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002488 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002489 EXPECT_METRIC_EQ(
2490 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2491 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002492 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002493}
2494
Erik Språng22c2b482016-03-01 09:40:42 +01002495TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2496 StreamDataCountersCallback* proxy =
2497 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2498 StreamDataCounters counters;
2499 StreamDataCounters rtx_counters;
2500 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002501
asapersson93e1e232017-02-06 05:18:35 -08002502 const int kMinRequiredPeriodSamples = 8;
2503 const int kPeriodIntervalMs = 2000;
2504 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2505 counters.transmitted.packets += 20;
2506 counters.transmitted.header_bytes += 500;
2507 counters.transmitted.padding_bytes += 1000;
2508 counters.transmitted.payload_bytes += 2000;
2509 counters.retransmitted.packets += 2;
2510 counters.retransmitted.header_bytes += 25;
2511 counters.retransmitted.padding_bytes += 100;
2512 counters.retransmitted.payload_bytes += 250;
2513 counters.fec = counters.retransmitted;
2514 rtx_counters.transmitted = counters.transmitted;
2515 // Advance one interval and update counters.
2516 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2517 proxy->DataCountersUpdated(counters, kFirstSsrc);
2518 proxy->DataCountersUpdated(counters, kSecondSsrc);
2519 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2520 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2521 }
Erik Språng22c2b482016-03-01 09:40:42 +01002522
2523 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002524 VideoEncoderConfig config;
2525 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002526 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002527
asapersson93e1e232017-02-06 05:18:35 -08002528 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002529 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2530 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002531 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002532 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2533 EXPECT_METRIC_EQ(1,
2534 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002535 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002536 EXPECT_METRIC_EQ(1,
2537 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2538 EXPECT_METRIC_EQ(
2539 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002540 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002541 EXPECT_METRIC_EQ(
2542 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2543 EXPECT_METRIC_EQ(
2544 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002545 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002546 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2547 EXPECT_METRIC_EQ(1,
2548 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002549 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002550 EXPECT_METRIC_EQ(
2551 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2552 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002553 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002554
asapersson93e1e232017-02-06 05:18:35 -08002555 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002556 // Double counter values, this should result in the same counts as before but
2557 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002558 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2559 counters.transmitted.packets += 20;
2560 counters.transmitted.header_bytes += 500;
2561 counters.transmitted.padding_bytes += 1000;
2562 counters.transmitted.payload_bytes += 2000;
2563 counters.retransmitted.packets += 2;
2564 counters.retransmitted.header_bytes += 25;
2565 counters.retransmitted.padding_bytes += 100;
2566 counters.retransmitted.payload_bytes += 250;
2567 counters.fec = counters.retransmitted;
2568 rtx_counters.transmitted = counters.transmitted;
2569 // Advance one interval and update counters.
2570 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2571 proxy->DataCountersUpdated(counters, kFirstSsrc);
2572 proxy->DataCountersUpdated(counters, kSecondSsrc);
2573 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2574 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2575 }
Erik Språng22c2b482016-03-01 09:40:42 +01002576
asapersson93e1e232017-02-06 05:18:35 -08002577 // Reset stats proxy also causes histograms to be reported.
2578 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002579
asapersson93e1e232017-02-06 05:18:35 -08002580 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002581 EXPECT_METRIC_EQ(
2582 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2583 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002584 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2585 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002586 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002587 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002588 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2589 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002590 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002591 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2592 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2593 EXPECT_METRIC_EQ(
2594 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2595 12));
asapersson93e1e232017-02-06 05:18:35 -08002596 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002597 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2598 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2599 EXPECT_METRIC_EQ(
2600 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2601 16));
asapersson93e1e232017-02-06 05:18:35 -08002602 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002603 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002604 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002605 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2606 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002607 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002608 EXPECT_METRIC_EQ(
2609 1, metrics::NumSamples(
2610 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2611 EXPECT_METRIC_EQ(
2612 1, metrics::NumEvents(
2613 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002614}
Erik Språng22c2b482016-03-01 09:40:42 +01002615
asapersson93e1e232017-02-06 05:18:35 -08002616TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2617 StreamDataCountersCallback* proxy =
2618 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2619 StreamDataCounters counters;
2620 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002621
asapersson93e1e232017-02-06 05:18:35 -08002622 const int kMinRequiredPeriodSamples = 8;
2623 const int kPeriodIntervalMs = 2000;
2624 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2625 counters.transmitted.packets += 20;
2626 counters.transmitted.header_bytes += 500;
2627 counters.transmitted.payload_bytes += 2000;
2628 counters.fec = counters.retransmitted;
2629 // Advance one interval and update counters.
2630 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2631 proxy->DataCountersUpdated(counters, kFirstSsrc);
2632 }
2633
2634 // RTX enabled. No data sent over RTX.
2635 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002636 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2637 EXPECT_METRIC_EQ(1,
2638 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002639}
2640
2641TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2642 VideoSendStream::Config config(nullptr);
2643 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2644 statistics_proxy_.reset(new SendStatisticsProxy(
2645 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2646
2647 StreamDataCountersCallback* proxy =
2648 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2649 StreamDataCounters counters;
2650
2651 const int kMinRequiredPeriodSamples = 8;
2652 const int kPeriodIntervalMs = 2000;
2653 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2654 counters.transmitted.packets += 20;
2655 counters.transmitted.header_bytes += 500;
2656 counters.transmitted.payload_bytes += 2000;
2657 counters.fec = counters.retransmitted;
2658 // Advance one interval and update counters.
2659 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2660 proxy->DataCountersUpdated(counters, kFirstSsrc);
2661 }
2662
2663 // RTX not enabled.
2664 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002665 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002666}
2667
2668TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2669 StreamDataCountersCallback* proxy =
2670 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2671 StreamDataCounters counters;
2672 StreamDataCounters rtx_counters;
2673
2674 const int kMinRequiredPeriodSamples = 8;
2675 const int kPeriodIntervalMs = 2000;
2676 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2677 counters.transmitted.packets += 20;
2678 counters.transmitted.header_bytes += 500;
2679 counters.transmitted.payload_bytes += 2000;
2680 // Advance one interval and update counters.
2681 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2682 proxy->DataCountersUpdated(counters, kFirstSsrc);
2683 }
2684
2685 // FEC enabled. No FEC data sent.
2686 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002687 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2688 EXPECT_METRIC_EQ(1,
2689 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002690}
2691
2692TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2693 VideoSendStream::Config config(nullptr);
2694 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2695 statistics_proxy_.reset(new SendStatisticsProxy(
2696 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2697
2698 StreamDataCountersCallback* proxy =
2699 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2700 StreamDataCounters counters;
2701
2702 const int kMinRequiredPeriodSamples = 8;
2703 const int kPeriodIntervalMs = 2000;
2704 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2705 counters.transmitted.packets += 20;
2706 counters.transmitted.header_bytes += 500;
2707 counters.transmitted.payload_bytes += 2000;
2708 counters.fec = counters.retransmitted;
2709 // Advance one interval and update counters.
2710 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2711 proxy->DataCountersUpdated(counters, kFirstSsrc);
2712 }
2713
2714 // FEC not enabled.
2715 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002716 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002717}
2718
asapersson8d75ac72017-09-15 06:41:15 -07002719TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002720 const std::string kName = "encoderName";
2721 statistics_proxy_->OnEncoderImplementationChanged(kName);
2722 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002723}
2724
Sergey Silkinbb081a62018-09-04 18:34:22 +02002725TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2726 static const int kEncodedWidth = 123;
2727 static const int kEncodedHeight = 81;
2728 EncodedImage encoded_image;
2729 encoded_image._encodedWidth = kEncodedWidth;
2730 encoded_image._encodedHeight = kEncodedHeight;
2731 encoded_image.SetSpatialIndex(0);
2732
2733 CodecSpecificInfo codec_info;
2734 codec_info.codecType = kVideoCodecVP9;
2735
2736 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002737 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002738 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2739 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2740 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2741 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2742
2743 // Top layer updates resolution.
2744 encoded_image._encodedWidth = kEncodedWidth * 2;
2745 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002746 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002747 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2748 stats = statistics_proxy_->GetStats();
2749 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2750 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2751
2752 // Low layer of next frame doesn't update resolution.
2753 encoded_image._encodedWidth = kEncodedWidth;
2754 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002755 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002756 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2757 stats = statistics_proxy_->GetStats();
2758 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2759 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2760}
2761
asapersson8d75ac72017-09-15 06:41:15 -07002762class ForcedFallbackTest : public SendStatisticsProxyTest {
2763 public:
2764 explicit ForcedFallbackTest(const std::string& field_trials)
2765 : SendStatisticsProxyTest(field_trials) {
2766 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002767 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002768 encoded_image_._encodedWidth = kWidth;
2769 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002770 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002771 }
2772
2773 ~ForcedFallbackTest() override {}
2774
2775 protected:
2776 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002777 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2778
asapersson8d75ac72017-09-15 06:41:15 -07002779 // First frame is not updating stats, insert initial frame.
2780 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2781 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2782 }
2783 for (int i = 0; i < num_frames; ++i) {
2784 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2785 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2786 }
2787 // Add frame to include last time interval.
2788 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2789 }
2790
2791 EncodedImage encoded_image_;
2792 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002793 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002794 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2795 const int kFrameIntervalMs = 1000;
2796 const int kMinFrames = 20; // Min run time 20 sec.
2797};
2798
2799class ForcedFallbackDisabled : public ForcedFallbackTest {
2800 public:
2801 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002802 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2803 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002804};
2805
2806class ForcedFallbackEnabled : public ForcedFallbackTest {
2807 public:
2808 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002809 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2810 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002811};
2812
2813TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2814 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2815 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002816 EXPECT_METRIC_EQ(0,
2817 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2818 EXPECT_METRIC_EQ(
2819 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002820}
2821
2822TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2823 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002824 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002825 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002826 EXPECT_METRIC_EQ(1,
2827 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2828 EXPECT_METRIC_EQ(
2829 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2830 EXPECT_METRIC_EQ(
2831 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2832 EXPECT_METRIC_EQ(
2833 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002834}
2835
2836TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2837 codec_info_.codecType = kVideoCodecVP9;
2838 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2839 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002840 EXPECT_METRIC_EQ(0,
2841 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2842 EXPECT_METRIC_EQ(
2843 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002844}
2845
2846TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2847 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2848 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2849 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002850 EXPECT_METRIC_EQ(0,
2851 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2852 EXPECT_METRIC_EQ(
2853 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002854}
2855
2856TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002857 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002858 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2859 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002860 EXPECT_METRIC_EQ(0,
2861 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2862 EXPECT_METRIC_EQ(
2863 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002864}
2865
2866TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2867 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2868 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002869 EXPECT_METRIC_EQ(0,
2870 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2871 EXPECT_METRIC_EQ(
2872 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002873}
2874
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002875TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2876 InsertEncodedFrames(1, kFrameIntervalMs);
2877 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2878}
2879
2880TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2881 InsertEncodedFrames(1, kFrameIntervalMs);
2882 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2883}
2884
2885TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002886 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002887 InsertEncodedFrames(1, kFrameIntervalMs);
2888 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2889}
2890
2891TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2892 encoded_image_._encodedWidth = kWidth + 1;
2893 InsertEncodedFrames(1, kFrameIntervalMs);
2894 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2895}
2896
2897TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002898 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002899 InsertEncodedFrames(1, kFrameIntervalMs);
2900 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2901}
2902
2903TEST_F(ForcedFallbackDisabled,
2904 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2905 encoded_image_._encodedWidth = kWidth + 1;
2906 statistics_proxy_->OnMinPixelLimitReached();
2907 InsertEncodedFrames(1, kFrameIntervalMs);
2908 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2909}
2910
asapersson8d75ac72017-09-15 06:41:15 -07002911TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2912 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002913 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002914 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002915 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002916 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002917 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002918 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002919
2920 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002921 EXPECT_METRIC_EQ(1,
2922 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2923 EXPECT_METRIC_EQ(
2924 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2925 EXPECT_METRIC_EQ(
2926 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2927 EXPECT_METRIC_EQ(
2928 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002929}
2930
2931TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2932 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2933 const int kMaxFrameDiffMs = 2000;
2934
2935 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2936 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002937 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002938 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002939 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002940 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002941 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002942 InsertEncodedFrames(20, 1000);
2943 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2944 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002945 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002946 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002947 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002948 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002949 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002950 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002951 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002952
2953 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002954 EXPECT_METRIC_EQ(1,
2955 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2956 EXPECT_METRIC_EQ(
2957 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2958 EXPECT_METRIC_EQ(
2959 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2960 EXPECT_METRIC_EQ(
2961 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002962}
2963
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002964TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2965 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002966 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002967 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2968
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002969 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002970 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002971 EXPECT_METRIC_EQ(0,
2972 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2973 EXPECT_METRIC_EQ(
2974 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002975}
2976
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002977TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2978 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002979 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002980 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2981
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002982 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002983 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002984 EXPECT_METRIC_EQ(1,
2985 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2986 EXPECT_METRIC_EQ(
2987 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002988}
2989
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002990} // namespace webrtc