blob: aa133022a4b3e6540de85fa68934c5f38c6b72c0 [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
162 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700163 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
164 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
165 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000166 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
167 }
168 }
169
asapersson8d75ac72017-09-15 06:41:15 -0700170 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000171 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800172 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000174 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000175};
176
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200177TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
178 ReportBlockDataObserver* callback = statistics_proxy_.get();
179 for (uint32_t ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000180 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000181
182 // Add statistics with some arbitrary, but unique, numbers.
183 uint32_t offset = ssrc * sizeof(RtcpStatistics);
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200184 RTCPReportBlock report_block;
185 report_block.source_ssrc = ssrc;
186 report_block.packets_lost = offset;
187 report_block.extended_highest_sequence_number = offset + 1;
188 report_block.fraction_lost = offset + 2;
189 report_block.jitter = offset + 3;
190
191 ssrc_stats.rtcp_stats.packets_lost = report_block.packets_lost;
192 ssrc_stats.rtcp_stats.extended_highest_sequence_number =
193 report_block.extended_highest_sequence_number;
194 ssrc_stats.rtcp_stats.fraction_lost = report_block.fraction_lost;
195 ssrc_stats.rtcp_stats.jitter = report_block.jitter;
196 ReportBlockData data;
197 data.SetReportBlock(report_block, 0);
198
199 callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000200 }
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200201 for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000202 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000203
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000204 // Add statistics with some arbitrary, but unique, numbers.
205 uint32_t offset = ssrc * sizeof(RtcpStatistics);
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200206 RTCPReportBlock report_block;
207 report_block.source_ssrc = ssrc;
208 report_block.packets_lost = offset;
209 report_block.extended_highest_sequence_number = offset + 1;
210 report_block.fraction_lost = offset + 2;
211 report_block.jitter = offset + 3;
212
213 ssrc_stats.rtcp_stats.packets_lost = report_block.packets_lost;
214 ssrc_stats.rtcp_stats.extended_highest_sequence_number =
215 report_block.extended_highest_sequence_number;
216 ssrc_stats.rtcp_stats.fraction_lost = report_block.fraction_lost;
217 ssrc_stats.rtcp_stats.jitter = report_block.jitter;
218 ReportBlockData data;
219 data.SetReportBlock(report_block, 0);
220
221 callback->OnReportBlockDataUpdated(data);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000222 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000223 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000224 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000225}
226
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000227TEST_F(SendStatisticsProxyTest, Suspended) {
228 // Verify that the value is false by default.
229 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
230
231 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200232 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000233 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
234
235 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200236 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000237 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
238}
239
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000240TEST_F(SendStatisticsProxyTest, FrameCounts) {
241 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700242 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000243 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000244 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
245 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000246 FrameCounts frame_counts;
247 frame_counts.key_frames = offset;
248 frame_counts.delta_frames = offset + 1;
249 stats.frame_counts = frame_counts;
250 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000251 }
asapersson35151f32016-05-02 23:44:01 -0700252 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000253 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000254 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
255 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000256 FrameCounts frame_counts;
257 frame_counts.key_frames = offset;
258 frame_counts.delta_frames = offset + 1;
259 stats.frame_counts = frame_counts;
260 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000261 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000262
263 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000264 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000265}
266
267TEST_F(SendStatisticsProxyTest, DataCounters) {
268 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700269 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000270 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
271 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000272 size_t offset = ssrc * sizeof(StreamDataCounters);
273 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000274 counters.transmitted.payload_bytes = offset;
275 counters.transmitted.header_bytes = offset + 1;
276 counters.fec.packets = offset_uint32 + 2;
277 counters.transmitted.padding_bytes = offset + 3;
278 counters.retransmitted.packets = offset_uint32 + 4;
279 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000280 callback->DataCountersUpdated(counters, ssrc);
281 }
asapersson35151f32016-05-02 23:44:01 -0700282 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000283 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
284 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000285 size_t offset = ssrc * sizeof(StreamDataCounters);
286 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000287 counters.transmitted.payload_bytes = offset;
288 counters.transmitted.header_bytes = offset + 1;
289 counters.fec.packets = offset_uint32 + 2;
290 counters.transmitted.padding_bytes = offset + 3;
291 counters.retransmitted.packets = offset_uint32 + 4;
292 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000293 callback->DataCountersUpdated(counters, ssrc);
294 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000295
296 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000297 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000298}
299
300TEST_F(SendStatisticsProxyTest, Bitrate) {
301 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700302 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000303 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200304 uint32_t total = ssrc;
305 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000306 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700307 expected_.substreams[ssrc].total_bitrate_bps = total;
308 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000309 }
asapersson35151f32016-05-02 23:44:01 -0700310 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000311 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200312 uint32_t total = ssrc;
313 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000314 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700315 expected_.substreams[ssrc].total_bitrate_bps = total;
316 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000317 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000318
319 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000320 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000321}
322
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000323TEST_F(SendStatisticsProxyTest, SendSideDelay) {
324 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700325 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000326 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
327 // stream.
328 int avg_delay_ms = ssrc;
329 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200330 uint64_t total_packet_send_delay_ms = ssrc + 2;
331 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
332 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000333 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
334 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200335 expected_.substreams[ssrc].total_packet_send_delay_ms =
336 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000337 }
asapersson35151f32016-05-02 23:44:01 -0700338 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000339 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
340 // stream.
341 int avg_delay_ms = ssrc;
342 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200343 uint64_t total_packet_send_delay_ms = ssrc + 2;
344 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
345 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000346 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
347 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200348 expected_.substreams[ssrc].total_packet_send_delay_ms =
349 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000350 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000351 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000352 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000353}
354
Peter Boströme4499152016-02-05 11:13:28 +0100355TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800356 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200357 int encode_usage_percent = 80;
358 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
359 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800360
361 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
362 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200363 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800364}
365
Henrik Boström5684af52019-04-02 15:05:21 +0200366TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
367 const int kEncodeUsagePercent = 0; // Don't care for this test.
368 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
369 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
370 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
371 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
372 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
373}
374
sakal43536c32016-10-24 01:46:43 -0700375TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
376 EncodedImage encoded_image;
377 CodecSpecificInfo codec_info;
378 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
379 for (uint32_t i = 1; i <= 3; ++i) {
380 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
381 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
382 }
383}
384
sakal87da4042016-10-31 06:53:47 -0700385TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
386 EncodedImage encoded_image;
387 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200388 auto ssrc = config_.rtp.ssrcs[0];
389 EXPECT_EQ(absl::nullopt,
390 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700391 encoded_image.qp_ = 3;
392 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200393 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700394 encoded_image.qp_ = 127;
395 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200396 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700397}
398
399TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
400 EncodedImage encoded_image;
401 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200402 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700403 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200404 EXPECT_EQ(absl::nullopt,
405 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700406 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200407 EXPECT_EQ(absl::nullopt,
408 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700409}
410
Henrik Boström23aff9b2019-05-20 15:15:38 +0200411TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
412 const uint32_t kTargetBytesPerSecond = 100000;
413 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
414 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
415
416 EncodedImage encoded_image;
417 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
418 // On the first frame we don't know the frame rate yet, calculation yields
419 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
420 // increment by a full |kTargetBytesPerSecond|.
421 EXPECT_EQ(kTargetBytesPerSecond,
422 statistics_proxy_->GetStats().total_encoded_bytes_target);
423}
424
425TEST_F(SendStatisticsProxyTest,
426 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
427 const uint32_t kTargetBytesPerSecond = 100000;
428 const int kInterframeDelayMs = 100;
429
430 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
431 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
432 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
433 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
434 // this test can stop relying on rtc::ScopedFakeClock.
435 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100436 fake_global_clock.SetTime(
437 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200438
439 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
440 EncodedImage encoded_image;
441
442 // First frame
443 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
444 uint64_t first_total_encoded_bytes_target =
445 statistics_proxy_->GetStats().total_encoded_bytes_target;
446 // Second frame
447 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100448 fake_global_clock.SetTime(
449 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200450 encoded_image.SetTimestamp(encoded_image.Timestamp() +
451 90 * kInterframeDelayMs);
452 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
453
454 auto stats = statistics_proxy_->GetStats();
455 // By the time the second frame arrives, one frame has previously arrived
456 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
457 // the second frame's arrival should be 10 FPS.
458 uint64_t delta_encoded_bytes_target =
459 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
460 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
461}
462
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200463TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
464 const int kInterframeDelayMs = 100;
465 auto ssrc = config_.rtp.ssrcs[0];
466 rtc::ScopedFakeClock fake_global_clock;
467 fake_global_clock.SetTime(
468 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
469
470 EncodedImage encoded_image;
471
472 // First frame
473 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
474 // Second frame
475 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
476 fake_global_clock.SetTime(
477 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
478 encoded_image.SetTimestamp(encoded_image.Timestamp() +
479 90 * kInterframeDelayMs);
480 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
481
482 auto stats = statistics_proxy_->GetStats();
483 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
484}
485
asapersson09f05612017-05-15 23:40:18 -0700486TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200487 VideoAdaptationCounters cpu_counts;
488 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700489 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700490 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200491 cpu_counts.fps_adaptations = 1;
492 cpu_counts.resolution_adaptations = 0;
493 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200494 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
495 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700496 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700497 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200498 cpu_counts.fps_adaptations = 0;
499 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200500 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
501 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700502 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700503 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200504 cpu_counts.fps_adaptations = 1;
505 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
506 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200507 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
508 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700509 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700510 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200511 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
512 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200513 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
514 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700515 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
516 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
517}
518
519TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200520 VideoAdaptationCounters cpu_counts;
521 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700522 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
523 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200524 quality_counts.fps_adaptations = 1;
525 quality_counts.resolution_adaptations = 0;
526 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200527 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
528 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700529 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
530 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200531 quality_counts.fps_adaptations = 0;
532 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200533 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
534 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700535 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
536 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200537 quality_counts.fps_adaptations = 1;
538 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
539 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200540 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
541 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700542 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
543 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200544 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
545 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200546 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
547 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700548 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
549 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
550}
551
552TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200553 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
554 VideoAdaptationCounters cpu_counts;
555 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700556 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
557
Evan Shrubsoledff79252020-04-16 11:34:32 +0200558 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200559 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
560 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700561 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700562 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
563 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
564
Evan Shrubsoledff79252020-04-16 11:34:32 +0200565 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200566 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
567 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700568 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
569 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700570 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700571 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700572}
573
asapersson09f05612017-05-15 23:40:18 -0700574TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200575 VideoAdaptationCounters cpu_counts;
576 VideoAdaptationCounters quality_counts;
577 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700578 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
579
Evan Shrubsoledff79252020-04-16 11:34:32 +0200580 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200581 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
582 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700583 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
584 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700585 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
586
Evan Shrubsoledff79252020-04-16 11:34:32 +0200587 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200588 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
589 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700590 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700591 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700592 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
593 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700594}
595
Evan Shrubsoledff79252020-04-16 11:34:32 +0200596TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
597 VideoAdaptationCounters cpu_counts;
598 VideoAdaptationCounters quality_counts;
599 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
600 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
601 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
602
603 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200604 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
605 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200606 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200607 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
608 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200609 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200610 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
611 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200612 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200613 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
614 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200615 // We have 1 fps and resolution reduction for both cpu and quality
616 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
617 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
618 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
619 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
620 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
621 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
622
623 // Disable quality scaling. Expect quality scaling not limited.
624 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
625 kScalingDisabled);
626 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
627 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
628 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
629 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
630 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
631 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
632
633 // Disable framerate scaling.
634 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
635 kFramerateScalingDisabled);
636 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
637 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
638 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
639 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
640 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
641 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
642
643 // Disable resolution scaling.
644 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
645 kResolutionScalingDisabled);
646 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
647 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
648 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
649 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
650 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
651 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
652
653 // Enable all
654 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
655 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
656 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
657 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
658 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
659 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
660 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
661}
662
asapersson09f05612017-05-15 23:40:18 -0700663TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700664 // First RTP packet sent.
665 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700666 // Min runtime has passed.
667 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
668 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100669 EXPECT_METRIC_EQ(
670 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
671 EXPECT_METRIC_EQ(
672 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700673}
674
675TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700676 // First RTP packet sent.
677 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700678 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200679 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700680 // Min runtime has not passed.
681 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
682 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100683 EXPECT_METRIC_EQ(
684 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
685 EXPECT_METRIC_EQ(
686 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700687}
688
asapersson09f05612017-05-15 23:40:18 -0700689TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700690 // First RTP packet sent.
691 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700692 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200693 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700694 // Min runtime has passed.
695 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
696 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100697 EXPECT_METRIC_EQ(
698 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
699 EXPECT_METRIC_EQ(
700 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
701 EXPECT_METRIC_EQ(
702 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
703 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700704 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
705}
706
707TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700708 // First RTP packet sent.
709 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700710 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200711 VideoAdaptationCounters cpu_counts;
712 VideoAdaptationCounters quality_counts;
713 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700714 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200715 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
716 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700717 fake_clock_.AdvanceTimeMilliseconds(10000);
718 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100719 EXPECT_METRIC_EQ(
720 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
721 EXPECT_METRIC_EQ(
722 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700723}
724
Åsa Persson875841d2018-01-08 08:49:53 +0100725TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
726 // First RTP packet sent.
727 UpdateDataCounters(kFirstSsrc);
728 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200729 VideoAdaptationCounters cpu_counts;
730 VideoAdaptationCounters quality_counts;
731 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100732 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200733 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
734 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100735 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
736 fake_clock_.AdvanceTimeMilliseconds(10000);
737 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100738 EXPECT_METRIC_EQ(
739 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
740 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100741 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
742}
743
744TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
745 // First RTP packet sent.
746 UpdateDataCounters(kFirstSsrc);
747 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200748 VideoAdaptationCounters cpu_counts;
749 VideoAdaptationCounters quality_counts;
750 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100751 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200752 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200753 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
754 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100755 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200756 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200757 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
758 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100759 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200760 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200761 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
762 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100763 fake_clock_.AdvanceTimeMilliseconds(10000);
764 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100765 EXPECT_METRIC_EQ(
766 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
767 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100768 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
769}
770
771TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
772 // First RTP packet sent.
773 UpdateDataCounters(kFirstSsrc);
774 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200775 VideoAdaptationCounters cpu_counts;
776 VideoAdaptationCounters quality_counts;
777 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100778 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200779 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
780 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100781 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
782 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
783 fake_clock_.AdvanceTimeMilliseconds(10000);
784 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100785 EXPECT_METRIC_EQ(
786 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
787 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100788 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
789}
790
791TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
792 // First RTP packet sent.
793 UpdateDataCounters(kFirstSsrc);
794 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200795 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
796 VideoAdaptationCounters cpu_counts;
797 VideoAdaptationCounters quality_counts;
798 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100799 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200800 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200801 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
802 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100803 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200804 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200805 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
806 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100807 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200808 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200809 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
810 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200811 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200812 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
813 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200814 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200815 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
816 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200817 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200818 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
819 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200820 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200821 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
822 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200823 quality_counts.resolution_adaptations = 0;
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
827 fake_clock_.AdvanceTimeMilliseconds(10000);
828 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100829 EXPECT_METRIC_EQ(
830 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
831 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100832 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
833}
834
asapersson6eca98b2017-04-04 23:40:50 -0700835TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700836 // First RTP packet sent.
837 UpdateDataCounters(kFirstSsrc);
838
asapersson09f05612017-05-15 23:40:18 -0700839 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200840 VideoAdaptationCounters cpu_counts;
841 VideoAdaptationCounters quality_counts;
842 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
843 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700844 fake_clock_.AdvanceTimeMilliseconds(10000);
845
asapersson09f05612017-05-15 23:40:18 -0700846 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700847 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200848 quality_counts.fps_adaptations = 0;
849 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
850 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700851 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200852 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
853 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700854 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200855 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
856 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700857 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200858 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
859 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700860
asapersson09f05612017-05-15 23:40:18 -0700861 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200862 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
863 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700864 fake_clock_.AdvanceTimeMilliseconds(30000);
865
asapersson09f05612017-05-15 23:40:18 -0700866 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700867 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200868 quality_counts.resolution_adaptations = 0;
869 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
870 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200871 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
872 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700873 fake_clock_.AdvanceTimeMilliseconds(10000);
874
asapersson09f05612017-05-15 23:40:18 -0700875 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200876 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
877 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700878 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200879 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
880 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700881 fake_clock_.AdvanceTimeMilliseconds(20000);
882
asapersson0944a802017-04-07 00:57:58 -0700883 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700884 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100885 EXPECT_METRIC_EQ(
886 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
887 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700888 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
889}
890
asapersson0944a802017-04-07 00:57:58 -0700891TEST_F(SendStatisticsProxyTest,
892 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
893 // First RTP packet sent.
894 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700895
asapersson0944a802017-04-07 00:57:58 -0700896 // Suspend and resume video.
897 statistics_proxy_->OnSuspendChange(true);
898 fake_clock_.AdvanceTimeMilliseconds(5000);
899 statistics_proxy_->OnSuspendChange(false);
900
901 // Min runtime has passed but scaling not enabled.
902 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
903 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100904 EXPECT_METRIC_EQ(
905 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
906 EXPECT_METRIC_EQ(
907 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700908}
909
910TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
911 // First RTP packet sent.
912 UpdateDataCounters(kFirstSsrc);
913
asapersson09f05612017-05-15 23:40:18 -0700914 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200915 VideoAdaptationCounters cpu_counts;
916 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700917 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200918 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700919 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200920 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
921 cpu_counts, quality_counts);
922 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
923 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700924
925 // Suspend and resume video.
926 statistics_proxy_->OnSuspendChange(true);
927 fake_clock_.AdvanceTimeMilliseconds(30000);
928 statistics_proxy_->OnSuspendChange(false);
929
930 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200931 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
932 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700933 fake_clock_.AdvanceTimeMilliseconds(10000);
934
935 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
936 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100937 EXPECT_METRIC_EQ(
938 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
939 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700940 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
941}
942
943TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
944 // First RTP packet sent.
945 UpdateDataCounters(kFirstSsrc);
946
947 // Video not suspended.
948 statistics_proxy_->OnSuspendChange(false);
949 fake_clock_.AdvanceTimeMilliseconds(30000);
950
asapersson09f05612017-05-15 23:40:18 -0700951 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200952 VideoAdaptationCounters cpu_counts;
953 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700954 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200955 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700956 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200957 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
958 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700959
960 // Video not suspended, stats time already started.
961 statistics_proxy_->OnSuspendChange(false);
962 fake_clock_.AdvanceTimeMilliseconds(10000);
963
asapersson09f05612017-05-15 23:40:18 -0700964 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200965 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
966 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -0700967 fake_clock_.AdvanceTimeMilliseconds(30000);
968
969 // Suspend and resume video, stats time not started when scaling not enabled.
970 statistics_proxy_->OnSuspendChange(true);
971 fake_clock_.AdvanceTimeMilliseconds(30000);
972 statistics_proxy_->OnSuspendChange(false);
973 fake_clock_.AdvanceTimeMilliseconds(30000);
974
asapersson09f05612017-05-15 23:40:18 -0700975 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700976 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200977 cpu_counts.fps_adaptations = 0;
978 cpu_counts.resolution_adaptations = 0;
979 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700980 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200981 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
982 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700983
984 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
985 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100986 EXPECT_METRIC_EQ(
987 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
988 EXPECT_METRIC_EQ(
989 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700990}
991
992TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
993 // First RTP packet sent.
994 UpdateDataCounters(kFirstSsrc);
995
996 // Video suspended.
997 statistics_proxy_->OnSuspendChange(true);
998
asapersson09f05612017-05-15 23:40:18 -0700999 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001000 VideoAdaptationCounters cpu_counts;
1001 VideoAdaptationCounters quality_counts;
1002 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -07001003 fake_clock_.AdvanceTimeMilliseconds(10000);
1004
1005 // Resume video, stats time started.
1006 // Adapt changes: 1, elapsed time: 10 sec.
1007 statistics_proxy_->OnSuspendChange(false);
1008 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001009 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1010 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001011
1012 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1013 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001014 EXPECT_METRIC_EQ(
1015 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1016 EXPECT_METRIC_EQ(
1017 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001018}
1019
1020TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001021 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001022 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001023 VideoAdaptationCounters cpu_counts;
1024 VideoAdaptationCounters quality_counts;
1025 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001026 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001027 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001028
asapersson0944a802017-04-07 00:57:58 -07001029 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001030 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001031 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1032 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001033 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001034
asapersson0944a802017-04-07 00:57:58 -07001035 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001036 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001037 EXPECT_METRIC_EQ(
1038 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1039 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001040 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1041}
1042
1043TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001044 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001045 VideoAdaptationCounters cpu_counts;
1046 VideoAdaptationCounters quality_counts;
1047 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001048 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001049 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1050 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001051
1052 // Send first packet, scaling disabled.
1053 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001054 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001055 fake_clock_.AdvanceTimeMilliseconds(60000);
1056
asapersson09f05612017-05-15 23:40:18 -07001057 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001058 cpu_counts.resolution_adaptations = 0;
1059 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1060 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001061 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001062 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001063
asapersson0944a802017-04-07 00:57:58 -07001064 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001065 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001066 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1067 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001068
asapersson0944a802017-04-07 00:57:58 -07001069 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001070 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001071 EXPECT_METRIC_EQ(
1072 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1073 EXPECT_METRIC_EQ(
1074 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001075}
1076
1077TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001078 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001079 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001080 VideoAdaptationCounters cpu_counts;
1081 VideoAdaptationCounters quality_counts;
1082 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1083 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001084
asapersson0944a802017-04-07 00:57:58 -07001085 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001086 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1087 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001088 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001089 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1090 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001091 fake_clock_.AdvanceTimeMilliseconds(9000);
1092
1093 // Switch content type, real-time stats should be updated.
1094 VideoEncoderConfig config;
1095 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001096 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001097 EXPECT_METRIC_EQ(
1098 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1099 EXPECT_METRIC_EQ(
1100 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1101 EXPECT_METRIC_EQ(
1102 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001103
asapersson0944a802017-04-07 00:57:58 -07001104 // First RTP packet sent, scaling enabled.
1105 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001106 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1107 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001108
asapersson0944a802017-04-07 00:57:58 -07001109 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001110 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1111 cpu_counts, quality_counts);
1112 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1113 cpu_counts, quality_counts);
1114 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1115 cpu_counts, quality_counts);
1116 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1117 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001118 fake_clock_.AdvanceTimeMilliseconds(120000);
1119
1120 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001121 EXPECT_METRIC_EQ(1,
1122 metrics::NumSamples(
1123 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1124 EXPECT_METRIC_EQ(
1125 1, metrics::NumEvents(
1126 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1127 EXPECT_METRIC_EQ(
1128 0, metrics::NumSamples(
1129 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001130}
1131
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001132TEST_F(SendStatisticsProxyTest,
1133 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001134 VideoAdaptationCounters cpu_counts;
1135 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001136
Evan Shrubsoledff79252020-04-16 11:34:32 +02001137 cpu_counts.resolution_adaptations = 1;
1138 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001139 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1140 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001141
1142 EXPECT_EQ(QualityLimitationReason::kCpu,
1143 statistics_proxy_->GetStats().quality_limitation_reason);
1144}
1145
1146TEST_F(SendStatisticsProxyTest,
1147 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001148 VideoAdaptationCounters cpu_counts;
1149 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001150
Evan Shrubsoledff79252020-04-16 11:34:32 +02001151 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001152
Evan Shrubsoledff79252020-04-16 11:34:32 +02001153 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001154 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1155 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001156
1157 EXPECT_EQ(QualityLimitationReason::kCpu,
1158 statistics_proxy_->GetStats().quality_limitation_reason);
1159}
1160
1161TEST_F(SendStatisticsProxyTest,
1162 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001163 VideoAdaptationCounters cpu_counts;
1164 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001165
Evan Shrubsoledff79252020-04-16 11:34:32 +02001166 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001167
Evan Shrubsoledff79252020-04-16 11:34:32 +02001168 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001169 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1170 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001171
1172 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1173 statistics_proxy_->GetStats().quality_limitation_reason);
1174}
1175
1176TEST_F(SendStatisticsProxyTest,
1177 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001178 VideoAdaptationCounters cpu_counts;
1179 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001180
Evan Shrubsoledff79252020-04-16 11:34:32 +02001181 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001182
Evan Shrubsoledff79252020-04-16 11:34:32 +02001183 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001184 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1185 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001186
1187 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1188 statistics_proxy_->GetStats().quality_limitation_reason);
1189}
1190
1191TEST_F(SendStatisticsProxyTest,
1192 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
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.resolution_adaptations = 1;
1197 quality_counts.resolution_adaptations = 1;
1198 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001199
1200 // Even if the last adaptation reason is kCpu, if the counters indicate being
1201 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001202 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1203 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001204
1205 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1206 statistics_proxy_->GetStats().quality_limitation_reason);
1207}
1208
1209TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001210 VideoAdaptationCounters cpu_counts;
1211 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001212
1213 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1214 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001215 cpu_counts.resolution_adaptations = 1;
1216 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001217 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1218 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001219 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001220 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001221 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1222 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001223
1224 EXPECT_EQ(QualityLimitationReason::kNone,
1225 statistics_proxy_->GetStats().quality_limitation_reason);
1226}
1227
1228TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001229 VideoAdaptationCounters cpu_counts;
1230 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001231
Evan Shrubsoledff79252020-04-16 11:34:32 +02001232 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001233 // Not limited for 3000 ms
1234 fake_clock_.AdvanceTimeMilliseconds(3000);
1235 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001236 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001237 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1238 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001239 fake_clock_.AdvanceTimeMilliseconds(2000);
1240 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001241 cpu_counts.resolution_adaptations = 0;
1242 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001243 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1244 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001245 fake_clock_.AdvanceTimeMilliseconds(1000);
1246 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001247 cpu_counts.resolution_adaptations = 1;
1248 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001249 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1250 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001251 fake_clock_.AdvanceTimeMilliseconds(2000);
1252
1253 auto quality_limitation_durations_ms =
1254 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1255
1256 EXPECT_EQ(3000,
1257 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1258 EXPECT_EQ(4000,
1259 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1260 EXPECT_EQ(
1261 1000,
1262 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1263 EXPECT_EQ(0,
1264 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1265}
1266
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001267TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1268 EXPECT_EQ(
1269 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1270}
1271
1272TEST_F(SendStatisticsProxyTest,
1273 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1274 VideoCodec codec;
1275 VideoBitrateAllocation allocation;
1276 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1277 EXPECT_EQ(
1278 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1279}
1280
1281TEST_F(SendStatisticsProxyTest,
1282 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1283 VideoCodec codec;
1284 codec.simulcastStream[0].active = true;
1285 codec.simulcastStream[1].active = true;
1286 codec.simulcastStream[2].active = true;
1287 VideoBitrateAllocation allocation;
1288 allocation.SetBitrate(0, 0, 100);
1289 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1290 EXPECT_EQ(
1291 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1292}
1293
1294TEST_F(SendStatisticsProxyTest,
1295 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1296 VideoCodec codec;
1297 codec.simulcastStream[0].active = true;
1298 codec.simulcastStream[1].active = true;
1299 codec.simulcastStream[2].active = true;
1300 VideoBitrateAllocation allocation;
1301 allocation.SetBitrate(0, 0, 100);
1302 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1303 allocation.SetBitrate(1, 0, 100);
1304 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1305 EXPECT_EQ(
1306 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1307}
1308
1309TEST_F(SendStatisticsProxyTest,
1310 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1311 VideoCodec codec;
1312 codec.simulcastStream[0].active = true;
1313 VideoBitrateAllocation allocation;
1314 allocation.SetBitrate(0, 0, 100);
1315 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1316 // Layer 0 got more bandwidth, but still only one layer on
1317 allocation.SetBitrate(0, 0, 200);
1318 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1319 EXPECT_EQ(
1320 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1321}
1322
1323TEST_F(SendStatisticsProxyTest,
1324 QualityLimitationResolutionChangesWithTogglingLayers) {
1325 VideoCodec codec;
1326 codec.simulcastStream[0].active = true;
1327 codec.simulcastStream[1].active = true;
1328 codec.simulcastStream[2].active = true;
1329 VideoBitrateAllocation allocation;
1330 allocation.SetBitrate(0, 0, 100);
1331 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1332 EXPECT_EQ(
1333 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1334 allocation.SetBitrate(1, 0, 300);
1335 allocation.SetBitrate(2, 0, 500);
1336 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1337 EXPECT_EQ(
1338 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1339 // Layer 2 off
1340 allocation.SetBitrate(2, 0, 0);
1341 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1342 EXPECT_EQ(
1343 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1344 // Layer 2 back on
1345 allocation.SetBitrate(2, 0, 500);
1346 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1347 EXPECT_EQ(
1348 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1349 allocation.SetBitrate(0, 0, 0);
1350 allocation.SetBitrate(1, 0, 0);
1351 allocation.SetBitrate(2, 0, 0);
1352 // All layers off
1353 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1354 EXPECT_EQ(
1355 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1356}
1357
1358TEST_F(SendStatisticsProxyTest,
1359 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1360 VideoCodec codec;
1361 // 3 layers
1362 codec.simulcastStream[0].active = true;
1363 codec.simulcastStream[1].active = true;
1364 codec.simulcastStream[2].active = true;
1365 VideoBitrateAllocation allocation;
1366 allocation.SetBitrate(0, 0, 500);
1367 allocation.SetBitrate(1, 0, 500);
1368 allocation.SetBitrate(2, 0, 500);
1369 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1370 EXPECT_EQ(
1371 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1372
1373 // Down to one layer now, triggered by a config change
1374 codec.numberOfSimulcastStreams = 1;
1375 codec.simulcastStream[1].active = false;
1376 codec.simulcastStream[2].active = false;
1377 allocation.SetBitrate(0, 0, 100);
1378 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1379 EXPECT_EQ(
1380 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1381
1382 // Up to 3 layers again.
1383 codec.numberOfSimulcastStreams = 3;
1384 codec.simulcastStream[1].active = true;
1385 codec.simulcastStream[2].active = true;
1386 allocation.SetBitrate(0, 0, 500);
1387 allocation.SetBitrate(1, 0, 500);
1388 allocation.SetBitrate(2, 0, 500);
1389 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1390 EXPECT_EQ(
1391 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1392}
1393
1394TEST_F(SendStatisticsProxyTest,
1395 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1396 VideoCodec codec;
1397 codec.simulcastStream[0].active = true;
1398 codec.spatialLayers[0].active = true;
1399 codec.spatialLayers[1].active = true;
1400 codec.spatialLayers[2].active = true;
1401 VideoBitrateAllocation allocation;
1402 allocation.SetBitrate(0, 0, 500);
1403 allocation.SetBitrate(1, 0, 500);
1404 allocation.SetBitrate(2, 0, 500);
1405 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1406 EXPECT_EQ(
1407 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1408
1409 // Down to one layer now, triggered by a config change
1410 codec.spatialLayers[1].active = false;
1411 codec.spatialLayers[2].active = false;
1412 allocation.SetBitrate(0, 0, 100);
1413 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1414 EXPECT_EQ(
1415 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1416
1417 // Up to 3 layers again.
1418 codec.spatialLayers[1].active = true;
1419 codec.spatialLayers[2].active = true;
1420 allocation.SetBitrate(0, 0, 500);
1421 allocation.SetBitrate(1, 0, 500);
1422 allocation.SetBitrate(2, 0, 500);
1423 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1424 EXPECT_EQ(
1425 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1426}
1427
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001428TEST_F(SendStatisticsProxyTest,
1429 QualityLimitationReasonsAreCorrectForContentType) {
1430 // Realtime case.
1431 // Configure two streams.
1432 VideoEncoderConfig config;
1433 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1434 config.number_of_streams = 2;
1435 VideoStream stream1;
1436 stream1.width = kWidth / 2;
1437 stream1.height = kHeight / 2;
1438 VideoStream stream2;
1439 stream2.width = kWidth;
1440 stream2.height = kHeight;
1441 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1442 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1443 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1444 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1445 QualityLimitationReason::kNone);
1446 // Bw disabled one layer.
1447 VideoCodec codec;
1448 codec.numberOfSimulcastStreams = 2;
1449 codec.simulcastStream[0].active = true;
1450 codec.simulcastStream[1].active = true;
1451 VideoBitrateAllocation allocation;
1452 // Some positive bitrate only on the first stream.
1453 allocation.SetBitrate(0, 0, 10000);
1454 allocation.SetBitrate(1, 0, 0);
1455 allocation.set_bw_limited(true);
1456 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1457 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1458 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1459 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1460 QualityLimitationReason::kBandwidth);
1461 // Bw enabled all layers.
1462 allocation.SetBitrate(1, 0, 10000);
1463 allocation.set_bw_limited(false);
1464 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1465 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1466 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1467 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1468 QualityLimitationReason::kNone);
1469
1470 // Screencast case
1471 // Configure two streams.
1472 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1473 config.number_of_streams = 2;
1474 stream1.width = kWidth;
1475 stream1.height = kHeight;
1476 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1477 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1478 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1479 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1480 QualityLimitationReason::kNone);
1481 // Bw disabled one layer.
1482 // Some positive bitrate only on the second stream.
1483 allocation.SetBitrate(0, 0, 10000);
1484 allocation.SetBitrate(1, 0, 0);
1485 allocation.set_bw_limited(true);
1486 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1487 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1488 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1489 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1490 QualityLimitationReason::kBandwidth);
1491 // Bw enabled all layers.
1492 allocation.SetBitrate(1, 0, 10000);
1493 allocation.set_bw_limited(false);
1494 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1495 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1496 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1497 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1498 QualityLimitationReason::kNone);
1499}
1500
asapersson59bac1a2016-01-07 23:36:00 -08001501TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001502 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001503 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1504
Pera48ddb72016-09-29 11:48:50 +02001505 // No switch, stats should not be updated.
1506 VideoEncoderConfig config;
1507 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001508 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001509 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001510
1511 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001512 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001513 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001514 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001515}
1516
asapersson320e45a2016-11-29 01:40:35 -08001517TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1518 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1519 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001520
asapersson320e45a2016-11-29 01:40:35 -08001521 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001522 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1523 EXPECT_METRIC_EQ(
1524 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1525 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1526 EXPECT_METRIC_EQ(
1527 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001528}
1529
1530TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001531 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001532 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001533 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1534 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1535 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001536 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001537
1538 // Not enough samples, stats should not be updated.
1539 for (int i = 0; i < kMinSamples - 1; ++i) {
1540 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001541 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001542 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1543 }
Åsa Persson0122e842017-10-16 12:19:23 +02001544 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001545 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1546 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001547
1548 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001549 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001550 for (int i = 0; i < kMinSamples; ++i) {
1551 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001552 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001553 encoded_image._encodedWidth = kWidth;
1554 encoded_image._encodedHeight = kHeight;
1555 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1556 encoded_image._encodedWidth = kWidth / 2;
1557 encoded_image._encodedHeight = kHeight / 2;
1558 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1559 }
1560
asapersson320e45a2016-11-29 01:40:35 -08001561 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001562 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1563 EXPECT_METRIC_EQ(
1564 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1565 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1566 EXPECT_METRIC_EQ(
1567 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001568}
1569
1570TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1571 const int kFps = 20;
1572 const int kMinPeriodicSamples = 6;
1573 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1574 for (int i = 0; i <= frames; ++i) {
1575 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1576 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1577 }
1578 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001579 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1580 EXPECT_METRIC_EQ(
1581 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001582}
1583
1584TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1585 EncodedImage encoded_image;
1586 const int kFps = 20;
1587 const int kMinPeriodicSamples = 6;
1588 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001589 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001590 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001591 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001592 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1593 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001594 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1595 }
1596 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001597 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1598 EXPECT_METRIC_EQ(
1599 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001600}
1601
1602TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1603 const int kFps = 20;
1604 const int kSuspendTimeMs = 10000;
1605 const int kMinPeriodicSamples = 6;
1606 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1607 for (int i = 0; i < frames; ++i) {
1608 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1609 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1610 }
1611 // Suspend.
1612 statistics_proxy_->OnSuspendChange(true);
1613 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1614
1615 for (int i = 0; i < frames; ++i) {
1616 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1617 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1618 }
1619 // Suspended time interval should not affect the framerate.
1620 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001621 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1622 EXPECT_METRIC_EQ(
1623 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001624}
1625
1626TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1627 EncodedImage encoded_image;
1628 const int kFps = 20;
1629 const int kSuspendTimeMs = 10000;
1630 const int kMinPeriodicSamples = 6;
1631 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001632 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001633 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001634 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001635 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1636 }
1637 // Suspend.
1638 statistics_proxy_->OnSuspendChange(true);
1639 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1640
Åsa Persson0122e842017-10-16 12:19:23 +02001641 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001642 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001643 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001644 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1645 }
1646 // Suspended time interval should not affect the framerate.
1647 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001648 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1649 EXPECT_METRIC_EQ(
1650 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001651}
1652
asaperssonf4e44af2017-04-19 02:01:06 -07001653TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001654 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1655 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001656
1657 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1658 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1659
1660 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001661 EXPECT_METRIC_EQ(
1662 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001663}
1664
1665TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001666 VideoAdaptationCounters cpu_counts;
1667 VideoAdaptationCounters quality_counts;
1668 cpu_counts.resolution_adaptations = 0;
1669 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001670
perkj803d97f2016-11-01 11:45:46 -07001671 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1672 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1673
Evan Shrubsoledff79252020-04-16 11:34:32 +02001674 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001675 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1676 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001677
1678 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1679 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1680
1681 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001682 EXPECT_METRIC_EQ(
1683 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1684 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001685 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1686}
1687
asapersson4374a092016-07-27 00:39:09 -07001688TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1689 const int64_t kTimeSec = 3;
1690 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1691 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001692 EXPECT_METRIC_EQ(
1693 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1694 EXPECT_METRIC_EQ(
1695 1,
1696 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001697}
1698
1699TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1700 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1701 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001702 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001703}
1704
asapersson66d4b372016-12-19 06:50:53 -08001705TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1706 // First RTP packet sent.
1707 UpdateDataCounters(kFirstSsrc);
1708
1709 // Min runtime has passed.
1710 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1711 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001712 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1713 EXPECT_METRIC_EQ(1,
1714 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001715}
1716
1717TEST_F(SendStatisticsProxyTest,
1718 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1719 // First RTP packet sent.
1720 UpdateDataCounters(kFirstSsrc);
1721
1722 // Min runtime has not passed.
1723 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1724 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001725 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1726 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001727}
1728
1729TEST_F(SendStatisticsProxyTest,
1730 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1731 // First RTP packet not sent.
1732 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1733 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001734 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001735}
1736
1737TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1738 // First RTP packet sent and min runtime passed.
1739 UpdateDataCounters(kFirstSsrc);
1740
1741 // No change. Video: 10000 ms, paused: 0 ms (0%).
1742 statistics_proxy_->OnSetEncoderTargetRate(50000);
1743 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1744 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1745
1746 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001747 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1748 EXPECT_METRIC_EQ(1,
1749 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1750 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1751 EXPECT_METRIC_EQ(1,
1752 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001753}
1754
1755TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1756 // First RTP packet sent and min runtime passed.
1757 UpdateDataCounters(kFirstSsrc);
1758
1759 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1760 statistics_proxy_->OnSetEncoderTargetRate(50000);
1761 fake_clock_.AdvanceTimeMilliseconds(7000);
1762 statistics_proxy_->OnSetEncoderTargetRate(0);
1763 fake_clock_.AdvanceTimeMilliseconds(3000);
1764 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1765
1766 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001767 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1768 EXPECT_METRIC_EQ(1,
1769 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1770 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1771 EXPECT_METRIC_EQ(1,
1772 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001773}
1774
1775TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1776 // First RTP packet sent.
1777 UpdateDataCounters(kFirstSsrc);
1778
1779 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1780 statistics_proxy_->OnSetEncoderTargetRate(0);
1781 fake_clock_.AdvanceTimeMilliseconds(1000);
1782 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1783 fake_clock_.AdvanceTimeMilliseconds(7000);
1784 statistics_proxy_->OnSetEncoderTargetRate(60000);
1785 fake_clock_.AdvanceTimeMilliseconds(3000);
1786 statistics_proxy_->OnSetEncoderTargetRate(0);
1787 fake_clock_.AdvanceTimeMilliseconds(250);
1788 statistics_proxy_->OnSetEncoderTargetRate(0);
1789 fake_clock_.AdvanceTimeMilliseconds(750);
1790 statistics_proxy_->OnSetEncoderTargetRate(60000);
1791 fake_clock_.AdvanceTimeMilliseconds(5000);
1792 statistics_proxy_->OnSetEncoderTargetRate(50000);
1793 fake_clock_.AdvanceTimeMilliseconds(4000);
1794 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1795
1796 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001797 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1798 EXPECT_METRIC_EQ(1,
1799 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1800 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1801 EXPECT_METRIC_EQ(1,
1802 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001803}
1804
1805TEST_F(SendStatisticsProxyTest,
1806 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1807 // First RTP packet sent.
1808 UpdateDataCounters(kFirstSsrc);
1809 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1810
1811 // Min runtime has not passed.
1812 statistics_proxy_->OnSetEncoderTargetRate(50000);
1813 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1814 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1815
1816 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001817 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001818}
1819
asapersson118ef002016-03-31 00:00:19 -07001820TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001821 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001822 CodecSpecificInfo codec_info;
1823 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001824
perkj803d97f2016-11-01 11:45:46 -07001825 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001826 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001827 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001828 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001829 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001830 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001831 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001832 }
1833 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001834 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1835 EXPECT_METRIC_EQ(
1836 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1837 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1838 EXPECT_METRIC_EQ(
1839 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001840}
1841
1842TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1843 VideoSendStream::Config config(nullptr);
1844 config.rtp.ssrcs.push_back(kFirstSsrc);
1845 statistics_proxy_.reset(new SendStatisticsProxy(
1846 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1847
asapersson118ef002016-03-31 00:00:19 -07001848 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001849 CodecSpecificInfo codec_info;
1850 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001851
perkj803d97f2016-11-01 11:45:46 -07001852 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001853 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001854 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001855 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001856 }
1857 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001858 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1859 EXPECT_METRIC_EQ(1,
1860 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001861}
1862
asapersson5265fed2016-04-18 02:58:47 -07001863TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001864 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001865 CodecSpecificInfo codec_info;
1866 codec_info.codecType = kVideoCodecVP9;
1867 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001868
perkj803d97f2016-11-01 11:45:46 -07001869 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001870 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001871 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001872 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001873 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001874 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001875 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001876 }
1877 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001878 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1879 EXPECT_METRIC_EQ(
1880 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1881 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1882 EXPECT_METRIC_EQ(
1883 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001884}
1885
1886TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1887 VideoSendStream::Config config(nullptr);
1888 config.rtp.ssrcs.push_back(kFirstSsrc);
1889 statistics_proxy_.reset(new SendStatisticsProxy(
1890 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1891
asapersson5265fed2016-04-18 02:58:47 -07001892 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001893 CodecSpecificInfo codec_info;
1894 codec_info.codecType = kVideoCodecVP9;
1895 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001896
perkj803d97f2016-11-01 11:45:46 -07001897 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001898 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001899 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001900 }
1901 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001902 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1903 EXPECT_METRIC_EQ(1,
1904 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001905}
1906
asapersson827cab32016-11-02 09:08:47 -07001907TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1908 EncodedImage encoded_image;
1909 CodecSpecificInfo codec_info;
1910 codec_info.codecType = kVideoCodecH264;
1911
1912 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001913 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001914 encoded_image.qp_ = kQpIdx0;
1915 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001916 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001917 encoded_image.qp_ = kQpIdx1;
1918 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001919 }
1920 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001921 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1922 EXPECT_METRIC_EQ(
1923 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1924 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1925 EXPECT_METRIC_EQ(
1926 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001927}
1928
asapersson4ee70462016-10-31 04:05:12 -07001929TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001930 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1931 // Configure one stream.
1932 VideoEncoderConfig config;
1933 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1934 VideoStream stream1;
1935 stream1.width = kWidth;
1936 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001937 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001938
1939 const int64_t kMaxEncodedFrameWindowMs = 800;
1940 const int kFps = 20;
1941 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1942 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1943 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1944
1945 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001946 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001947 encoded_image._encodedWidth = kWidth;
1948 encoded_image._encodedHeight = kHeight;
1949 for (int i = 0; i < kMinSamples; ++i) {
1950 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001951 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1952 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001953 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001954 }
asapersson4ee70462016-10-31 04:05:12 -07001955
1956 // Histograms are updated when the statistics_proxy_ is deleted.
1957 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001958 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1959 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1960 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1961 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001962}
1963
1964TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001965 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1966 // Configure two streams.
1967 VideoEncoderConfig config;
1968 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1969 VideoStream stream1;
1970 stream1.width = kWidth / 2;
1971 stream1.height = kHeight / 2;
1972 VideoStream stream2;
1973 stream2.width = kWidth;
1974 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001975 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001976
1977 const int64_t kMaxEncodedFrameWindowMs = 800;
1978 const int kFps = 20;
1979 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1980 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1981 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1982
1983 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001984 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001985 for (int i = 0; i < kMinSamples; ++i) {
1986 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001987 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1988 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001989 encoded_image._encodedWidth = kWidth;
1990 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001991 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001992 encoded_image._encodedWidth = kWidth / 2;
1993 encoded_image._encodedHeight = kHeight / 2;
1994 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1995 }
asapersson4ee70462016-10-31 04:05:12 -07001996
1997 // Histograms are updated when the statistics_proxy_ is deleted.
1998 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001999 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2000 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2001 EXPECT_METRIC_EQ(
2002 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2003 0));
asapersson4ee70462016-10-31 04:05:12 -07002004 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002005 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_OneResolutionDisabled) {
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 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002029 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002030 encoded_image._encodedWidth = kWidth / 2;
2031 encoded_image._encodedHeight = kHeight / 2;
2032 for (int i = 0; i < kMinSamples; ++i) {
2033 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002034 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2035 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002036 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002037 }
asapersson4ee70462016-10-31 04:05:12 -07002038
2039 // Histograms are updated when the statistics_proxy_ is deleted.
2040 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002041 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2042 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2043 EXPECT_METRIC_EQ(
2044 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2045 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002046 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002047 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2048 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2049 EXPECT_METRIC_EQ(
2050 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2051 1));
asapersson4ee70462016-10-31 04:05:12 -07002052}
2053
2054TEST_F(SendStatisticsProxyTest,
2055 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002056 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2057 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002058 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002059 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002060 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002061 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002062
2063 // Histograms are updated when the statistics_proxy_ is deleted.
2064 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002065 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002066 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002067 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2068 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002069}
2070
2071TEST_F(SendStatisticsProxyTest,
2072 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002073 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002074 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002075 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002076 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002077 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002078
2079 // Histograms are updated when the statistics_proxy_ is deleted.
2080 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002081 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002082 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002083 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2084 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002085 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002086 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2087 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002088}
2089
2090TEST_F(SendStatisticsProxyTest,
2091 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2092 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002093 VideoAdaptationCounters cpu_counts;
2094 VideoAdaptationCounters quality_counts;
2095 quality_counts.resolution_adaptations = kDownscales;
2096 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002097 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2098 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002099 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002100 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002101 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002102 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002103 // Histograms are updated when the statistics_proxy_ is deleted.
2104 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002105 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002106 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002107 EXPECT_METRIC_EQ(
2108 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2109 100));
asapersson4ee70462016-10-31 04:05:12 -07002110 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002111 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2112 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2113 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002114 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2115 kDownscales));
2116}
2117
2118TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2119 // Initially false.
2120 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002121
Åsa Perssonaa329e72017-12-15 15:54:44 +01002122 // Configure two streams.
2123 VideoEncoderConfig config;
2124 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002125 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002126 VideoStream stream1;
2127 stream1.width = kWidth / 2;
2128 stream1.height = kHeight / 2;
2129 VideoStream stream2;
2130 stream2.width = kWidth;
2131 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002132 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002133
Åsa Perssonaa329e72017-12-15 15:54:44 +01002134 // One stream encoded.
2135 EncodedImage encoded_image;
2136 encoded_image._encodedWidth = kWidth / 2;
2137 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002138
2139 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002140 VideoAdaptationCounters cpu_counts;
2141 VideoAdaptationCounters quality_counts;
2142 quality_counts.resolution_adaptations = 1;
2143 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2144 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002145 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2146 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002147 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2148 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002149
2150 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002151 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002152 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2153 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002154 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2155 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2156
2157 // Bw disabled one layer.
2158 VideoCodec codec;
2159 codec.numberOfSimulcastStreams = 2;
2160 codec.simulcastStream[0].active = true;
2161 codec.simulcastStream[1].active = true;
2162 VideoBitrateAllocation allocation;
2163 // Some positive bitrate only on the second stream.
2164 allocation.SetBitrate(1, 0, 10000);
2165 allocation.set_bw_limited(true);
2166 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2167 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002168
2169 // Revert for the next test.
2170 allocation.set_bw_limited(false);
2171 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2172 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2173
2174 // Internal encoder scaler reduced resolution.
2175 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2176 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002177}
2178
asapersson66d4b372016-12-19 06:50:53 -08002179TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2180 // Initially zero.
2181 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2182
2183 const int kBitrate = 100000;
2184 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2185 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2186
2187 statistics_proxy_->OnSetEncoderTargetRate(0);
2188 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2189}
2190
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002191TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002192 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002193 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2194 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002195 1;
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002196 // From ReportBlockDataObserver.
2197 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2198 RTCPReportBlock report_block;
2199 report_block.source_ssrc = excluded_ssrc;
2200 ReportBlockData data;
2201 data.SetReportBlock(report_block, 0);
2202 rtcp_callback->OnReportBlockDataUpdated(data);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002203
2204 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002205 uint32_t total = 0;
2206 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002207 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002208 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002209
2210 // From FrameCountObserver.
2211 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002212 FrameCounts frame_counts;
2213 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002214 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002215
2216 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2217 EXPECT_TRUE(stats.substreams.empty());
2218}
2219
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002220TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2221 static const int kEncodedWidth = 123;
2222 static const int kEncodedHeight = 81;
2223 EncodedImage encoded_image;
2224 encoded_image._encodedWidth = kEncodedWidth;
2225 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002226 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002227
kjellander02b3d272016-04-20 05:05:54 -07002228 CodecSpecificInfo codec_info;
2229 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002230
kjellander02b3d272016-04-20 05:05:54 -07002231 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002232 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002233 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002234
2235 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002236 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2237 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2238 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2239 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002240
2241 // Forward almost to timeout, this should not have removed stats.
2242 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2243 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002244 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2245 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002246
2247 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2248 // resolution still times out (no global timeout for all stats).
Danil Chapovalovf01c2c92021-05-14 15:39:23 +02002249 ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2250 RTCPReportBlock report_block;
2251 report_block.source_ssrc = config_.rtp.ssrcs[0];
2252 ReportBlockData data;
2253 data.SetReportBlock(report_block, 0);
2254 rtcp_callback->OnReportBlockDataUpdated(data);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002255
2256 // Report stats for second SSRC to make sure it's not outdated along with the
2257 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002258 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002259
2260 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2261 // reported, but substream 1 should.
2262 fake_clock_.AdvanceTimeMilliseconds(1);
2263 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002264 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2265 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2266 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2267 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002268}
2269
Peter Boström20f3f942015-05-15 11:33:39 +02002270TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2271 static const int kEncodedWidth = 123;
2272 static const int kEncodedHeight = 81;
2273 EncodedImage encoded_image;
2274 encoded_image._encodedWidth = kEncodedWidth;
2275 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002276 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002277
kjellander02b3d272016-04-20 05:05:54 -07002278 CodecSpecificInfo codec_info;
2279 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002280
kjellander02b3d272016-04-20 05:05:54 -07002281 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002282 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002283 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002284
2285 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2286 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2287 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2288 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2289 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2290 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2291}
2292
2293TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002294 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002295 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2296 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2297 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2298
2299 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2300
2301 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002302 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002303 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002304 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002305 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2306 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2307 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2308}
2309
sprang07fb9be2016-02-24 07:55:00 -08002310TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2311 RtcpPacketTypeCounterObserver* proxy =
2312 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2313 RtcpPacketTypeCounter counters;
2314 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2315 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2316 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2317
2318 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2319
2320 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2321 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2322 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2323 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2324 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2325
2326 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2327 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2328
2329 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002330 VideoEncoderConfig config;
2331 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002332 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002333
Ying Wangef3998f2019-12-09 13:06:53 +01002334 EXPECT_METRIC_EQ(
2335 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2336 EXPECT_METRIC_EQ(
2337 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2338 EXPECT_METRIC_EQ(
2339 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2340 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2341 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002342
2343 const int kRate = 60 * 2; // Packets per minute with two streams.
2344
Ying Wangef3998f2019-12-09 13:06:53 +01002345 EXPECT_METRIC_EQ(
2346 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2347 1 * kRate));
2348 EXPECT_METRIC_EQ(
2349 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2350 2 * kRate));
2351 EXPECT_METRIC_EQ(
2352 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2353 3 * kRate));
2354 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002355 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2356 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002357
2358 // New start time but same counter values.
2359 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2360 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2361
2362 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2363
2364 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2365 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2366 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2367 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2368 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2369
2370 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2371 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2372
2373 SetUp(); // Reset stats proxy also causes histograms to be reported.
2374
Ying Wangef3998f2019-12-09 13:06:53 +01002375 EXPECT_METRIC_EQ(
2376 1, metrics::NumSamples(
2377 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2378 EXPECT_METRIC_EQ(1,
2379 metrics::NumSamples(
2380 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2381 EXPECT_METRIC_EQ(1,
2382 metrics::NumSamples(
2383 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2384 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002385 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002386 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2387
Ying Wangef3998f2019-12-09 13:06:53 +01002388 EXPECT_METRIC_EQ(
2389 1,
2390 metrics::NumEvents(
2391 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2392 EXPECT_METRIC_EQ(
2393 1,
2394 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2395 2 * kRate));
2396 EXPECT_METRIC_EQ(
2397 1,
2398 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2399 3 * kRate));
2400 EXPECT_METRIC_EQ(
2401 1, metrics::NumEvents(
2402 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2403 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002404}
2405
Henrik Boströmf45ca372020-03-24 13:30:50 +01002406TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2407 StreamDataCountersCallback* proxy =
2408 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2409 StreamDataCounters counters;
2410 proxy->DataCountersUpdated(counters, kFirstSsrc);
2411 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2412
2413 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2414 VideoSendStream::StreamStats::StreamType::kRtx);
2415 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2416 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2417 VideoSendStream::StreamStats::StreamType::kRtx);
2418 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2419}
2420
asaperssona6a699a2016-11-25 03:52:46 -08002421TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2422 statistics_proxy_.reset(
2423 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2424 VideoEncoderConfig::ContentType::kRealtimeVideo));
2425
2426 StreamDataCountersCallback* proxy =
2427 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2428 StreamDataCounters counters;
2429 proxy->DataCountersUpdated(counters, kFirstSsrc);
2430 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2431
Henrik Boströmf45ca372020-03-24 13:30:50 +01002432 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2433 VideoSendStream::StreamStats::StreamType::kFlexfec);
2434 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2435 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2436 VideoSendStream::StreamStats::StreamType::kFlexfec);
2437 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002438}
2439
2440TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2441 statistics_proxy_.reset(
2442 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2443 VideoEncoderConfig::ContentType::kRealtimeVideo));
2444
2445 StreamDataCountersCallback* proxy =
2446 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002447 StreamDataCounters counters;
2448 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002449
asapersson93e1e232017-02-06 05:18:35 -08002450 const int kMinRequiredPeriodSamples = 8;
2451 const int kPeriodIntervalMs = 2000;
2452 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2453 counters.transmitted.packets += 20;
2454 counters.transmitted.header_bytes += 500;
2455 counters.transmitted.padding_bytes += 1000;
2456 counters.transmitted.payload_bytes += 2000;
2457 counters.retransmitted.packets += 2;
2458 counters.retransmitted.header_bytes += 25;
2459 counters.retransmitted.padding_bytes += 100;
2460 counters.retransmitted.payload_bytes += 250;
2461 counters.fec = counters.retransmitted;
2462 rtx_counters.transmitted = counters.transmitted;
2463 // Advance one interval and update counters.
2464 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2465 proxy->DataCountersUpdated(counters, kFirstSsrc);
2466 proxy->DataCountersUpdated(counters, kSecondSsrc);
2467 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2468 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2469 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2470 }
asaperssona6a699a2016-11-25 03:52:46 -08002471
asaperssona6a699a2016-11-25 03:52:46 -08002472 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002473 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002474 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2475 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002476 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002477 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2478 EXPECT_METRIC_EQ(1,
2479 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002480 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002481 EXPECT_METRIC_EQ(1,
2482 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2483 EXPECT_METRIC_EQ(
2484 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002485 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002486 EXPECT_METRIC_EQ(
2487 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2488 EXPECT_METRIC_EQ(
2489 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002490 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002491 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2492 EXPECT_METRIC_EQ(1,
2493 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002494 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002495 EXPECT_METRIC_EQ(
2496 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2497 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002498 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002499}
2500
Erik Språng22c2b482016-03-01 09:40:42 +01002501TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2502 StreamDataCountersCallback* proxy =
2503 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2504 StreamDataCounters counters;
2505 StreamDataCounters rtx_counters;
2506 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002507
asapersson93e1e232017-02-06 05:18:35 -08002508 const int kMinRequiredPeriodSamples = 8;
2509 const int kPeriodIntervalMs = 2000;
2510 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2511 counters.transmitted.packets += 20;
2512 counters.transmitted.header_bytes += 500;
2513 counters.transmitted.padding_bytes += 1000;
2514 counters.transmitted.payload_bytes += 2000;
2515 counters.retransmitted.packets += 2;
2516 counters.retransmitted.header_bytes += 25;
2517 counters.retransmitted.padding_bytes += 100;
2518 counters.retransmitted.payload_bytes += 250;
2519 counters.fec = counters.retransmitted;
2520 rtx_counters.transmitted = counters.transmitted;
2521 // Advance one interval and update counters.
2522 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2523 proxy->DataCountersUpdated(counters, kFirstSsrc);
2524 proxy->DataCountersUpdated(counters, kSecondSsrc);
2525 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2526 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2527 }
Erik Språng22c2b482016-03-01 09:40:42 +01002528
2529 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002530 VideoEncoderConfig config;
2531 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002532 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002533
asapersson93e1e232017-02-06 05:18:35 -08002534 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002535 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2536 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002537 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002538 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2539 EXPECT_METRIC_EQ(1,
2540 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002541 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002542 EXPECT_METRIC_EQ(1,
2543 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2544 EXPECT_METRIC_EQ(
2545 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002546 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002547 EXPECT_METRIC_EQ(
2548 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2549 EXPECT_METRIC_EQ(
2550 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002551 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002552 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2553 EXPECT_METRIC_EQ(1,
2554 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002555 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002556 EXPECT_METRIC_EQ(
2557 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2558 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002559 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002560
asapersson93e1e232017-02-06 05:18:35 -08002561 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002562 // Double counter values, this should result in the same counts as before but
2563 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002564 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2565 counters.transmitted.packets += 20;
2566 counters.transmitted.header_bytes += 500;
2567 counters.transmitted.padding_bytes += 1000;
2568 counters.transmitted.payload_bytes += 2000;
2569 counters.retransmitted.packets += 2;
2570 counters.retransmitted.header_bytes += 25;
2571 counters.retransmitted.padding_bytes += 100;
2572 counters.retransmitted.payload_bytes += 250;
2573 counters.fec = counters.retransmitted;
2574 rtx_counters.transmitted = counters.transmitted;
2575 // Advance one interval and update counters.
2576 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2577 proxy->DataCountersUpdated(counters, kFirstSsrc);
2578 proxy->DataCountersUpdated(counters, kSecondSsrc);
2579 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2580 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2581 }
Erik Språng22c2b482016-03-01 09:40:42 +01002582
asapersson93e1e232017-02-06 05:18:35 -08002583 // Reset stats proxy also causes histograms to be reported.
2584 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002585
asapersson93e1e232017-02-06 05:18:35 -08002586 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002587 EXPECT_METRIC_EQ(
2588 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2589 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002590 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2591 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002592 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002593 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002594 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2595 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002596 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002597 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2598 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2599 EXPECT_METRIC_EQ(
2600 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2601 12));
asapersson93e1e232017-02-06 05:18:35 -08002602 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002603 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2604 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2605 EXPECT_METRIC_EQ(
2606 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2607 16));
asapersson93e1e232017-02-06 05:18:35 -08002608 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002609 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002610 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002611 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2612 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002613 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002614 EXPECT_METRIC_EQ(
2615 1, metrics::NumSamples(
2616 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2617 EXPECT_METRIC_EQ(
2618 1, metrics::NumEvents(
2619 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002620}
Erik Språng22c2b482016-03-01 09:40:42 +01002621
asapersson93e1e232017-02-06 05:18:35 -08002622TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2623 StreamDataCountersCallback* proxy =
2624 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2625 StreamDataCounters counters;
2626 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002627
asapersson93e1e232017-02-06 05:18:35 -08002628 const int kMinRequiredPeriodSamples = 8;
2629 const int kPeriodIntervalMs = 2000;
2630 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2631 counters.transmitted.packets += 20;
2632 counters.transmitted.header_bytes += 500;
2633 counters.transmitted.payload_bytes += 2000;
2634 counters.fec = counters.retransmitted;
2635 // Advance one interval and update counters.
2636 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2637 proxy->DataCountersUpdated(counters, kFirstSsrc);
2638 }
2639
2640 // RTX enabled. No data sent over RTX.
2641 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002642 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2643 EXPECT_METRIC_EQ(1,
2644 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002645}
2646
2647TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2648 VideoSendStream::Config config(nullptr);
2649 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2650 statistics_proxy_.reset(new SendStatisticsProxy(
2651 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2652
2653 StreamDataCountersCallback* proxy =
2654 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2655 StreamDataCounters counters;
2656
2657 const int kMinRequiredPeriodSamples = 8;
2658 const int kPeriodIntervalMs = 2000;
2659 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2660 counters.transmitted.packets += 20;
2661 counters.transmitted.header_bytes += 500;
2662 counters.transmitted.payload_bytes += 2000;
2663 counters.fec = counters.retransmitted;
2664 // Advance one interval and update counters.
2665 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2666 proxy->DataCountersUpdated(counters, kFirstSsrc);
2667 }
2668
2669 // RTX not enabled.
2670 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002671 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002672}
2673
2674TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2675 StreamDataCountersCallback* proxy =
2676 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2677 StreamDataCounters counters;
2678 StreamDataCounters rtx_counters;
2679
2680 const int kMinRequiredPeriodSamples = 8;
2681 const int kPeriodIntervalMs = 2000;
2682 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2683 counters.transmitted.packets += 20;
2684 counters.transmitted.header_bytes += 500;
2685 counters.transmitted.payload_bytes += 2000;
2686 // Advance one interval and update counters.
2687 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2688 proxy->DataCountersUpdated(counters, kFirstSsrc);
2689 }
2690
2691 // FEC enabled. No FEC data sent.
2692 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002693 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2694 EXPECT_METRIC_EQ(1,
2695 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002696}
2697
2698TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2699 VideoSendStream::Config config(nullptr);
2700 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2701 statistics_proxy_.reset(new SendStatisticsProxy(
2702 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2703
2704 StreamDataCountersCallback* proxy =
2705 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2706 StreamDataCounters counters;
2707
2708 const int kMinRequiredPeriodSamples = 8;
2709 const int kPeriodIntervalMs = 2000;
2710 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2711 counters.transmitted.packets += 20;
2712 counters.transmitted.header_bytes += 500;
2713 counters.transmitted.payload_bytes += 2000;
2714 counters.fec = counters.retransmitted;
2715 // Advance one interval and update counters.
2716 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2717 proxy->DataCountersUpdated(counters, kFirstSsrc);
2718 }
2719
2720 // FEC not enabled.
2721 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002722 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002723}
2724
asapersson8d75ac72017-09-15 06:41:15 -07002725TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002726 const std::string kName = "encoderName";
2727 statistics_proxy_->OnEncoderImplementationChanged(kName);
2728 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002729}
2730
Sergey Silkinbb081a62018-09-04 18:34:22 +02002731TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2732 static const int kEncodedWidth = 123;
2733 static const int kEncodedHeight = 81;
2734 EncodedImage encoded_image;
2735 encoded_image._encodedWidth = kEncodedWidth;
2736 encoded_image._encodedHeight = kEncodedHeight;
2737 encoded_image.SetSpatialIndex(0);
2738
2739 CodecSpecificInfo codec_info;
2740 codec_info.codecType = kVideoCodecVP9;
2741
2742 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002743 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002744 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2745 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2746 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2747 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2748
2749 // Top layer updates resolution.
2750 encoded_image._encodedWidth = kEncodedWidth * 2;
2751 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002752 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002753 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2754 stats = statistics_proxy_->GetStats();
2755 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2756 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2757
2758 // Low layer of next frame doesn't update resolution.
2759 encoded_image._encodedWidth = kEncodedWidth;
2760 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002761 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002762 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2763 stats = statistics_proxy_->GetStats();
2764 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2765 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2766}
2767
asapersson8d75ac72017-09-15 06:41:15 -07002768class ForcedFallbackTest : public SendStatisticsProxyTest {
2769 public:
2770 explicit ForcedFallbackTest(const std::string& field_trials)
2771 : SendStatisticsProxyTest(field_trials) {
2772 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002773 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002774 encoded_image_._encodedWidth = kWidth;
2775 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002776 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002777 }
2778
2779 ~ForcedFallbackTest() override {}
2780
2781 protected:
2782 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002783 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2784
asapersson8d75ac72017-09-15 06:41:15 -07002785 // First frame is not updating stats, insert initial frame.
2786 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2787 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2788 }
2789 for (int i = 0; i < num_frames; ++i) {
2790 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2791 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2792 }
2793 // Add frame to include last time interval.
2794 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2795 }
2796
2797 EncodedImage encoded_image_;
2798 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002799 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002800 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2801 const int kFrameIntervalMs = 1000;
2802 const int kMinFrames = 20; // Min run time 20 sec.
2803};
2804
2805class ForcedFallbackDisabled : public ForcedFallbackTest {
2806 public:
2807 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002808 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2809 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002810};
2811
2812class ForcedFallbackEnabled : public ForcedFallbackTest {
2813 public:
2814 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002815 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2816 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002817};
2818
2819TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2820 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2821 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002822 EXPECT_METRIC_EQ(0,
2823 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2824 EXPECT_METRIC_EQ(
2825 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002826}
2827
2828TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2829 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002830 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002831 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002832 EXPECT_METRIC_EQ(1,
2833 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2834 EXPECT_METRIC_EQ(
2835 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2836 EXPECT_METRIC_EQ(
2837 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2838 EXPECT_METRIC_EQ(
2839 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002840}
2841
2842TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2843 codec_info_.codecType = kVideoCodecVP9;
2844 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2845 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002846 EXPECT_METRIC_EQ(0,
2847 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2848 EXPECT_METRIC_EQ(
2849 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002850}
2851
2852TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2853 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2854 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2855 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002856 EXPECT_METRIC_EQ(0,
2857 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2858 EXPECT_METRIC_EQ(
2859 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002860}
2861
2862TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002863 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002864 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2865 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002866 EXPECT_METRIC_EQ(0,
2867 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2868 EXPECT_METRIC_EQ(
2869 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002870}
2871
2872TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2873 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2874 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002875 EXPECT_METRIC_EQ(0,
2876 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2877 EXPECT_METRIC_EQ(
2878 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002879}
2880
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002881TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2882 InsertEncodedFrames(1, kFrameIntervalMs);
2883 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2884}
2885
2886TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2887 InsertEncodedFrames(1, kFrameIntervalMs);
2888 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2889}
2890
2891TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002892 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002893 InsertEncodedFrames(1, kFrameIntervalMs);
2894 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2895}
2896
2897TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2898 encoded_image_._encodedWidth = kWidth + 1;
2899 InsertEncodedFrames(1, kFrameIntervalMs);
2900 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2901}
2902
2903TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002904 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002905 InsertEncodedFrames(1, kFrameIntervalMs);
2906 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2907}
2908
2909TEST_F(ForcedFallbackDisabled,
2910 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2911 encoded_image_._encodedWidth = kWidth + 1;
2912 statistics_proxy_->OnMinPixelLimitReached();
2913 InsertEncodedFrames(1, kFrameIntervalMs);
2914 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2915}
2916
asapersson8d75ac72017-09-15 06:41:15 -07002917TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2918 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002919 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002920 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002921 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002922 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002923 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002924 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002925
2926 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002927 EXPECT_METRIC_EQ(1,
2928 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2929 EXPECT_METRIC_EQ(
2930 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2931 EXPECT_METRIC_EQ(
2932 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2933 EXPECT_METRIC_EQ(
2934 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002935}
2936
2937TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2938 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2939 const int kMaxFrameDiffMs = 2000;
2940
2941 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2942 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002943 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002944 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002945 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002946 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002947 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002948 InsertEncodedFrames(20, 1000);
2949 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2950 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002951 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002952 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002953 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002954 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002955 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002956 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002957 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002958
2959 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002960 EXPECT_METRIC_EQ(1,
2961 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2962 EXPECT_METRIC_EQ(
2963 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2964 EXPECT_METRIC_EQ(
2965 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2966 EXPECT_METRIC_EQ(
2967 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002968}
2969
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002970TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2971 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002972 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002973 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2974
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002975 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002976 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002977 EXPECT_METRIC_EQ(0,
2978 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2979 EXPECT_METRIC_EQ(
2980 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002981}
2982
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002983TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2984 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002985 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002986 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2987
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002988 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002989 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002990 EXPECT_METRIC_EQ(1,
2991 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2992 EXPECT_METRIC_EQ(
2993 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002994}
2995
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002996} // namespace webrtc