blob: 01dbebdbd9c67902b20608959ea3468b777cd6e9 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
Steve Antonbd631a02019-03-28 10:51:27 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 10:51:27 -070019#include "absl/algorithm/container.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020020#include "api/units/timestamp.h"
Evan Shrubsolece0a11d2020-04-16 11:36:55 +020021#include "api/video/video_adaptation_reason.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020022#include "api/video/video_bitrate_allocation.h"
23#include "api/video/video_codec_type.h"
24#include "api/video_codecs/video_codec.h"
25#include "api/video_codecs/video_encoder_config.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020026#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070028#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000030
31namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070032namespace {
33const uint32_t kFirstSsrc = 17;
34const uint32_t kSecondSsrc = 42;
35const uint32_t kFirstRtxSsrc = 18;
36const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080037const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080038const int kFpsPeriodicIntervalMs = 2000;
39const int kWidth = 640;
40const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070041const int kQpIdx0 = 21;
42const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010043const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080044const CodecSpecificInfo kDefaultCodecInfo = []() {
45 CodecSpecificInfo codec_info;
46 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080047 return codec_info;
48}();
Evan Shrubsoledff79252020-04-16 11:34:32 +020049
50const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
51 true);
52const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
53 true,
54 false);
55const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
56 false,
57 true);
58const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
asapersson5265fed2016-04-18 02:58:47 -070059} // namespace
sprang07fb9be2016-02-24 07:55:00 -080060
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000061class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000062 public:
asapersson8d75ac72017-09-15 06:41:15 -070063 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
64 explicit SendStatisticsProxyTest(const std::string& field_trials)
65 : override_field_trials_(field_trials),
66 fake_clock_(1234),
Åsa Persson90719572021-04-08 19:05:30 +020067 config_(GetTestConfig()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000068 virtual ~SendStatisticsProxyTest() {}
69
70 protected:
71 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070072 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080073 statistics_proxy_.reset(new SendStatisticsProxy(
74 &fake_clock_, GetTestConfig(),
75 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000076 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010077 for (const auto& ssrc : config_.rtp.ssrcs) {
78 expected_.substreams[ssrc].type =
79 VideoSendStream::StreamStats::StreamType::kMedia;
80 }
81 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
82 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
83 expected_.substreams[ssrc].type =
84 VideoSendStream::StreamStats::StreamType::kRtx;
85 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
86 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000087 }
88
89 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070090 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080091 config.rtp.ssrcs.push_back(kFirstSsrc);
92 config.rtp.ssrcs.push_back(kSecondSsrc);
93 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
94 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070095 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000096 return config;
97 }
98
asaperssona6a699a2016-11-25 03:52:46 -080099 VideoSendStream::Config GetTestConfigWithFlexFec() {
100 VideoSendStream::Config config(nullptr);
101 config.rtp.ssrcs.push_back(kFirstSsrc);
102 config.rtp.ssrcs.push_back(kSecondSsrc);
103 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
104 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -0800105 config.rtp.flexfec.payload_type = 50;
106 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +0100107 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -0800108 return config;
109 }
110
111 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
112 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
113 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
114 stats.substreams.find(ssrc);
115 EXPECT_NE(it, stats.substreams.end());
116 return it->second;
117 }
118
asapersson66d4b372016-12-19 06:50:53 -0800119 void UpdateDataCounters(uint32_t ssrc) {
120 StreamDataCountersCallback* proxy =
121 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
122 StreamDataCounters counters;
123 proxy->DataCountersUpdated(counters, ssrc);
124 }
125
sprang@webrtc.org09315702014-02-07 12:06:29 +0000126 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
Di Wu668dbf62021-02-27 00:29:15 -0800127 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000128 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
129 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000130 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000131 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
133 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000134 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000135 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000136 it != one.substreams.end(); ++it) {
137 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
138 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000139 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000140 const VideoSendStream::StreamStats& a = it->second;
141 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142
Henrik Boströmf45ca372020-03-24 13:30:50 +0100143 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000144 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
145 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000146 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000147 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
148 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000150 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
151 b.rtp_stats.transmitted.payload_bytes);
152 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
153 b.rtp_stats.transmitted.header_bytes);
154 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
155 b.rtp_stats.transmitted.padding_bytes);
156 EXPECT_EQ(a.rtp_stats.transmitted.packets,
157 b.rtp_stats.transmitted.packets);
158 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
159 b.rtp_stats.retransmitted.packets);
160 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000161
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200162 EXPECT_EQ(a.report_block_data.has_value(),
163 b.report_block_data.has_value());
164 if (a.report_block_data.has_value()) {
165 const RTCPReportBlock& a_rtcp_stats =
166 a.report_block_data->report_block();
167 const RTCPReportBlock& b_rtcp_stats =
168 b.report_block_data->report_block();
169 EXPECT_EQ(a_rtcp_stats.fraction_lost, b_rtcp_stats.fraction_lost);
170 EXPECT_EQ(a_rtcp_stats.packets_lost, b_rtcp_stats.packets_lost);
171 EXPECT_EQ(a_rtcp_stats.extended_highest_sequence_number,
172 b_rtcp_stats.extended_highest_sequence_number);
173 EXPECT_EQ(a_rtcp_stats.jitter, b_rtcp_stats.jitter);
174 }
sprang@webrtc.org09315702014-02-07 12:06:29 +0000175 }
176 }
177
asapersson8d75ac72017-09-15 06:41:15 -0700178 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000179 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800180 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000181 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000183};
184
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200185TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
186 ReportBlockDataObserver* callback = statistics_proxy_.get();
187 for (uint32_t ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000188 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200189 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200190 RTCPReportBlock report_block;
191 report_block.source_ssrc = ssrc;
192 report_block.packets_lost = offset;
193 report_block.extended_highest_sequence_number = offset + 1;
194 report_block.fraction_lost = offset + 2;
195 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200196 ReportBlockData data;
197 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200198 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200199
200 callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000201 }
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200202 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000203 // Add statistics with some arbitrary, but unique, numbers.
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200204 uint32_t offset = ssrc * 4;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200205 RTCPReportBlock report_block;
206 report_block.source_ssrc = ssrc;
207 report_block.packets_lost = offset;
208 report_block.extended_highest_sequence_number = offset + 1;
209 report_block.fraction_lost = offset + 2;
210 report_block.jitter = offset + 3;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200211 ReportBlockData data;
212 data.SetReportBlock(report_block, 0);
Danil Chapovalovea7474e2021-05-18 12:48:12 +0200213 expected_.substreams[ssrc].report_block_data = data;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200214
215 callback->OnReportBlockDataUpdated(data);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000216 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000217 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000218 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000219}
220
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000221TEST_F(SendStatisticsProxyTest, Suspended) {
222 // Verify that the value is false by default.
223 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
224
225 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200226 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000227 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
228
229 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200230 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000231 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
232}
233
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000234TEST_F(SendStatisticsProxyTest, FrameCounts) {
235 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700236 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000237 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000238 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
239 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000240 FrameCounts frame_counts;
241 frame_counts.key_frames = offset;
242 frame_counts.delta_frames = offset + 1;
243 stats.frame_counts = frame_counts;
244 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000245 }
asapersson35151f32016-05-02 23:44:01 -0700246 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000247 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000248 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
249 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000250 FrameCounts frame_counts;
251 frame_counts.key_frames = offset;
252 frame_counts.delta_frames = offset + 1;
253 stats.frame_counts = frame_counts;
254 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000255 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000256
257 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000258 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000259}
260
261TEST_F(SendStatisticsProxyTest, DataCounters) {
262 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700263 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000264 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
265 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000266 size_t offset = ssrc * sizeof(StreamDataCounters);
267 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000268 counters.transmitted.payload_bytes = offset;
269 counters.transmitted.header_bytes = offset + 1;
270 counters.fec.packets = offset_uint32 + 2;
271 counters.transmitted.padding_bytes = offset + 3;
272 counters.retransmitted.packets = offset_uint32 + 4;
273 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000274 callback->DataCountersUpdated(counters, ssrc);
275 }
asapersson35151f32016-05-02 23:44:01 -0700276 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000277 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
278 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000279 size_t offset = ssrc * sizeof(StreamDataCounters);
280 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000281 counters.transmitted.payload_bytes = offset;
282 counters.transmitted.header_bytes = offset + 1;
283 counters.fec.packets = offset_uint32 + 2;
284 counters.transmitted.padding_bytes = offset + 3;
285 counters.retransmitted.packets = offset_uint32 + 4;
286 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000287 callback->DataCountersUpdated(counters, ssrc);
288 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000289
290 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000291 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000292}
293
294TEST_F(SendStatisticsProxyTest, Bitrate) {
295 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700296 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000297 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200298 uint32_t total = ssrc;
299 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000300 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700301 expected_.substreams[ssrc].total_bitrate_bps = total;
302 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000303 }
asapersson35151f32016-05-02 23:44:01 -0700304 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000305 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200306 uint32_t total = ssrc;
307 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000308 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700309 expected_.substreams[ssrc].total_bitrate_bps = total;
310 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000311 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000312
313 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000314 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000315}
316
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000317TEST_F(SendStatisticsProxyTest, SendSideDelay) {
318 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700319 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000320 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
321 // stream.
322 int avg_delay_ms = ssrc;
323 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200324 uint64_t total_packet_send_delay_ms = ssrc + 2;
325 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
326 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000327 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
328 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200329 expected_.substreams[ssrc].total_packet_send_delay_ms =
330 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000331 }
asapersson35151f32016-05-02 23:44:01 -0700332 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000333 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
334 // stream.
335 int avg_delay_ms = ssrc;
336 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200337 uint64_t total_packet_send_delay_ms = ssrc + 2;
338 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
339 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000340 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
341 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200342 expected_.substreams[ssrc].total_packet_send_delay_ms =
343 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000344 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000345 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000346 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000347}
348
Peter Boströme4499152016-02-05 11:13:28 +0100349TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800350 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200351 int encode_usage_percent = 80;
352 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
353 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800354
355 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
356 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200357 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800358}
359
Henrik Boström5684af52019-04-02 15:05:21 +0200360TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
361 const int kEncodeUsagePercent = 0; // Don't care for this test.
362 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
363 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
364 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
365 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
366 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
367}
368
sakal43536c32016-10-24 01:46:43 -0700369TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
370 EncodedImage encoded_image;
371 CodecSpecificInfo codec_info;
372 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
373 for (uint32_t i = 1; i <= 3; ++i) {
374 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
375 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
376 }
377}
378
sakal87da4042016-10-31 06:53:47 -0700379TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
380 EncodedImage encoded_image;
381 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200382 auto ssrc = config_.rtp.ssrcs[0];
383 EXPECT_EQ(absl::nullopt,
384 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700385 encoded_image.qp_ = 3;
386 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200387 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700388 encoded_image.qp_ = 127;
389 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200390 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700391}
392
393TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
394 EncodedImage encoded_image;
395 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200396 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700397 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200398 EXPECT_EQ(absl::nullopt,
399 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700400 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200401 EXPECT_EQ(absl::nullopt,
402 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700403}
404
Henrik Boström23aff9b2019-05-20 15:15:38 +0200405TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
406 const uint32_t kTargetBytesPerSecond = 100000;
407 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
408 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
409
410 EncodedImage encoded_image;
411 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
412 // On the first frame we don't know the frame rate yet, calculation yields
413 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
Artem Titovab30d722021-07-27 16:22:11 +0200414 // increment by a full `kTargetBytesPerSecond`.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200415 EXPECT_EQ(kTargetBytesPerSecond,
416 statistics_proxy_->GetStats().total_encoded_bytes_target);
417}
418
419TEST_F(SendStatisticsProxyTest,
420 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
421 const uint32_t kTargetBytesPerSecond = 100000;
422 const int kInterframeDelayMs = 100;
423
424 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
Artem Titovab30d722021-07-27 16:22:11 +0200425 // `fake_clock_` for testing, but the RateTracker relies on a global clock.
Henrik Boström23aff9b2019-05-20 15:15:38 +0200426 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
427 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
428 // this test can stop relying on rtc::ScopedFakeClock.
429 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100430 fake_global_clock.SetTime(
431 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200432
433 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
434 EncodedImage encoded_image;
435
436 // First frame
437 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
438 uint64_t first_total_encoded_bytes_target =
439 statistics_proxy_->GetStats().total_encoded_bytes_target;
440 // Second frame
441 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100442 fake_global_clock.SetTime(
443 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200444 encoded_image.SetTimestamp(encoded_image.Timestamp() +
445 90 * kInterframeDelayMs);
446 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
447
448 auto stats = statistics_proxy_->GetStats();
449 // By the time the second frame arrives, one frame has previously arrived
Artem Titovab30d722021-07-27 16:22:11 +0200450 // during a `kInterframeDelayMs` interval. The estimated encode frame rate at
Henrik Boström23aff9b2019-05-20 15:15:38 +0200451 // the second frame's arrival should be 10 FPS.
452 uint64_t delta_encoded_bytes_target =
453 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
454 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
455}
456
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200457TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
458 const int kInterframeDelayMs = 100;
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
Åsa Persson8d564722021-08-03 14:43:01 +0200480TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp8Simulcast) {
481 const int kInterframeDelayMs = 100;
482 rtc::ScopedFakeClock fake_global_clock;
483 EncodedImage encoded_image;
484 CodecSpecificInfo codec_info;
485 codec_info.codecType = kVideoCodecVP8;
486
487 for (int i = 0; i < 10; ++i) {
488 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
489 fake_global_clock.SetTime(
490 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
491 encoded_image.SetTimestamp(encoded_image.Timestamp() +
492 90 * kInterframeDelayMs);
493 encoded_image.SetSpatialIndex(0);
494 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
495 encoded_image.SetSpatialIndex(1);
496 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
497 }
498
499 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
500 EXPECT_EQ(2u, stats.substreams.size());
501 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
502 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
503}
504
505TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp9Svc) {
506 const int kInterframeDelayMs = 100;
507 rtc::ScopedFakeClock fake_global_clock;
508 EncodedImage encoded_image;
509 CodecSpecificInfo codec_info;
510 codec_info.codecType = kVideoCodecVP9;
511
512 for (int i = 0; i < 10; ++i) {
513 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
514 fake_global_clock.SetTime(
515 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
516 encoded_image.SetTimestamp(encoded_image.Timestamp() +
517 90 * kInterframeDelayMs);
518 encoded_image.SetSpatialIndex(0);
519 codec_info.end_of_picture = false;
520 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
521 encoded_image.SetSpatialIndex(1);
522 codec_info.end_of_picture = true;
523 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
524 }
525
526 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
527 EXPECT_EQ(1u, stats.substreams.size());
528 EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
529}
530
asapersson09f05612017-05-15 23:40:18 -0700531TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200532 VideoAdaptationCounters cpu_counts;
533 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700534 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700535 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200536 cpu_counts.fps_adaptations = 1;
537 cpu_counts.resolution_adaptations = 0;
538 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200539 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
540 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700541 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700542 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200543 cpu_counts.fps_adaptations = 0;
544 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200545 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
546 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700547 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700548 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200549 cpu_counts.fps_adaptations = 1;
550 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
551 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200552 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
553 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700554 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700555 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200556 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
557 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200558 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
559 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700560 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
561 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
562}
563
564TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200565 VideoAdaptationCounters cpu_counts;
566 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700567 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
568 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200569 quality_counts.fps_adaptations = 1;
570 quality_counts.resolution_adaptations = 0;
571 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200572 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
573 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700574 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
575 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200576 quality_counts.fps_adaptations = 0;
577 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200578 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
579 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700580 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
581 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200582 quality_counts.fps_adaptations = 1;
583 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
584 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200585 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
586 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700587 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
588 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200589 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
590 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200591 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
592 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700593 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
594 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
595}
596
597TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200598 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
599 VideoAdaptationCounters cpu_counts;
600 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700601 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
602
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);
asapersson09f05612017-05-15 23:40:18 -0700606 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700607 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
608 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
609
Evan Shrubsoledff79252020-04-16 11:34:32 +0200610 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200611 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
612 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700613 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
614 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700615 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700616 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700617}
618
asapersson09f05612017-05-15 23:40:18 -0700619TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200620 VideoAdaptationCounters cpu_counts;
621 VideoAdaptationCounters quality_counts;
622 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700623 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
624
Evan Shrubsoledff79252020-04-16 11:34:32 +0200625 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200626 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
627 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700628 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
629 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700630 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
631
Evan Shrubsoledff79252020-04-16 11:34:32 +0200632 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200633 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
634 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700635 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700636 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700637 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
638 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700639}
640
Evan Shrubsoledff79252020-04-16 11:34:32 +0200641TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
642 VideoAdaptationCounters cpu_counts;
643 VideoAdaptationCounters quality_counts;
644 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
645 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
646 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
647
648 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200649 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
650 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200651 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200652 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
653 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200654 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200655 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
656 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200657 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200658 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
659 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200660 // We have 1 fps and resolution reduction for both cpu and quality
661 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
662 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
663 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
664 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
665 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
666 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
667
668 // Disable quality scaling. Expect quality scaling not limited.
669 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
670 kScalingDisabled);
671 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
672 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
673 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
674 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
675 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
676 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
677
678 // Disable framerate scaling.
679 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
680 kFramerateScalingDisabled);
681 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
682 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
683 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
684 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
685 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
686 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
687
688 // Disable resolution scaling.
689 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
690 kResolutionScalingDisabled);
691 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
692 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
693 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
694 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
695 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
696 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
697
698 // Enable all
699 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
700 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
701 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
702 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
703 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
704 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
705 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
706}
707
asapersson09f05612017-05-15 23:40:18 -0700708TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700709 // First RTP packet sent.
710 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700711 // Min runtime has passed.
712 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
713 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100714 EXPECT_METRIC_EQ(
715 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
716 EXPECT_METRIC_EQ(
717 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700718}
719
720TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700721 // First RTP packet sent.
722 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700723 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200724 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700725 // Min runtime has not passed.
726 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
727 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100728 EXPECT_METRIC_EQ(
729 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
730 EXPECT_METRIC_EQ(
731 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700732}
733
asapersson09f05612017-05-15 23:40:18 -0700734TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700735 // First RTP packet sent.
736 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700737 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200738 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700739 // Min runtime has passed.
740 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
741 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100742 EXPECT_METRIC_EQ(
743 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
744 EXPECT_METRIC_EQ(
745 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
746 EXPECT_METRIC_EQ(
747 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
748 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700749 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
750}
751
752TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700753 // First RTP packet sent.
754 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700755 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200756 VideoAdaptationCounters cpu_counts;
757 VideoAdaptationCounters quality_counts;
758 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700759 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200760 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
761 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700762 fake_clock_.AdvanceTimeMilliseconds(10000);
763 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100764 EXPECT_METRIC_EQ(
765 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
766 EXPECT_METRIC_EQ(
767 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700768}
769
Åsa Persson875841d2018-01-08 08:49:53 +0100770TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
771 // First RTP packet sent.
772 UpdateDataCounters(kFirstSsrc);
773 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200774 VideoAdaptationCounters cpu_counts;
775 VideoAdaptationCounters quality_counts;
776 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100777 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200778 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
779 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100780 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
781 fake_clock_.AdvanceTimeMilliseconds(10000);
782 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100783 EXPECT_METRIC_EQ(
784 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
785 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100786 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
787}
788
789TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
790 // First RTP packet sent.
791 UpdateDataCounters(kFirstSsrc);
792 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200793 VideoAdaptationCounters cpu_counts;
794 VideoAdaptationCounters quality_counts;
795 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100796 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200797 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200798 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
799 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100800 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200801 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200802 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
803 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100804 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200805 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200806 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
807 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100808 fake_clock_.AdvanceTimeMilliseconds(10000);
809 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100810 EXPECT_METRIC_EQ(
811 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
812 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100813 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
814}
815
816TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
817 // First RTP packet sent.
818 UpdateDataCounters(kFirstSsrc);
819 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200820 VideoAdaptationCounters cpu_counts;
821 VideoAdaptationCounters quality_counts;
822 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100823 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200824 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
825 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100826 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
827 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
828 fake_clock_.AdvanceTimeMilliseconds(10000);
829 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100830 EXPECT_METRIC_EQ(
831 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
832 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100833 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
834}
835
836TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
837 // First RTP packet sent.
838 UpdateDataCounters(kFirstSsrc);
839 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200840 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
841 VideoAdaptationCounters cpu_counts;
842 VideoAdaptationCounters quality_counts;
843 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100844 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200845 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200846 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
847 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100848 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200849 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200850 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
851 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100852 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200853 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200854 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
855 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200856 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200857 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
858 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200859 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200860 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
861 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200862 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200863 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
864 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200865 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200866 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
867 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200868 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200869 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
870 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100871
872 fake_clock_.AdvanceTimeMilliseconds(10000);
873 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100874 EXPECT_METRIC_EQ(
875 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
876 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100877 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
878}
879
asapersson6eca98b2017-04-04 23:40:50 -0700880TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700881 // First RTP packet sent.
882 UpdateDataCounters(kFirstSsrc);
883
asapersson09f05612017-05-15 23:40:18 -0700884 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200885 VideoAdaptationCounters cpu_counts;
886 VideoAdaptationCounters quality_counts;
887 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
888 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700889 fake_clock_.AdvanceTimeMilliseconds(10000);
890
asapersson09f05612017-05-15 23:40:18 -0700891 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700892 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200893 quality_counts.fps_adaptations = 0;
894 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
895 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700896 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200897 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
898 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700899 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200900 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
901 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700902 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200903 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
904 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700905
asapersson09f05612017-05-15 23:40:18 -0700906 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200907 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
908 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700909 fake_clock_.AdvanceTimeMilliseconds(30000);
910
asapersson09f05612017-05-15 23:40:18 -0700911 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700912 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200913 quality_counts.resolution_adaptations = 0;
914 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
915 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200916 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
917 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700918 fake_clock_.AdvanceTimeMilliseconds(10000);
919
asapersson09f05612017-05-15 23:40:18 -0700920 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200921 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
922 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700923 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200924 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
925 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700926 fake_clock_.AdvanceTimeMilliseconds(20000);
927
asapersson0944a802017-04-07 00:57:58 -0700928 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700929 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100930 EXPECT_METRIC_EQ(
931 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
932 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700933 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
934}
935
asapersson0944a802017-04-07 00:57:58 -0700936TEST_F(SendStatisticsProxyTest,
937 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
938 // First RTP packet sent.
939 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700940
asapersson0944a802017-04-07 00:57:58 -0700941 // Suspend and resume video.
942 statistics_proxy_->OnSuspendChange(true);
943 fake_clock_.AdvanceTimeMilliseconds(5000);
944 statistics_proxy_->OnSuspendChange(false);
945
946 // Min runtime has passed but scaling not enabled.
947 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
948 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100949 EXPECT_METRIC_EQ(
950 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
951 EXPECT_METRIC_EQ(
952 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700953}
954
955TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
956 // First RTP packet sent.
957 UpdateDataCounters(kFirstSsrc);
958
asapersson09f05612017-05-15 23:40:18 -0700959 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200960 VideoAdaptationCounters cpu_counts;
961 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700962 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200963 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700964 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200965 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
966 cpu_counts, quality_counts);
967 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
968 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700969
970 // Suspend and resume video.
971 statistics_proxy_->OnSuspendChange(true);
972 fake_clock_.AdvanceTimeMilliseconds(30000);
973 statistics_proxy_->OnSuspendChange(false);
974
975 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200976 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
977 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700978 fake_clock_.AdvanceTimeMilliseconds(10000);
979
980 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
981 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100982 EXPECT_METRIC_EQ(
983 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
984 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700985 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
986}
987
988TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
989 // First RTP packet sent.
990 UpdateDataCounters(kFirstSsrc);
991
992 // Video not suspended.
993 statistics_proxy_->OnSuspendChange(false);
994 fake_clock_.AdvanceTimeMilliseconds(30000);
995
asapersson09f05612017-05-15 23:40:18 -0700996 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200997 VideoAdaptationCounters cpu_counts;
998 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700999 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001000 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001001 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001002 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1003 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001004
1005 // Video not suspended, stats time already started.
1006 statistics_proxy_->OnSuspendChange(false);
1007 fake_clock_.AdvanceTimeMilliseconds(10000);
1008
asapersson09f05612017-05-15 23:40:18 -07001009 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001010 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1011 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -07001012 fake_clock_.AdvanceTimeMilliseconds(30000);
1013
1014 // Suspend and resume video, stats time not started when scaling not enabled.
1015 statistics_proxy_->OnSuspendChange(true);
1016 fake_clock_.AdvanceTimeMilliseconds(30000);
1017 statistics_proxy_->OnSuspendChange(false);
1018 fake_clock_.AdvanceTimeMilliseconds(30000);
1019
asapersson09f05612017-05-15 23:40:18 -07001020 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -07001021 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001022 cpu_counts.fps_adaptations = 0;
1023 cpu_counts.resolution_adaptations = 0;
1024 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001025 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001026 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1027 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001028
1029 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
1030 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001031 EXPECT_METRIC_EQ(
1032 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1033 EXPECT_METRIC_EQ(
1034 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -07001035}
1036
1037TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
1038 // First RTP packet sent.
1039 UpdateDataCounters(kFirstSsrc);
1040
1041 // Video suspended.
1042 statistics_proxy_->OnSuspendChange(true);
1043
asapersson09f05612017-05-15 23:40:18 -07001044 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001045 VideoAdaptationCounters cpu_counts;
1046 VideoAdaptationCounters quality_counts;
1047 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001048 fake_clock_.AdvanceTimeMilliseconds(10000);
1049
1050 // Resume video, stats time started.
1051 // Adapt changes: 1, elapsed time: 10 sec.
1052 statistics_proxy_->OnSuspendChange(false);
1053 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001054 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1055 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001056
1057 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1058 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001059 EXPECT_METRIC_EQ(
1060 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1061 EXPECT_METRIC_EQ(
1062 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001063}
1064
1065TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001066 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001067 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001068 VideoAdaptationCounters cpu_counts;
1069 VideoAdaptationCounters quality_counts;
1070 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001071 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001072 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001073
asapersson0944a802017-04-07 00:57:58 -07001074 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001075 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001076 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1077 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001078 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001079
asapersson0944a802017-04-07 00:57:58 -07001080 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001081 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001082 EXPECT_METRIC_EQ(
1083 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1084 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001085 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1086}
1087
1088TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001089 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001090 VideoAdaptationCounters cpu_counts;
1091 VideoAdaptationCounters quality_counts;
1092 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001093 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001094 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1095 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001096
1097 // Send first packet, scaling disabled.
1098 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001099 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001100 fake_clock_.AdvanceTimeMilliseconds(60000);
1101
asapersson09f05612017-05-15 23:40:18 -07001102 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001103 cpu_counts.resolution_adaptations = 0;
1104 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1105 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001106 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001107 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001108
asapersson0944a802017-04-07 00:57:58 -07001109 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001110 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001111 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1112 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001113
asapersson0944a802017-04-07 00:57:58 -07001114 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001115 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001116 EXPECT_METRIC_EQ(
1117 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1118 EXPECT_METRIC_EQ(
1119 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001120}
1121
1122TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001123 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001124 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001125 VideoAdaptationCounters cpu_counts;
1126 VideoAdaptationCounters quality_counts;
1127 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1128 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001129
asapersson0944a802017-04-07 00:57:58 -07001130 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001131 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1132 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001133 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001134 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1135 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001136 fake_clock_.AdvanceTimeMilliseconds(9000);
1137
1138 // Switch content type, real-time stats should be updated.
1139 VideoEncoderConfig config;
1140 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001141 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001142 EXPECT_METRIC_EQ(
1143 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1144 EXPECT_METRIC_EQ(
1145 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1146 EXPECT_METRIC_EQ(
1147 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001148
asapersson0944a802017-04-07 00:57:58 -07001149 // First RTP packet sent, scaling enabled.
1150 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001151 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1152 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001153
asapersson0944a802017-04-07 00:57:58 -07001154 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001155 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1156 cpu_counts, quality_counts);
1157 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1158 cpu_counts, quality_counts);
1159 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1160 cpu_counts, quality_counts);
1161 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1162 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001163 fake_clock_.AdvanceTimeMilliseconds(120000);
1164
1165 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001166 EXPECT_METRIC_EQ(1,
1167 metrics::NumSamples(
1168 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1169 EXPECT_METRIC_EQ(
1170 1, metrics::NumEvents(
1171 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1172 EXPECT_METRIC_EQ(
1173 0, metrics::NumSamples(
1174 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001175}
1176
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001177TEST_F(SendStatisticsProxyTest,
1178 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001179 VideoAdaptationCounters cpu_counts;
1180 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001181
Evan Shrubsoledff79252020-04-16 11:34:32 +02001182 cpu_counts.resolution_adaptations = 1;
1183 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001184 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1185 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001186
1187 EXPECT_EQ(QualityLimitationReason::kCpu,
1188 statistics_proxy_->GetStats().quality_limitation_reason);
1189}
1190
1191TEST_F(SendStatisticsProxyTest,
1192 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001193 VideoAdaptationCounters cpu_counts;
1194 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001195
Evan Shrubsoledff79252020-04-16 11:34:32 +02001196 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001197
Evan Shrubsoledff79252020-04-16 11:34:32 +02001198 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001199 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1200 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001201
1202 EXPECT_EQ(QualityLimitationReason::kCpu,
1203 statistics_proxy_->GetStats().quality_limitation_reason);
1204}
1205
1206TEST_F(SendStatisticsProxyTest,
1207 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001208 VideoAdaptationCounters cpu_counts;
1209 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001210
Evan Shrubsoledff79252020-04-16 11:34:32 +02001211 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001212
Evan Shrubsoledff79252020-04-16 11:34:32 +02001213 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001214 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1215 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001216
1217 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1218 statistics_proxy_->GetStats().quality_limitation_reason);
1219}
1220
1221TEST_F(SendStatisticsProxyTest,
1222 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
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 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001227
Evan Shrubsoledff79252020-04-16 11:34:32 +02001228 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001229 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1230 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001231
1232 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1233 statistics_proxy_->GetStats().quality_limitation_reason);
1234}
1235
1236TEST_F(SendStatisticsProxyTest,
1237 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001238 VideoAdaptationCounters cpu_counts;
1239 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001240
Evan Shrubsoledff79252020-04-16 11:34:32 +02001241 cpu_counts.resolution_adaptations = 1;
1242 quality_counts.resolution_adaptations = 1;
1243 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001244
1245 // Even if the last adaptation reason is kCpu, if the counters indicate being
1246 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001247 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1248 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001249
1250 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1251 statistics_proxy_->GetStats().quality_limitation_reason);
1252}
1253
1254TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001255 VideoAdaptationCounters cpu_counts;
1256 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001257
1258 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1259 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001260 cpu_counts.resolution_adaptations = 1;
1261 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001262 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1263 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001264 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001265 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001266 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1267 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001268
1269 EXPECT_EQ(QualityLimitationReason::kNone,
1270 statistics_proxy_->GetStats().quality_limitation_reason);
1271}
1272
1273TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001274 VideoAdaptationCounters cpu_counts;
1275 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001276
Evan Shrubsoledff79252020-04-16 11:34:32 +02001277 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001278 // Not limited for 3000 ms
1279 fake_clock_.AdvanceTimeMilliseconds(3000);
1280 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001281 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001282 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1283 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001284 fake_clock_.AdvanceTimeMilliseconds(2000);
1285 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001286 cpu_counts.resolution_adaptations = 0;
1287 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001288 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1289 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001290 fake_clock_.AdvanceTimeMilliseconds(1000);
1291 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001292 cpu_counts.resolution_adaptations = 1;
1293 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001294 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1295 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001296 fake_clock_.AdvanceTimeMilliseconds(2000);
1297
1298 auto quality_limitation_durations_ms =
1299 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1300
1301 EXPECT_EQ(3000,
1302 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1303 EXPECT_EQ(4000,
1304 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1305 EXPECT_EQ(
1306 1000,
1307 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1308 EXPECT_EQ(0,
1309 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1310}
1311
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001312TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1313 EXPECT_EQ(
1314 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1315}
1316
1317TEST_F(SendStatisticsProxyTest,
1318 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1319 VideoCodec codec;
1320 VideoBitrateAllocation allocation;
1321 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1322 EXPECT_EQ(
1323 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1324}
1325
1326TEST_F(SendStatisticsProxyTest,
1327 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1328 VideoCodec codec;
1329 codec.simulcastStream[0].active = true;
1330 codec.simulcastStream[1].active = true;
1331 codec.simulcastStream[2].active = true;
1332 VideoBitrateAllocation allocation;
1333 allocation.SetBitrate(0, 0, 100);
1334 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1335 EXPECT_EQ(
1336 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1337}
1338
1339TEST_F(SendStatisticsProxyTest,
1340 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1341 VideoCodec codec;
1342 codec.simulcastStream[0].active = true;
1343 codec.simulcastStream[1].active = true;
1344 codec.simulcastStream[2].active = true;
1345 VideoBitrateAllocation allocation;
1346 allocation.SetBitrate(0, 0, 100);
1347 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1348 allocation.SetBitrate(1, 0, 100);
1349 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1350 EXPECT_EQ(
1351 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1352}
1353
1354TEST_F(SendStatisticsProxyTest,
1355 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1356 VideoCodec codec;
1357 codec.simulcastStream[0].active = true;
1358 VideoBitrateAllocation allocation;
1359 allocation.SetBitrate(0, 0, 100);
1360 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1361 // Layer 0 got more bandwidth, but still only one layer on
1362 allocation.SetBitrate(0, 0, 200);
1363 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1364 EXPECT_EQ(
1365 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1366}
1367
1368TEST_F(SendStatisticsProxyTest,
1369 QualityLimitationResolutionChangesWithTogglingLayers) {
1370 VideoCodec codec;
1371 codec.simulcastStream[0].active = true;
1372 codec.simulcastStream[1].active = true;
1373 codec.simulcastStream[2].active = true;
1374 VideoBitrateAllocation allocation;
1375 allocation.SetBitrate(0, 0, 100);
1376 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1377 EXPECT_EQ(
1378 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1379 allocation.SetBitrate(1, 0, 300);
1380 allocation.SetBitrate(2, 0, 500);
1381 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1382 EXPECT_EQ(
1383 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1384 // Layer 2 off
1385 allocation.SetBitrate(2, 0, 0);
1386 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1387 EXPECT_EQ(
1388 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1389 // Layer 2 back on
1390 allocation.SetBitrate(2, 0, 500);
1391 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1392 EXPECT_EQ(
1393 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1394 allocation.SetBitrate(0, 0, 0);
1395 allocation.SetBitrate(1, 0, 0);
1396 allocation.SetBitrate(2, 0, 0);
1397 // All layers off
1398 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1399 EXPECT_EQ(
1400 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1401}
1402
1403TEST_F(SendStatisticsProxyTest,
1404 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1405 VideoCodec codec;
1406 // 3 layers
1407 codec.simulcastStream[0].active = true;
1408 codec.simulcastStream[1].active = true;
1409 codec.simulcastStream[2].active = true;
1410 VideoBitrateAllocation allocation;
1411 allocation.SetBitrate(0, 0, 500);
1412 allocation.SetBitrate(1, 0, 500);
1413 allocation.SetBitrate(2, 0, 500);
1414 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1415 EXPECT_EQ(
1416 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1417
1418 // Down to one layer now, triggered by a config change
1419 codec.numberOfSimulcastStreams = 1;
1420 codec.simulcastStream[1].active = false;
1421 codec.simulcastStream[2].active = false;
1422 allocation.SetBitrate(0, 0, 100);
1423 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1424 EXPECT_EQ(
1425 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1426
1427 // Up to 3 layers again.
1428 codec.numberOfSimulcastStreams = 3;
1429 codec.simulcastStream[1].active = true;
1430 codec.simulcastStream[2].active = true;
1431 allocation.SetBitrate(0, 0, 500);
1432 allocation.SetBitrate(1, 0, 500);
1433 allocation.SetBitrate(2, 0, 500);
1434 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1435 EXPECT_EQ(
1436 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1437}
1438
1439TEST_F(SendStatisticsProxyTest,
1440 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1441 VideoCodec codec;
1442 codec.simulcastStream[0].active = true;
1443 codec.spatialLayers[0].active = true;
1444 codec.spatialLayers[1].active = true;
1445 codec.spatialLayers[2].active = true;
1446 VideoBitrateAllocation allocation;
1447 allocation.SetBitrate(0, 0, 500);
1448 allocation.SetBitrate(1, 0, 500);
1449 allocation.SetBitrate(2, 0, 500);
1450 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1451 EXPECT_EQ(
1452 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1453
1454 // Down to one layer now, triggered by a config change
1455 codec.spatialLayers[1].active = false;
1456 codec.spatialLayers[2].active = false;
1457 allocation.SetBitrate(0, 0, 100);
1458 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1459 EXPECT_EQ(
1460 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1461
1462 // Up to 3 layers again.
1463 codec.spatialLayers[1].active = true;
1464 codec.spatialLayers[2].active = true;
1465 allocation.SetBitrate(0, 0, 500);
1466 allocation.SetBitrate(1, 0, 500);
1467 allocation.SetBitrate(2, 0, 500);
1468 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1469 EXPECT_EQ(
1470 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1471}
1472
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001473TEST_F(SendStatisticsProxyTest,
1474 QualityLimitationReasonsAreCorrectForContentType) {
1475 // Realtime case.
1476 // Configure two streams.
1477 VideoEncoderConfig config;
1478 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1479 config.number_of_streams = 2;
1480 VideoStream stream1;
1481 stream1.width = kWidth / 2;
1482 stream1.height = kHeight / 2;
1483 VideoStream stream2;
1484 stream2.width = kWidth;
1485 stream2.height = kHeight;
1486 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1487 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1488 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1489 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1490 QualityLimitationReason::kNone);
1491 // Bw disabled one layer.
1492 VideoCodec codec;
1493 codec.numberOfSimulcastStreams = 2;
1494 codec.simulcastStream[0].active = true;
1495 codec.simulcastStream[1].active = true;
1496 VideoBitrateAllocation allocation;
1497 // Some positive bitrate only on the first stream.
1498 allocation.SetBitrate(0, 0, 10000);
1499 allocation.SetBitrate(1, 0, 0);
1500 allocation.set_bw_limited(true);
1501 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1502 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1503 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1504 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1505 QualityLimitationReason::kBandwidth);
1506 // Bw enabled all layers.
1507 allocation.SetBitrate(1, 0, 10000);
1508 allocation.set_bw_limited(false);
1509 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1510 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1511 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1512 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1513 QualityLimitationReason::kNone);
1514
1515 // Screencast case
1516 // Configure two streams.
1517 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1518 config.number_of_streams = 2;
1519 stream1.width = kWidth;
1520 stream1.height = kHeight;
1521 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1522 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1523 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1524 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1525 QualityLimitationReason::kNone);
1526 // Bw disabled one layer.
1527 // Some positive bitrate only on the second stream.
1528 allocation.SetBitrate(0, 0, 10000);
1529 allocation.SetBitrate(1, 0, 0);
1530 allocation.set_bw_limited(true);
1531 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1532 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1533 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1534 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1535 QualityLimitationReason::kBandwidth);
1536 // Bw enabled all layers.
1537 allocation.SetBitrate(1, 0, 10000);
1538 allocation.set_bw_limited(false);
1539 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1540 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1541 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1542 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1543 QualityLimitationReason::kNone);
1544}
1545
asapersson59bac1a2016-01-07 23:36:00 -08001546TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001547 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001548 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1549
Pera48ddb72016-09-29 11:48:50 +02001550 // No switch, stats should not be updated.
1551 VideoEncoderConfig config;
1552 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001553 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001554 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001555
1556 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001557 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001558 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001559 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001560}
1561
asapersson320e45a2016-11-29 01:40:35 -08001562TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1563 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1564 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001565
asapersson320e45a2016-11-29 01:40:35 -08001566 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001567 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1568 EXPECT_METRIC_EQ(
1569 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1570 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1571 EXPECT_METRIC_EQ(
1572 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001573}
1574
1575TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001576 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001577 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001578 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1579 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1580 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001581 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001582
1583 // Not enough samples, stats should not be updated.
1584 for (int i = 0; i < kMinSamples - 1; ++i) {
1585 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001586 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001587 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1588 }
Åsa Persson0122e842017-10-16 12:19:23 +02001589 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001590 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1591 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001592
1593 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001594 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001595 for (int i = 0; i < kMinSamples; ++i) {
1596 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001597 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001598 encoded_image._encodedWidth = kWidth;
1599 encoded_image._encodedHeight = kHeight;
1600 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1601 encoded_image._encodedWidth = kWidth / 2;
1602 encoded_image._encodedHeight = kHeight / 2;
1603 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1604 }
1605
asapersson320e45a2016-11-29 01:40:35 -08001606 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001607 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1608 EXPECT_METRIC_EQ(
1609 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1610 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1611 EXPECT_METRIC_EQ(
1612 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001613}
1614
1615TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1616 const int kFps = 20;
1617 const int kMinPeriodicSamples = 6;
1618 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1619 for (int i = 0; i <= frames; ++i) {
1620 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1621 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1622 }
1623 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001624 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1625 EXPECT_METRIC_EQ(
1626 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001627}
1628
1629TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1630 EncodedImage encoded_image;
1631 const int kFps = 20;
1632 const int kMinPeriodicSamples = 6;
1633 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001634 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001635 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001636 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001637 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1638 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001639 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1640 }
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
1647TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1648 const int kFps = 20;
1649 const int kSuspendTimeMs = 10000;
1650 const int kMinPeriodicSamples = 6;
1651 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1652 for (int i = 0; i < frames; ++i) {
1653 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1654 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1655 }
1656 // Suspend.
1657 statistics_proxy_->OnSuspendChange(true);
1658 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1659
1660 for (int i = 0; i < frames; ++i) {
1661 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1662 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1663 }
1664 // Suspended time interval should not affect the framerate.
1665 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001666 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1667 EXPECT_METRIC_EQ(
1668 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001669}
1670
1671TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1672 EncodedImage encoded_image;
1673 const int kFps = 20;
1674 const int kSuspendTimeMs = 10000;
1675 const int kMinPeriodicSamples = 6;
1676 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001677 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001678 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001679 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001680 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1681 }
1682 // Suspend.
1683 statistics_proxy_->OnSuspendChange(true);
1684 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1685
Åsa Persson0122e842017-10-16 12:19:23 +02001686 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001687 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001688 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001689 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1690 }
1691 // Suspended time interval should not affect the framerate.
1692 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001693 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1694 EXPECT_METRIC_EQ(
1695 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001696}
1697
asaperssonf4e44af2017-04-19 02:01:06 -07001698TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001699 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1700 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001701
1702 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1703 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1704
1705 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001706 EXPECT_METRIC_EQ(
1707 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001708}
1709
1710TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001711 VideoAdaptationCounters cpu_counts;
1712 VideoAdaptationCounters quality_counts;
1713 cpu_counts.resolution_adaptations = 0;
1714 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001715
perkj803d97f2016-11-01 11:45:46 -07001716 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1717 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1718
Evan Shrubsoledff79252020-04-16 11:34:32 +02001719 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001720 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1721 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001722
1723 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1724 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1725
1726 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001727 EXPECT_METRIC_EQ(
1728 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1729 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001730 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1731}
1732
asapersson4374a092016-07-27 00:39:09 -07001733TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1734 const int64_t kTimeSec = 3;
1735 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1736 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001737 EXPECT_METRIC_EQ(
1738 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1739 EXPECT_METRIC_EQ(
1740 1,
1741 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001742}
1743
1744TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1745 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1746 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001747 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001748}
1749
asapersson66d4b372016-12-19 06:50:53 -08001750TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1751 // First RTP packet sent.
1752 UpdateDataCounters(kFirstSsrc);
1753
1754 // Min runtime has passed.
1755 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1756 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001757 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1758 EXPECT_METRIC_EQ(1,
1759 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001760}
1761
1762TEST_F(SendStatisticsProxyTest,
1763 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1764 // First RTP packet sent.
1765 UpdateDataCounters(kFirstSsrc);
1766
1767 // Min runtime has not passed.
1768 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1769 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001770 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1771 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001772}
1773
1774TEST_F(SendStatisticsProxyTest,
1775 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1776 // First RTP packet not sent.
1777 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1778 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001779 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001780}
1781
1782TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1783 // First RTP packet sent and min runtime passed.
1784 UpdateDataCounters(kFirstSsrc);
1785
1786 // No change. Video: 10000 ms, paused: 0 ms (0%).
1787 statistics_proxy_->OnSetEncoderTargetRate(50000);
1788 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1789 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1790
1791 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001792 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1793 EXPECT_METRIC_EQ(1,
1794 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1795 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1796 EXPECT_METRIC_EQ(1,
1797 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001798}
1799
1800TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1801 // First RTP packet sent and min runtime passed.
1802 UpdateDataCounters(kFirstSsrc);
1803
1804 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1805 statistics_proxy_->OnSetEncoderTargetRate(50000);
1806 fake_clock_.AdvanceTimeMilliseconds(7000);
1807 statistics_proxy_->OnSetEncoderTargetRate(0);
1808 fake_clock_.AdvanceTimeMilliseconds(3000);
1809 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1810
1811 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001812 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1813 EXPECT_METRIC_EQ(1,
1814 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1815 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1816 EXPECT_METRIC_EQ(1,
1817 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001818}
1819
1820TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1821 // First RTP packet sent.
1822 UpdateDataCounters(kFirstSsrc);
1823
1824 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1825 statistics_proxy_->OnSetEncoderTargetRate(0);
1826 fake_clock_.AdvanceTimeMilliseconds(1000);
1827 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1828 fake_clock_.AdvanceTimeMilliseconds(7000);
1829 statistics_proxy_->OnSetEncoderTargetRate(60000);
1830 fake_clock_.AdvanceTimeMilliseconds(3000);
1831 statistics_proxy_->OnSetEncoderTargetRate(0);
1832 fake_clock_.AdvanceTimeMilliseconds(250);
1833 statistics_proxy_->OnSetEncoderTargetRate(0);
1834 fake_clock_.AdvanceTimeMilliseconds(750);
1835 statistics_proxy_->OnSetEncoderTargetRate(60000);
1836 fake_clock_.AdvanceTimeMilliseconds(5000);
1837 statistics_proxy_->OnSetEncoderTargetRate(50000);
1838 fake_clock_.AdvanceTimeMilliseconds(4000);
1839 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1840
1841 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001842 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1843 EXPECT_METRIC_EQ(1,
1844 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1845 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1846 EXPECT_METRIC_EQ(1,
1847 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001848}
1849
1850TEST_F(SendStatisticsProxyTest,
1851 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1852 // First RTP packet sent.
1853 UpdateDataCounters(kFirstSsrc);
1854 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1855
1856 // Min runtime has not passed.
1857 statistics_proxy_->OnSetEncoderTargetRate(50000);
1858 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1859 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1860
1861 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001862 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001863}
1864
asapersson118ef002016-03-31 00:00:19 -07001865TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001866 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001867 CodecSpecificInfo codec_info;
1868 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001869
perkj803d97f2016-11-01 11:45:46 -07001870 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001871 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001872 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001873 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001874 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001875 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001876 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001877 }
1878 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001879 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1880 EXPECT_METRIC_EQ(
1881 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1882 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1883 EXPECT_METRIC_EQ(
1884 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001885}
1886
1887TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1888 VideoSendStream::Config config(nullptr);
1889 config.rtp.ssrcs.push_back(kFirstSsrc);
1890 statistics_proxy_.reset(new SendStatisticsProxy(
1891 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1892
asapersson118ef002016-03-31 00:00:19 -07001893 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001894 CodecSpecificInfo codec_info;
1895 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001896
perkj803d97f2016-11-01 11:45:46 -07001897 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001898 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001899 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001900 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001901 }
1902 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001903 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1904 EXPECT_METRIC_EQ(1,
1905 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001906}
1907
asapersson5265fed2016-04-18 02:58:47 -07001908TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001909 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001910 CodecSpecificInfo codec_info;
1911 codec_info.codecType = kVideoCodecVP9;
1912 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001913
perkj803d97f2016-11-01 11:45:46 -07001914 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001915 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001916 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001917 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001918 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001919 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001920 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001921 }
1922 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001923 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1924 EXPECT_METRIC_EQ(
1925 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1926 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1927 EXPECT_METRIC_EQ(
1928 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001929}
1930
1931TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1932 VideoSendStream::Config config(nullptr);
1933 config.rtp.ssrcs.push_back(kFirstSsrc);
1934 statistics_proxy_.reset(new SendStatisticsProxy(
1935 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1936
asapersson5265fed2016-04-18 02:58:47 -07001937 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001938 CodecSpecificInfo codec_info;
1939 codec_info.codecType = kVideoCodecVP9;
1940 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001941
perkj803d97f2016-11-01 11:45:46 -07001942 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001943 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001944 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001945 }
1946 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001947 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1948 EXPECT_METRIC_EQ(1,
1949 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001950}
1951
asapersson827cab32016-11-02 09:08:47 -07001952TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1953 EncodedImage encoded_image;
1954 CodecSpecificInfo codec_info;
1955 codec_info.codecType = kVideoCodecH264;
1956
1957 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001958 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001959 encoded_image.qp_ = kQpIdx0;
1960 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001961 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001962 encoded_image.qp_ = kQpIdx1;
1963 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001964 }
1965 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001966 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1967 EXPECT_METRIC_EQ(
1968 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1969 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1970 EXPECT_METRIC_EQ(
1971 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001972}
1973
asapersson4ee70462016-10-31 04:05:12 -07001974TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001975 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1976 // Configure one stream.
1977 VideoEncoderConfig config;
1978 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1979 VideoStream stream1;
1980 stream1.width = kWidth;
1981 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001982 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001983
1984 const int64_t kMaxEncodedFrameWindowMs = 800;
1985 const int kFps = 20;
1986 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1987 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1988 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1989
1990 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001991 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001992 encoded_image._encodedWidth = kWidth;
1993 encoded_image._encodedHeight = kHeight;
1994 for (int i = 0; i < kMinSamples; ++i) {
1995 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001996 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1997 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001998 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001999 }
asapersson4ee70462016-10-31 04:05:12 -07002000
2001 // Histograms are updated when the statistics_proxy_ is deleted.
2002 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002003 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2004 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2005 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2006 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002007}
2008
2009TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002010 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
2011 // Configure two streams.
2012 VideoEncoderConfig config;
2013 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2014 VideoStream stream1;
2015 stream1.width = kWidth / 2;
2016 stream1.height = kHeight / 2;
2017 VideoStream stream2;
2018 stream2.width = kWidth;
2019 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002020 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002021
2022 const int64_t kMaxEncodedFrameWindowMs = 800;
2023 const int kFps = 20;
2024 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2025 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2026 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2027
2028 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07002029 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002030 for (int i = 0; i < kMinSamples; ++i) {
2031 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002032 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2033 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002034 encoded_image._encodedWidth = kWidth;
2035 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07002036 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002037 encoded_image._encodedWidth = kWidth / 2;
2038 encoded_image._encodedHeight = kHeight / 2;
2039 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2040 }
asapersson4ee70462016-10-31 04:05:12 -07002041
2042 // Histograms are updated when the statistics_proxy_ is deleted.
2043 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002044 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2045 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2046 EXPECT_METRIC_EQ(
2047 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2048 0));
asapersson4ee70462016-10-31 04:05:12 -07002049 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002050 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2051 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07002052}
2053
2054TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01002055 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2056 // Configure two streams.
2057 VideoEncoderConfig config;
2058 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2059 VideoStream stream1;
2060 stream1.width = kWidth / 2;
2061 stream1.height = kHeight / 2;
2062 VideoStream stream2;
2063 stream2.width = kWidth;
2064 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002065 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002066
2067 const int64_t kMaxEncodedFrameWindowMs = 800;
2068 const int kFps = 20;
2069 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2070 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2071 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2072
2073 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002074 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002075 encoded_image._encodedWidth = kWidth / 2;
2076 encoded_image._encodedHeight = kHeight / 2;
2077 for (int i = 0; i < kMinSamples; ++i) {
2078 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002079 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2080 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002081 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002082 }
asapersson4ee70462016-10-31 04:05:12 -07002083
2084 // Histograms are updated when the statistics_proxy_ is deleted.
2085 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002086 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2087 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2088 EXPECT_METRIC_EQ(
2089 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2090 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002091 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002092 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2093 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2094 EXPECT_METRIC_EQ(
2095 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2096 1));
asapersson4ee70462016-10-31 04:05:12 -07002097}
2098
2099TEST_F(SendStatisticsProxyTest,
2100 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002101 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2102 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002103 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002104 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002105 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002106 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002107
2108 // Histograms are updated when the statistics_proxy_ is deleted.
2109 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002110 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002111 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002112 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2113 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002114}
2115
2116TEST_F(SendStatisticsProxyTest,
2117 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002118 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002119 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002120 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002121 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002122 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002123
2124 // Histograms are updated when the statistics_proxy_ is deleted.
2125 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002126 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002127 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002128 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2129 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002130 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002131 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2132 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002133}
2134
2135TEST_F(SendStatisticsProxyTest,
2136 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2137 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002138 VideoAdaptationCounters cpu_counts;
2139 VideoAdaptationCounters quality_counts;
2140 quality_counts.resolution_adaptations = kDownscales;
2141 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002142 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2143 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002144 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002145 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002146 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002147 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002148 // Histograms are updated when the statistics_proxy_ is deleted.
2149 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002150 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002151 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002152 EXPECT_METRIC_EQ(
2153 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2154 100));
asapersson4ee70462016-10-31 04:05:12 -07002155 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002156 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2157 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2158 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002159 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2160 kDownscales));
2161}
2162
2163TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2164 // Initially false.
2165 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002166
Åsa Perssonaa329e72017-12-15 15:54:44 +01002167 // Configure two streams.
2168 VideoEncoderConfig config;
2169 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002170 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002171 VideoStream stream1;
2172 stream1.width = kWidth / 2;
2173 stream1.height = kHeight / 2;
2174 VideoStream stream2;
2175 stream2.width = kWidth;
2176 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002177 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002178
Åsa Perssonaa329e72017-12-15 15:54:44 +01002179 // One stream encoded.
2180 EncodedImage encoded_image;
2181 encoded_image._encodedWidth = kWidth / 2;
2182 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002183
2184 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002185 VideoAdaptationCounters cpu_counts;
2186 VideoAdaptationCounters quality_counts;
2187 quality_counts.resolution_adaptations = 1;
2188 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2189 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002190 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2191 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002192 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2193 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002194
2195 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002196 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002197 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2198 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002199 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2200 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2201
2202 // Bw disabled one layer.
2203 VideoCodec codec;
2204 codec.numberOfSimulcastStreams = 2;
2205 codec.simulcastStream[0].active = true;
2206 codec.simulcastStream[1].active = true;
2207 VideoBitrateAllocation allocation;
2208 // Some positive bitrate only on the second stream.
2209 allocation.SetBitrate(1, 0, 10000);
2210 allocation.set_bw_limited(true);
2211 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2212 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002213
2214 // Revert for the next test.
2215 allocation.set_bw_limited(false);
2216 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2217 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2218
2219 // Internal encoder scaler reduced resolution.
2220 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2221 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002222}
2223
asapersson66d4b372016-12-19 06:50:53 -08002224TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2225 // Initially zero.
2226 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2227
2228 const int kBitrate = 100000;
2229 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2230 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2231
2232 statistics_proxy_->OnSetEncoderTargetRate(0);
2233 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2234}
2235
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002236TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002237 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002238 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2239 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002240 1;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002241 // From ReportBlockDataObserver.
2242 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2243 RTCPReportBlock report_block;
2244 report_block.source_ssrc = excluded_ssrc;
2245 ReportBlockData data;
2246 data.SetReportBlock(report_block, 0);
2247 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002248
2249 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002250 uint32_t total = 0;
2251 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002252 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002253 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002254
2255 // From FrameCountObserver.
2256 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002257 FrameCounts frame_counts;
2258 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002259 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002260
2261 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2262 EXPECT_TRUE(stats.substreams.empty());
2263}
2264
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002265TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2266 static const int kEncodedWidth = 123;
2267 static const int kEncodedHeight = 81;
2268 EncodedImage encoded_image;
2269 encoded_image._encodedWidth = kEncodedWidth;
2270 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002271 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002272
kjellander02b3d272016-04-20 05:05:54 -07002273 CodecSpecificInfo codec_info;
2274 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002275
kjellander02b3d272016-04-20 05:05:54 -07002276 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002277 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002278 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002279
2280 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002281 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2282 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2283 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2284 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002285
2286 // Forward almost to timeout, this should not have removed stats.
2287 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2288 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002289 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2290 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002291
2292 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2293 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002294 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2295 RTCPReportBlock report_block;
2296 report_block.source_ssrc = config_.rtp.ssrcs[0];
2297 ReportBlockData data;
2298 data.SetReportBlock(report_block, 0);
2299 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002300
2301 // Report stats for second SSRC to make sure it's not outdated along with the
2302 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002303 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002304
2305 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2306 // reported, but substream 1 should.
2307 fake_clock_.AdvanceTimeMilliseconds(1);
2308 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002309 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2310 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2311 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2312 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002313}
2314
Peter Boström20f3f942015-05-15 11:33:39 +02002315TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2316 static const int kEncodedWidth = 123;
2317 static const int kEncodedHeight = 81;
2318 EncodedImage encoded_image;
2319 encoded_image._encodedWidth = kEncodedWidth;
2320 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002321 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002322
kjellander02b3d272016-04-20 05:05:54 -07002323 CodecSpecificInfo codec_info;
2324 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002325
kjellander02b3d272016-04-20 05:05:54 -07002326 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002327 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002328 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002329
2330 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2331 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2332 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2333 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2334 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2335 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2336}
2337
2338TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002339 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002340 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2341 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2342 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2343
2344 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2345
2346 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002347 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002348 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002349 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002350 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2351 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2352 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2353}
2354
sprang07fb9be2016-02-24 07:55:00 -08002355TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2356 RtcpPacketTypeCounterObserver* proxy =
2357 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2358 RtcpPacketTypeCounter counters;
2359 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2360 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2361 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2362
2363 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2364
2365 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2366 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2367 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2368 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2369 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2370
2371 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2372 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2373
2374 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002375 VideoEncoderConfig config;
2376 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002377 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002378
Ying Wangef3998f2019-12-09 13:06:53 +01002379 EXPECT_METRIC_EQ(
2380 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2381 EXPECT_METRIC_EQ(
2382 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2383 EXPECT_METRIC_EQ(
2384 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2385 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2386 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002387
2388 const int kRate = 60 * 2; // Packets per minute with two streams.
2389
Ying Wangef3998f2019-12-09 13:06:53 +01002390 EXPECT_METRIC_EQ(
2391 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2392 1 * kRate));
2393 EXPECT_METRIC_EQ(
2394 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2395 2 * kRate));
2396 EXPECT_METRIC_EQ(
2397 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2398 3 * kRate));
2399 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002400 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2401 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002402
2403 // New start time but same counter values.
2404 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2405 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2406
2407 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2408
2409 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2410 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2411 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2412 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2413 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2414
2415 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2416 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2417
2418 SetUp(); // Reset stats proxy also causes histograms to be reported.
2419
Ying Wangef3998f2019-12-09 13:06:53 +01002420 EXPECT_METRIC_EQ(
2421 1, metrics::NumSamples(
2422 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2423 EXPECT_METRIC_EQ(1,
2424 metrics::NumSamples(
2425 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2426 EXPECT_METRIC_EQ(1,
2427 metrics::NumSamples(
2428 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2429 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002430 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002431 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2432
Ying Wangef3998f2019-12-09 13:06:53 +01002433 EXPECT_METRIC_EQ(
2434 1,
2435 metrics::NumEvents(
2436 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2437 EXPECT_METRIC_EQ(
2438 1,
2439 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2440 2 * kRate));
2441 EXPECT_METRIC_EQ(
2442 1,
2443 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2444 3 * kRate));
2445 EXPECT_METRIC_EQ(
2446 1, metrics::NumEvents(
2447 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2448 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002449}
2450
Henrik Boströmf45ca372020-03-24 13:30:50 +01002451TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2452 StreamDataCountersCallback* proxy =
2453 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2454 StreamDataCounters counters;
2455 proxy->DataCountersUpdated(counters, kFirstSsrc);
2456 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2457
2458 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2459 VideoSendStream::StreamStats::StreamType::kRtx);
2460 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2461 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2462 VideoSendStream::StreamStats::StreamType::kRtx);
2463 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2464}
2465
asaperssona6a699a2016-11-25 03:52:46 -08002466TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2467 statistics_proxy_.reset(
2468 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2469 VideoEncoderConfig::ContentType::kRealtimeVideo));
2470
2471 StreamDataCountersCallback* proxy =
2472 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2473 StreamDataCounters counters;
2474 proxy->DataCountersUpdated(counters, kFirstSsrc);
2475 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2476
Henrik Boströmf45ca372020-03-24 13:30:50 +01002477 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2478 VideoSendStream::StreamStats::StreamType::kFlexfec);
2479 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2480 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2481 VideoSendStream::StreamStats::StreamType::kFlexfec);
2482 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002483}
2484
2485TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2486 statistics_proxy_.reset(
2487 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2488 VideoEncoderConfig::ContentType::kRealtimeVideo));
2489
2490 StreamDataCountersCallback* proxy =
2491 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002492 StreamDataCounters counters;
2493 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002494
asapersson93e1e232017-02-06 05:18:35 -08002495 const int kMinRequiredPeriodSamples = 8;
2496 const int kPeriodIntervalMs = 2000;
2497 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2498 counters.transmitted.packets += 20;
2499 counters.transmitted.header_bytes += 500;
2500 counters.transmitted.padding_bytes += 1000;
2501 counters.transmitted.payload_bytes += 2000;
2502 counters.retransmitted.packets += 2;
2503 counters.retransmitted.header_bytes += 25;
2504 counters.retransmitted.padding_bytes += 100;
2505 counters.retransmitted.payload_bytes += 250;
2506 counters.fec = counters.retransmitted;
2507 rtx_counters.transmitted = counters.transmitted;
2508 // Advance one interval and update counters.
2509 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2510 proxy->DataCountersUpdated(counters, kFirstSsrc);
2511 proxy->DataCountersUpdated(counters, kSecondSsrc);
2512 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2513 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2514 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2515 }
asaperssona6a699a2016-11-25 03:52:46 -08002516
asaperssona6a699a2016-11-25 03:52:46 -08002517 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002518 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002519 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2520 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002521 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002522 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2523 EXPECT_METRIC_EQ(1,
2524 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002525 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002526 EXPECT_METRIC_EQ(1,
2527 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2528 EXPECT_METRIC_EQ(
2529 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002530 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002531 EXPECT_METRIC_EQ(
2532 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2533 EXPECT_METRIC_EQ(
2534 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002535 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002536 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2537 EXPECT_METRIC_EQ(1,
2538 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002539 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002540 EXPECT_METRIC_EQ(
2541 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2542 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002543 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002544}
2545
Erik Språng22c2b482016-03-01 09:40:42 +01002546TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2547 StreamDataCountersCallback* proxy =
2548 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2549 StreamDataCounters counters;
2550 StreamDataCounters rtx_counters;
2551 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002552
asapersson93e1e232017-02-06 05:18:35 -08002553 const int kMinRequiredPeriodSamples = 8;
2554 const int kPeriodIntervalMs = 2000;
2555 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2556 counters.transmitted.packets += 20;
2557 counters.transmitted.header_bytes += 500;
2558 counters.transmitted.padding_bytes += 1000;
2559 counters.transmitted.payload_bytes += 2000;
2560 counters.retransmitted.packets += 2;
2561 counters.retransmitted.header_bytes += 25;
2562 counters.retransmitted.padding_bytes += 100;
2563 counters.retransmitted.payload_bytes += 250;
2564 counters.fec = counters.retransmitted;
2565 rtx_counters.transmitted = counters.transmitted;
2566 // Advance one interval and update counters.
2567 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2568 proxy->DataCountersUpdated(counters, kFirstSsrc);
2569 proxy->DataCountersUpdated(counters, kSecondSsrc);
2570 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2571 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2572 }
Erik Språng22c2b482016-03-01 09:40:42 +01002573
2574 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002575 VideoEncoderConfig config;
2576 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002577 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002578
asapersson93e1e232017-02-06 05:18:35 -08002579 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002580 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2581 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002582 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002583 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2584 EXPECT_METRIC_EQ(1,
2585 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002586 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002587 EXPECT_METRIC_EQ(1,
2588 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2589 EXPECT_METRIC_EQ(
2590 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002591 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002592 EXPECT_METRIC_EQ(
2593 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2594 EXPECT_METRIC_EQ(
2595 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002596 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002597 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2598 EXPECT_METRIC_EQ(1,
2599 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002600 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002601 EXPECT_METRIC_EQ(
2602 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2603 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002604 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002605
asapersson93e1e232017-02-06 05:18:35 -08002606 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002607 // Double counter values, this should result in the same counts as before but
2608 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002609 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2610 counters.transmitted.packets += 20;
2611 counters.transmitted.header_bytes += 500;
2612 counters.transmitted.padding_bytes += 1000;
2613 counters.transmitted.payload_bytes += 2000;
2614 counters.retransmitted.packets += 2;
2615 counters.retransmitted.header_bytes += 25;
2616 counters.retransmitted.padding_bytes += 100;
2617 counters.retransmitted.payload_bytes += 250;
2618 counters.fec = counters.retransmitted;
2619 rtx_counters.transmitted = counters.transmitted;
2620 // Advance one interval and update counters.
2621 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2622 proxy->DataCountersUpdated(counters, kFirstSsrc);
2623 proxy->DataCountersUpdated(counters, kSecondSsrc);
2624 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2625 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2626 }
Erik Språng22c2b482016-03-01 09:40:42 +01002627
asapersson93e1e232017-02-06 05:18:35 -08002628 // Reset stats proxy also causes histograms to be reported.
2629 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002630
asapersson93e1e232017-02-06 05:18:35 -08002631 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002632 EXPECT_METRIC_EQ(
2633 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2634 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002635 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2636 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002637 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002638 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002639 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2640 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002641 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002642 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2643 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2644 EXPECT_METRIC_EQ(
2645 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2646 12));
asapersson93e1e232017-02-06 05:18:35 -08002647 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002648 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2649 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2650 EXPECT_METRIC_EQ(
2651 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2652 16));
asapersson93e1e232017-02-06 05:18:35 -08002653 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002654 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002655 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002656 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2657 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002658 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002659 EXPECT_METRIC_EQ(
2660 1, metrics::NumSamples(
2661 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2662 EXPECT_METRIC_EQ(
2663 1, metrics::NumEvents(
2664 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002665}
Erik Språng22c2b482016-03-01 09:40:42 +01002666
asapersson93e1e232017-02-06 05:18:35 -08002667TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2668 StreamDataCountersCallback* proxy =
2669 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2670 StreamDataCounters counters;
2671 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002672
asapersson93e1e232017-02-06 05:18:35 -08002673 const int kMinRequiredPeriodSamples = 8;
2674 const int kPeriodIntervalMs = 2000;
2675 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2676 counters.transmitted.packets += 20;
2677 counters.transmitted.header_bytes += 500;
2678 counters.transmitted.payload_bytes += 2000;
2679 counters.fec = counters.retransmitted;
2680 // Advance one interval and update counters.
2681 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2682 proxy->DataCountersUpdated(counters, kFirstSsrc);
2683 }
2684
2685 // RTX enabled. No data sent over RTX.
2686 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002687 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2688 EXPECT_METRIC_EQ(1,
2689 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002690}
2691
2692TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2693 VideoSendStream::Config config(nullptr);
2694 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX 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 // RTX not enabled.
2715 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002716 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002717}
2718
2719TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2720 StreamDataCountersCallback* proxy =
2721 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2722 StreamDataCounters counters;
2723 StreamDataCounters rtx_counters;
2724
2725 const int kMinRequiredPeriodSamples = 8;
2726 const int kPeriodIntervalMs = 2000;
2727 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2728 counters.transmitted.packets += 20;
2729 counters.transmitted.header_bytes += 500;
2730 counters.transmitted.payload_bytes += 2000;
2731 // Advance one interval and update counters.
2732 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2733 proxy->DataCountersUpdated(counters, kFirstSsrc);
2734 }
2735
2736 // FEC enabled. No FEC data sent.
2737 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002738 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2739 EXPECT_METRIC_EQ(1,
2740 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002741}
2742
2743TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2744 VideoSendStream::Config config(nullptr);
2745 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2746 statistics_proxy_.reset(new SendStatisticsProxy(
2747 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2748
2749 StreamDataCountersCallback* proxy =
2750 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2751 StreamDataCounters counters;
2752
2753 const int kMinRequiredPeriodSamples = 8;
2754 const int kPeriodIntervalMs = 2000;
2755 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2756 counters.transmitted.packets += 20;
2757 counters.transmitted.header_bytes += 500;
2758 counters.transmitted.payload_bytes += 2000;
2759 counters.fec = counters.retransmitted;
2760 // Advance one interval and update counters.
2761 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2762 proxy->DataCountersUpdated(counters, kFirstSsrc);
2763 }
2764
2765 // FEC not enabled.
2766 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002767 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002768}
2769
asapersson8d75ac72017-09-15 06:41:15 -07002770TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002771 const std::string kName = "encoderName";
2772 statistics_proxy_->OnEncoderImplementationChanged(kName);
2773 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002774}
2775
Sergey Silkinbb081a62018-09-04 18:34:22 +02002776TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2777 static const int kEncodedWidth = 123;
2778 static const int kEncodedHeight = 81;
2779 EncodedImage encoded_image;
2780 encoded_image._encodedWidth = kEncodedWidth;
2781 encoded_image._encodedHeight = kEncodedHeight;
2782 encoded_image.SetSpatialIndex(0);
2783
2784 CodecSpecificInfo codec_info;
2785 codec_info.codecType = kVideoCodecVP9;
2786
2787 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002788 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002789 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2790 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2791 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2792 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2793
2794 // Top layer updates resolution.
2795 encoded_image._encodedWidth = kEncodedWidth * 2;
2796 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002797 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002798 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2799 stats = statistics_proxy_->GetStats();
2800 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2801 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2802
2803 // Low layer of next frame doesn't update resolution.
2804 encoded_image._encodedWidth = kEncodedWidth;
2805 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002806 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002807 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2808 stats = statistics_proxy_->GetStats();
2809 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2810 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2811}
2812
asapersson8d75ac72017-09-15 06:41:15 -07002813class ForcedFallbackTest : public SendStatisticsProxyTest {
2814 public:
2815 explicit ForcedFallbackTest(const std::string& field_trials)
2816 : SendStatisticsProxyTest(field_trials) {
2817 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002818 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002819 encoded_image_._encodedWidth = kWidth;
2820 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002821 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002822 }
2823
2824 ~ForcedFallbackTest() override {}
2825
2826 protected:
2827 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002828 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2829
asapersson8d75ac72017-09-15 06:41:15 -07002830 // First frame is not updating stats, insert initial frame.
2831 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2832 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2833 }
2834 for (int i = 0; i < num_frames; ++i) {
2835 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2836 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2837 }
2838 // Add frame to include last time interval.
2839 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2840 }
2841
2842 EncodedImage encoded_image_;
2843 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002844 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002845 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2846 const int kFrameIntervalMs = 1000;
2847 const int kMinFrames = 20; // Min run time 20 sec.
2848};
2849
2850class ForcedFallbackDisabled : public ForcedFallbackTest {
2851 public:
2852 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002853 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2854 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002855};
2856
2857class ForcedFallbackEnabled : public ForcedFallbackTest {
2858 public:
2859 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002860 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2861 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002862};
2863
2864TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2865 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2866 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002867 EXPECT_METRIC_EQ(0,
2868 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2869 EXPECT_METRIC_EQ(
2870 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002871}
2872
2873TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2874 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002875 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002876 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002877 EXPECT_METRIC_EQ(1,
2878 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2879 EXPECT_METRIC_EQ(
2880 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2881 EXPECT_METRIC_EQ(
2882 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2883 EXPECT_METRIC_EQ(
2884 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002885}
2886
2887TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2888 codec_info_.codecType = kVideoCodecVP9;
2889 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2890 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002891 EXPECT_METRIC_EQ(0,
2892 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2893 EXPECT_METRIC_EQ(
2894 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002895}
2896
2897TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2898 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2899 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2900 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002901 EXPECT_METRIC_EQ(0,
2902 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2903 EXPECT_METRIC_EQ(
2904 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002905}
2906
2907TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002908 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002909 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2910 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002911 EXPECT_METRIC_EQ(0,
2912 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2913 EXPECT_METRIC_EQ(
2914 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002915}
2916
2917TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2918 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2919 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002920 EXPECT_METRIC_EQ(0,
2921 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2922 EXPECT_METRIC_EQ(
2923 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002924}
2925
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002926TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2927 InsertEncodedFrames(1, kFrameIntervalMs);
2928 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2929}
2930
2931TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2932 InsertEncodedFrames(1, kFrameIntervalMs);
2933 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2934}
2935
2936TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002937 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002938 InsertEncodedFrames(1, kFrameIntervalMs);
2939 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2940}
2941
2942TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2943 encoded_image_._encodedWidth = kWidth + 1;
2944 InsertEncodedFrames(1, kFrameIntervalMs);
2945 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2946}
2947
2948TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002949 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002950 InsertEncodedFrames(1, kFrameIntervalMs);
2951 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2952}
2953
2954TEST_F(ForcedFallbackDisabled,
2955 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2956 encoded_image_._encodedWidth = kWidth + 1;
2957 statistics_proxy_->OnMinPixelLimitReached();
2958 InsertEncodedFrames(1, kFrameIntervalMs);
2959 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2960}
2961
asapersson8d75ac72017-09-15 06:41:15 -07002962TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2963 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002964 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002965 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002966 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002967 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002968 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002969 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002970
2971 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002972 EXPECT_METRIC_EQ(1,
2973 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2974 EXPECT_METRIC_EQ(
2975 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2976 EXPECT_METRIC_EQ(
2977 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2978 EXPECT_METRIC_EQ(
2979 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002980}
2981
2982TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2983 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2984 const int kMaxFrameDiffMs = 2000;
2985
2986 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2987 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002988 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002989 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002990 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002991 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002992 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002993 InsertEncodedFrames(20, 1000);
2994 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2995 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002996 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002997 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002998 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002999 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02003000 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003001 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003002 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003003
3004 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003005 EXPECT_METRIC_EQ(1,
3006 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3007 EXPECT_METRIC_EQ(
3008 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3009 EXPECT_METRIC_EQ(
3010 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3011 EXPECT_METRIC_EQ(
3012 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07003013}
3014
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003015TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
3016 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003017 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003018 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3019
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003020 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003021 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003022 EXPECT_METRIC_EQ(0,
3023 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3024 EXPECT_METRIC_EQ(
3025 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003026}
3027
Åsa Persson45bbc8a2017-11-13 10:16:47 +01003028TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
3029 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02003030 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07003031 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3032
Åsa Perssonc3ed6302017-11-16 14:04:52 +01003033 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07003034 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01003035 EXPECT_METRIC_EQ(1,
3036 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3037 EXPECT_METRIC_EQ(
3038 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07003039}
3040
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00003041} // namespace webrtc