blob: bce79a5c97c7ace77dd4b2a8519eb7057072c8be [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),
67 config_(GetTestConfig()),
68 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070069 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000070 virtual ~SendStatisticsProxyTest() {}
71
72 protected:
73 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070074 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080075 statistics_proxy_.reset(new SendStatisticsProxy(
76 &fake_clock_, GetTestConfig(),
77 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000078 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010079 for (const auto& ssrc : config_.rtp.ssrcs) {
80 expected_.substreams[ssrc].type =
81 VideoSendStream::StreamStats::StreamType::kMedia;
82 }
83 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
84 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
85 expected_.substreams[ssrc].type =
86 VideoSendStream::StreamStats::StreamType::kRtx;
87 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
88 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000089 }
90
91 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070092 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080093 config.rtp.ssrcs.push_back(kFirstSsrc);
94 config.rtp.ssrcs.push_back(kSecondSsrc);
95 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
96 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070097 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000098 return config;
99 }
100
asaperssona6a699a2016-11-25 03:52:46 -0800101 VideoSendStream::Config GetTestConfigWithFlexFec() {
102 VideoSendStream::Config config(nullptr);
103 config.rtp.ssrcs.push_back(kFirstSsrc);
104 config.rtp.ssrcs.push_back(kSecondSsrc);
105 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
106 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -0800107 config.rtp.flexfec.payload_type = 50;
108 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +0100109 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -0800110 return config;
111 }
112
113 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
114 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
115 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
116 stats.substreams.find(ssrc);
117 EXPECT_NE(it, stats.substreams.end());
118 return it->second;
119 }
120
asapersson66d4b372016-12-19 06:50:53 -0800121 void UpdateDataCounters(uint32_t ssrc) {
122 StreamDataCountersCallback* proxy =
123 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
124 StreamDataCounters counters;
125 proxy->DataCountersUpdated(counters, ssrc);
126 }
127
sprang@webrtc.org09315702014-02-07 12:06:29 +0000128 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
Di Wu668dbf62021-02-27 00:29:15 -0800129 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000130 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
131 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000132 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000133 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000134
135 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000136 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000137 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000138 it != one.substreams.end(); ++it) {
139 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
140 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000141 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000142 const VideoSendStream::StreamStats& a = it->second;
143 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000144
Henrik Boströmf45ca372020-03-24 13:30:50 +0100145 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000146 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
147 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000148 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000149 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
150 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000151
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000152 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
153 b.rtp_stats.transmitted.payload_bytes);
154 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
155 b.rtp_stats.transmitted.header_bytes);
156 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
157 b.rtp_stats.transmitted.padding_bytes);
158 EXPECT_EQ(a.rtp_stats.transmitted.packets,
159 b.rtp_stats.transmitted.packets);
160 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
161 b.rtp_stats.retransmitted.packets);
162 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000163
164 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700165 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
166 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
167 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000168 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
169 }
170 }
171
asapersson8d75ac72017-09-15 06:41:15 -0700172 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000173 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800174 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000175 VideoSendStream::Config config_;
176 int avg_delay_ms_;
177 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000178 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000179 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
180 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000181};
182
183TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
184 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700185 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000186 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000187
188 // Add statistics with some arbitrary, but unique, numbers.
189 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700190 ssrc_stats.rtcp_stats.packets_lost = offset;
191 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000192 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
193 ssrc_stats.rtcp_stats.jitter = offset + 3;
194 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
195 }
asapersson35151f32016-05-02 23:44:01 -0700196 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000197 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000198
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000199 // Add statistics with some arbitrary, but unique, numbers.
200 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700201 ssrc_stats.rtcp_stats.packets_lost = offset;
202 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000203 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
204 ssrc_stats.rtcp_stats.jitter = offset + 3;
205 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
206 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000207 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000208 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000209}
210
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000211TEST_F(SendStatisticsProxyTest, Suspended) {
212 // Verify that the value is false by default.
213 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
214
215 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200216 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000217 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
218
219 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200220 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000221 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
222}
223
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224TEST_F(SendStatisticsProxyTest, FrameCounts) {
225 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700226 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000227 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000228 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
229 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000230 FrameCounts frame_counts;
231 frame_counts.key_frames = offset;
232 frame_counts.delta_frames = offset + 1;
233 stats.frame_counts = frame_counts;
234 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000235 }
asapersson35151f32016-05-02 23:44:01 -0700236 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000237 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000238 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
239 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000240 FrameCounts frame_counts;
241 frame_counts.key_frames = offset;
242 frame_counts.delta_frames = offset + 1;
243 stats.frame_counts = frame_counts;
244 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000245 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000246
247 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000248 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000249}
250
251TEST_F(SendStatisticsProxyTest, DataCounters) {
252 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700253 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000254 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
255 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000256 size_t offset = ssrc * sizeof(StreamDataCounters);
257 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000258 counters.transmitted.payload_bytes = offset;
259 counters.transmitted.header_bytes = offset + 1;
260 counters.fec.packets = offset_uint32 + 2;
261 counters.transmitted.padding_bytes = offset + 3;
262 counters.retransmitted.packets = offset_uint32 + 4;
263 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000264 callback->DataCountersUpdated(counters, ssrc);
265 }
asapersson35151f32016-05-02 23:44:01 -0700266 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000267 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
268 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000269 size_t offset = ssrc * sizeof(StreamDataCounters);
270 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000271 counters.transmitted.payload_bytes = offset;
272 counters.transmitted.header_bytes = offset + 1;
273 counters.fec.packets = offset_uint32 + 2;
274 counters.transmitted.padding_bytes = offset + 3;
275 counters.retransmitted.packets = offset_uint32 + 4;
276 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000277 callback->DataCountersUpdated(counters, ssrc);
278 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000279
280 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000281 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000282}
283
284TEST_F(SendStatisticsProxyTest, Bitrate) {
285 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700286 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700287 uint32_t total;
288 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000289 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700290 total = ssrc;
291 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000292 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700293 expected_.substreams[ssrc].total_bitrate_bps = total;
294 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000295 }
asapersson35151f32016-05-02 23:44:01 -0700296 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700297 uint32_t total;
298 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000299 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700300 total = ssrc;
301 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000302 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700303 expected_.substreams[ssrc].total_bitrate_bps = total;
304 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000305 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000306
307 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000308 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000309}
310
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000311TEST_F(SendStatisticsProxyTest, SendSideDelay) {
312 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700313 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000314 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
315 // stream.
316 int avg_delay_ms = ssrc;
317 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200318 uint64_t total_packet_send_delay_ms = ssrc + 2;
319 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
320 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000321 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
322 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200323 expected_.substreams[ssrc].total_packet_send_delay_ms =
324 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000325 }
asapersson35151f32016-05-02 23:44:01 -0700326 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000327 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
328 // stream.
329 int avg_delay_ms = ssrc;
330 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200331 uint64_t total_packet_send_delay_ms = ssrc + 2;
332 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
333 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000334 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
335 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200336 expected_.substreams[ssrc].total_packet_send_delay_ms =
337 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000338 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000339 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000340 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000341}
342
Peter Boströme4499152016-02-05 11:13:28 +0100343TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800344 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200345 int encode_usage_percent = 80;
346 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
347 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800348
349 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
350 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200351 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800352}
353
Henrik Boström5684af52019-04-02 15:05:21 +0200354TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
355 const int kEncodeUsagePercent = 0; // Don't care for this test.
356 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
357 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
358 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
359 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
360 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
361}
362
sakal43536c32016-10-24 01:46:43 -0700363TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
364 EncodedImage encoded_image;
365 CodecSpecificInfo codec_info;
366 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
367 for (uint32_t i = 1; i <= 3; ++i) {
368 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
369 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
370 }
371}
372
sakal87da4042016-10-31 06:53:47 -0700373TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
374 EncodedImage encoded_image;
375 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200376 auto ssrc = config_.rtp.ssrcs[0];
377 EXPECT_EQ(absl::nullopt,
378 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700379 encoded_image.qp_ = 3;
380 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200381 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700382 encoded_image.qp_ = 127;
383 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200384 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700385}
386
387TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
388 EncodedImage encoded_image;
389 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200390 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700391 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200392 EXPECT_EQ(absl::nullopt,
393 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700394 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200395 EXPECT_EQ(absl::nullopt,
396 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700397}
398
Henrik Boström23aff9b2019-05-20 15:15:38 +0200399TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
400 const uint32_t kTargetBytesPerSecond = 100000;
401 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
402 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
403
404 EncodedImage encoded_image;
405 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
406 // On the first frame we don't know the frame rate yet, calculation yields
407 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
408 // increment by a full |kTargetBytesPerSecond|.
409 EXPECT_EQ(kTargetBytesPerSecond,
410 statistics_proxy_->GetStats().total_encoded_bytes_target);
411}
412
413TEST_F(SendStatisticsProxyTest,
414 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
415 const uint32_t kTargetBytesPerSecond = 100000;
416 const int kInterframeDelayMs = 100;
417
418 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
419 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
420 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
421 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
422 // this test can stop relying on rtc::ScopedFakeClock.
423 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100424 fake_global_clock.SetTime(
425 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200426
427 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
428 EncodedImage encoded_image;
429
430 // First frame
431 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
432 uint64_t first_total_encoded_bytes_target =
433 statistics_proxy_->GetStats().total_encoded_bytes_target;
434 // Second frame
435 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
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 encoded_image.SetTimestamp(encoded_image.Timestamp() +
439 90 * kInterframeDelayMs);
440 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
441
442 auto stats = statistics_proxy_->GetStats();
443 // By the time the second frame arrives, one frame has previously arrived
444 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
445 // the second frame's arrival should be 10 FPS.
446 uint64_t delta_encoded_bytes_target =
447 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
448 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
449}
450
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200451TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
452 const int kInterframeDelayMs = 100;
453 auto ssrc = config_.rtp.ssrcs[0];
454 rtc::ScopedFakeClock fake_global_clock;
455 fake_global_clock.SetTime(
456 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
457
458 EncodedImage encoded_image;
459
460 // First frame
461 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
462 // Second frame
463 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
464 fake_global_clock.SetTime(
465 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
466 encoded_image.SetTimestamp(encoded_image.Timestamp() +
467 90 * kInterframeDelayMs);
468 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
469
470 auto stats = statistics_proxy_->GetStats();
471 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
472}
473
asapersson09f05612017-05-15 23:40:18 -0700474TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200475 VideoAdaptationCounters cpu_counts;
476 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700477 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700478 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200479 cpu_counts.fps_adaptations = 1;
480 cpu_counts.resolution_adaptations = 0;
481 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200482 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
483 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700484 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700485 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200486 cpu_counts.fps_adaptations = 0;
487 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200488 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
489 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700490 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700491 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200492 cpu_counts.fps_adaptations = 1;
493 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
494 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200495 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
496 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700497 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700498 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200499 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
500 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200501 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
502 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700503 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
504 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
505}
506
507TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200508 VideoAdaptationCounters cpu_counts;
509 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700510 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
511 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200512 quality_counts.fps_adaptations = 1;
513 quality_counts.resolution_adaptations = 0;
514 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200515 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
516 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700517 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
518 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200519 quality_counts.fps_adaptations = 0;
520 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200521 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
522 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700523 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
524 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200525 quality_counts.fps_adaptations = 1;
526 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
527 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200528 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
529 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700530 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
531 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200532 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
533 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200534 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
535 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700536 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
537 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
538}
539
540TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200541 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
542 VideoAdaptationCounters cpu_counts;
543 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700544 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
545
Evan Shrubsoledff79252020-04-16 11:34:32 +0200546 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200547 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
548 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700549 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700550 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
551 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
552
Evan Shrubsoledff79252020-04-16 11:34:32 +0200553 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200554 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
555 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700556 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
557 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700558 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700559 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700560}
561
asapersson09f05612017-05-15 23:40:18 -0700562TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200563 VideoAdaptationCounters cpu_counts;
564 VideoAdaptationCounters quality_counts;
565 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700566 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
567
Evan Shrubsoledff79252020-04-16 11:34:32 +0200568 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200569 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
570 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700571 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
572 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700573 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
574
Evan Shrubsoledff79252020-04-16 11:34:32 +0200575 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200576 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
577 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700578 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700579 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700580 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
581 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700582}
583
Evan Shrubsoledff79252020-04-16 11:34:32 +0200584TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
585 VideoAdaptationCounters cpu_counts;
586 VideoAdaptationCounters quality_counts;
587 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
588 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
589 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
590
591 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200592 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
593 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200594 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200595 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
596 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200597 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200598 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
599 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200600 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200601 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
602 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200603 // We have 1 fps and resolution reduction for both cpu and quality
604 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
605 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
606 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
607 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
608 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
609 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
610
611 // Disable quality scaling. Expect quality scaling not limited.
612 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
613 kScalingDisabled);
614 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
615 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
616 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
617 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
618 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
619 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
620
621 // Disable framerate scaling.
622 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
623 kFramerateScalingDisabled);
624 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
625 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
626 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
627 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
628 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
629 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
630
631 // Disable resolution scaling.
632 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
633 kResolutionScalingDisabled);
634 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
635 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
636 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
637 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
638 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
639 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
640
641 // Enable all
642 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
643 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
644 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
645 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
646 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
647 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
648 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
649}
650
asapersson09f05612017-05-15 23:40:18 -0700651TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700652 // First RTP packet sent.
653 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700654 // Min runtime has passed.
655 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
656 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100657 EXPECT_METRIC_EQ(
658 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
659 EXPECT_METRIC_EQ(
660 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700661}
662
663TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700664 // First RTP packet sent.
665 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700666 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200667 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700668 // Min runtime has not passed.
669 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
670 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100671 EXPECT_METRIC_EQ(
672 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
673 EXPECT_METRIC_EQ(
674 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700675}
676
asapersson09f05612017-05-15 23:40:18 -0700677TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700678 // First RTP packet sent.
679 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700680 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200681 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700682 // Min runtime has passed.
683 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
684 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100685 EXPECT_METRIC_EQ(
686 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
687 EXPECT_METRIC_EQ(
688 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
689 EXPECT_METRIC_EQ(
690 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
691 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700692 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
693}
694
695TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700696 // First RTP packet sent.
697 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700698 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200699 VideoAdaptationCounters cpu_counts;
700 VideoAdaptationCounters quality_counts;
701 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700702 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200703 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
704 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700705 fake_clock_.AdvanceTimeMilliseconds(10000);
706 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100707 EXPECT_METRIC_EQ(
708 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
709 EXPECT_METRIC_EQ(
710 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700711}
712
Åsa Persson875841d2018-01-08 08:49:53 +0100713TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
714 // First RTP packet sent.
715 UpdateDataCounters(kFirstSsrc);
716 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200717 VideoAdaptationCounters cpu_counts;
718 VideoAdaptationCounters quality_counts;
719 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100720 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200721 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
722 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100723 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
724 fake_clock_.AdvanceTimeMilliseconds(10000);
725 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100726 EXPECT_METRIC_EQ(
727 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
728 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100729 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
730}
731
732TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
733 // First RTP packet sent.
734 UpdateDataCounters(kFirstSsrc);
735 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200736 VideoAdaptationCounters cpu_counts;
737 VideoAdaptationCounters quality_counts;
738 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100739 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200740 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200741 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
742 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100743 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200744 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200745 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
746 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100747 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200748 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200749 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
750 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100751 fake_clock_.AdvanceTimeMilliseconds(10000);
752 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100753 EXPECT_METRIC_EQ(
754 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
755 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100756 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
757}
758
759TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
760 // First RTP packet sent.
761 UpdateDataCounters(kFirstSsrc);
762 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200763 VideoAdaptationCounters cpu_counts;
764 VideoAdaptationCounters quality_counts;
765 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100766 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200767 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
768 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100769 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
770 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
771 fake_clock_.AdvanceTimeMilliseconds(10000);
772 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100773 EXPECT_METRIC_EQ(
774 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
775 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100776 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
777}
778
779TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
780 // First RTP packet sent.
781 UpdateDataCounters(kFirstSsrc);
782 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200783 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
784 VideoAdaptationCounters cpu_counts;
785 VideoAdaptationCounters quality_counts;
786 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100787 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200788 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200789 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
790 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100791 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200792 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200793 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
794 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100795 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200796 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200797 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
798 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200799 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200800 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
801 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200802 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200803 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
804 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200805 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200806 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
807 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200808 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200809 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
810 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200811 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200812 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
813 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100814
815 fake_clock_.AdvanceTimeMilliseconds(10000);
816 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100817 EXPECT_METRIC_EQ(
818 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
819 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100820 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
821}
822
asapersson6eca98b2017-04-04 23:40:50 -0700823TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700824 // First RTP packet sent.
825 UpdateDataCounters(kFirstSsrc);
826
asapersson09f05612017-05-15 23:40:18 -0700827 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200828 VideoAdaptationCounters cpu_counts;
829 VideoAdaptationCounters quality_counts;
830 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
831 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700832 fake_clock_.AdvanceTimeMilliseconds(10000);
833
asapersson09f05612017-05-15 23:40:18 -0700834 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700835 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200836 quality_counts.fps_adaptations = 0;
837 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
838 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700839 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200840 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
841 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700842 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200843 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
844 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700845 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200846 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
847 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700848
asapersson09f05612017-05-15 23:40:18 -0700849 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200850 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
851 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700852 fake_clock_.AdvanceTimeMilliseconds(30000);
853
asapersson09f05612017-05-15 23:40:18 -0700854 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700855 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200856 quality_counts.resolution_adaptations = 0;
857 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
858 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200859 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
860 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700861 fake_clock_.AdvanceTimeMilliseconds(10000);
862
asapersson09f05612017-05-15 23:40:18 -0700863 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200864 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
865 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700866 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200867 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
868 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700869 fake_clock_.AdvanceTimeMilliseconds(20000);
870
asapersson0944a802017-04-07 00:57:58 -0700871 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700872 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100873 EXPECT_METRIC_EQ(
874 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
875 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700876 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
877}
878
asapersson0944a802017-04-07 00:57:58 -0700879TEST_F(SendStatisticsProxyTest,
880 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
881 // First RTP packet sent.
882 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700883
asapersson0944a802017-04-07 00:57:58 -0700884 // Suspend and resume video.
885 statistics_proxy_->OnSuspendChange(true);
886 fake_clock_.AdvanceTimeMilliseconds(5000);
887 statistics_proxy_->OnSuspendChange(false);
888
889 // Min runtime has passed but scaling not enabled.
890 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
891 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100892 EXPECT_METRIC_EQ(
893 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
894 EXPECT_METRIC_EQ(
895 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700896}
897
898TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
899 // First RTP packet sent.
900 UpdateDataCounters(kFirstSsrc);
901
asapersson09f05612017-05-15 23:40:18 -0700902 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200903 VideoAdaptationCounters cpu_counts;
904 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700905 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200906 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700907 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200908 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
909 cpu_counts, quality_counts);
910 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
911 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700912
913 // Suspend and resume video.
914 statistics_proxy_->OnSuspendChange(true);
915 fake_clock_.AdvanceTimeMilliseconds(30000);
916 statistics_proxy_->OnSuspendChange(false);
917
918 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200919 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
920 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700921 fake_clock_.AdvanceTimeMilliseconds(10000);
922
923 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
924 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100925 EXPECT_METRIC_EQ(
926 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
927 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700928 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
929}
930
931TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
932 // First RTP packet sent.
933 UpdateDataCounters(kFirstSsrc);
934
935 // Video not suspended.
936 statistics_proxy_->OnSuspendChange(false);
937 fake_clock_.AdvanceTimeMilliseconds(30000);
938
asapersson09f05612017-05-15 23:40:18 -0700939 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200940 VideoAdaptationCounters cpu_counts;
941 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700942 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200943 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700944 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200945 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
946 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700947
948 // Video not suspended, stats time already started.
949 statistics_proxy_->OnSuspendChange(false);
950 fake_clock_.AdvanceTimeMilliseconds(10000);
951
asapersson09f05612017-05-15 23:40:18 -0700952 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200953 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
954 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -0700955 fake_clock_.AdvanceTimeMilliseconds(30000);
956
957 // Suspend and resume video, stats time not started when scaling not enabled.
958 statistics_proxy_->OnSuspendChange(true);
959 fake_clock_.AdvanceTimeMilliseconds(30000);
960 statistics_proxy_->OnSuspendChange(false);
961 fake_clock_.AdvanceTimeMilliseconds(30000);
962
asapersson09f05612017-05-15 23:40:18 -0700963 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700964 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200965 cpu_counts.fps_adaptations = 0;
966 cpu_counts.resolution_adaptations = 0;
967 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700968 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200969 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
970 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700971
972 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
973 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100974 EXPECT_METRIC_EQ(
975 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
976 EXPECT_METRIC_EQ(
977 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700978}
979
980TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
981 // First RTP packet sent.
982 UpdateDataCounters(kFirstSsrc);
983
984 // Video suspended.
985 statistics_proxy_->OnSuspendChange(true);
986
asapersson09f05612017-05-15 23:40:18 -0700987 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200988 VideoAdaptationCounters cpu_counts;
989 VideoAdaptationCounters quality_counts;
990 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700991 fake_clock_.AdvanceTimeMilliseconds(10000);
992
993 // Resume video, stats time started.
994 // Adapt changes: 1, elapsed time: 10 sec.
995 statistics_proxy_->OnSuspendChange(false);
996 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200997 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
998 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700999
1000 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1001 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001002 EXPECT_METRIC_EQ(
1003 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1004 EXPECT_METRIC_EQ(
1005 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001006}
1007
1008TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001009 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001010 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001011 VideoAdaptationCounters cpu_counts;
1012 VideoAdaptationCounters quality_counts;
1013 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001014 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001015 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001016
asapersson0944a802017-04-07 00:57:58 -07001017 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001018 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001019 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1020 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001021 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001022
asapersson0944a802017-04-07 00:57:58 -07001023 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001024 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001025 EXPECT_METRIC_EQ(
1026 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1027 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001028 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1029}
1030
1031TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001032 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001033 VideoAdaptationCounters cpu_counts;
1034 VideoAdaptationCounters quality_counts;
1035 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001036 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001037 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1038 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001039
1040 // Send first packet, scaling disabled.
1041 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001042 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001043 fake_clock_.AdvanceTimeMilliseconds(60000);
1044
asapersson09f05612017-05-15 23:40:18 -07001045 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001046 cpu_counts.resolution_adaptations = 0;
1047 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1048 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001049 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001050 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001051
asapersson0944a802017-04-07 00:57:58 -07001052 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001053 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001054 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1055 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001056
asapersson0944a802017-04-07 00:57:58 -07001057 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001058 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001059 EXPECT_METRIC_EQ(
1060 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1061 EXPECT_METRIC_EQ(
1062 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001063}
1064
1065TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001066 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001067 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001068 VideoAdaptationCounters cpu_counts;
1069 VideoAdaptationCounters quality_counts;
1070 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1071 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001072
asapersson0944a802017-04-07 00:57:58 -07001073 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001074 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1075 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001076 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001077 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1078 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001079 fake_clock_.AdvanceTimeMilliseconds(9000);
1080
1081 // Switch content type, real-time stats should be updated.
1082 VideoEncoderConfig config;
1083 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001084 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001085 EXPECT_METRIC_EQ(
1086 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1087 EXPECT_METRIC_EQ(
1088 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1089 EXPECT_METRIC_EQ(
1090 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001091
asapersson0944a802017-04-07 00:57:58 -07001092 // First RTP packet sent, scaling enabled.
1093 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001094 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1095 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001096
asapersson0944a802017-04-07 00:57:58 -07001097 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001098 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1099 cpu_counts, quality_counts);
1100 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1101 cpu_counts, quality_counts);
1102 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1103 cpu_counts, quality_counts);
1104 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1105 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001106 fake_clock_.AdvanceTimeMilliseconds(120000);
1107
1108 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001109 EXPECT_METRIC_EQ(1,
1110 metrics::NumSamples(
1111 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1112 EXPECT_METRIC_EQ(
1113 1, metrics::NumEvents(
1114 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1115 EXPECT_METRIC_EQ(
1116 0, metrics::NumSamples(
1117 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001118}
1119
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001120TEST_F(SendStatisticsProxyTest,
1121 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001122 VideoAdaptationCounters cpu_counts;
1123 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001124
Evan Shrubsoledff79252020-04-16 11:34:32 +02001125 cpu_counts.resolution_adaptations = 1;
1126 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001127 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1128 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001129
1130 EXPECT_EQ(QualityLimitationReason::kCpu,
1131 statistics_proxy_->GetStats().quality_limitation_reason);
1132}
1133
1134TEST_F(SendStatisticsProxyTest,
1135 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001136 VideoAdaptationCounters cpu_counts;
1137 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001138
Evan Shrubsoledff79252020-04-16 11:34:32 +02001139 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001140
Evan Shrubsoledff79252020-04-16 11:34:32 +02001141 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001142 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1143 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001144
1145 EXPECT_EQ(QualityLimitationReason::kCpu,
1146 statistics_proxy_->GetStats().quality_limitation_reason);
1147}
1148
1149TEST_F(SendStatisticsProxyTest,
1150 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001151 VideoAdaptationCounters cpu_counts;
1152 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001153
Evan Shrubsoledff79252020-04-16 11:34:32 +02001154 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001155
Evan Shrubsoledff79252020-04-16 11:34:32 +02001156 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001157 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1158 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001159
1160 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1161 statistics_proxy_->GetStats().quality_limitation_reason);
1162}
1163
1164TEST_F(SendStatisticsProxyTest,
1165 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001166 VideoAdaptationCounters cpu_counts;
1167 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001168
Evan Shrubsoledff79252020-04-16 11:34:32 +02001169 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001170
Evan Shrubsoledff79252020-04-16 11:34:32 +02001171 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001172 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1173 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001174
1175 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1176 statistics_proxy_->GetStats().quality_limitation_reason);
1177}
1178
1179TEST_F(SendStatisticsProxyTest,
1180 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001181 VideoAdaptationCounters cpu_counts;
1182 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001183
Evan Shrubsoledff79252020-04-16 11:34:32 +02001184 cpu_counts.resolution_adaptations = 1;
1185 quality_counts.resolution_adaptations = 1;
1186 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001187
1188 // Even if the last adaptation reason is kCpu, if the counters indicate being
1189 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001190 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1191 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001192
1193 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1194 statistics_proxy_->GetStats().quality_limitation_reason);
1195}
1196
1197TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001198 VideoAdaptationCounters cpu_counts;
1199 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001200
1201 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1202 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001203 cpu_counts.resolution_adaptations = 1;
1204 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001205 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1206 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001207 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001208 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001209 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1210 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001211
1212 EXPECT_EQ(QualityLimitationReason::kNone,
1213 statistics_proxy_->GetStats().quality_limitation_reason);
1214}
1215
1216TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001217 VideoAdaptationCounters cpu_counts;
1218 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001219
Evan Shrubsoledff79252020-04-16 11:34:32 +02001220 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001221 // Not limited for 3000 ms
1222 fake_clock_.AdvanceTimeMilliseconds(3000);
1223 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001224 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001225 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1226 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001227 fake_clock_.AdvanceTimeMilliseconds(2000);
1228 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001229 cpu_counts.resolution_adaptations = 0;
1230 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001231 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1232 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001233 fake_clock_.AdvanceTimeMilliseconds(1000);
1234 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001235 cpu_counts.resolution_adaptations = 1;
1236 quality_counts.resolution_adaptations = 0;
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
1241 auto quality_limitation_durations_ms =
1242 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1243
1244 EXPECT_EQ(3000,
1245 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1246 EXPECT_EQ(4000,
1247 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1248 EXPECT_EQ(
1249 1000,
1250 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1251 EXPECT_EQ(0,
1252 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1253}
1254
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001255TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1256 EXPECT_EQ(
1257 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1258}
1259
1260TEST_F(SendStatisticsProxyTest,
1261 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1262 VideoCodec codec;
1263 VideoBitrateAllocation allocation;
1264 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1265 EXPECT_EQ(
1266 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1267}
1268
1269TEST_F(SendStatisticsProxyTest,
1270 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1271 VideoCodec codec;
1272 codec.simulcastStream[0].active = true;
1273 codec.simulcastStream[1].active = true;
1274 codec.simulcastStream[2].active = true;
1275 VideoBitrateAllocation allocation;
1276 allocation.SetBitrate(0, 0, 100);
1277 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1278 EXPECT_EQ(
1279 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1280}
1281
1282TEST_F(SendStatisticsProxyTest,
1283 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1284 VideoCodec codec;
1285 codec.simulcastStream[0].active = true;
1286 codec.simulcastStream[1].active = true;
1287 codec.simulcastStream[2].active = true;
1288 VideoBitrateAllocation allocation;
1289 allocation.SetBitrate(0, 0, 100);
1290 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1291 allocation.SetBitrate(1, 0, 100);
1292 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1293 EXPECT_EQ(
1294 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1295}
1296
1297TEST_F(SendStatisticsProxyTest,
1298 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1299 VideoCodec codec;
1300 codec.simulcastStream[0].active = true;
1301 VideoBitrateAllocation allocation;
1302 allocation.SetBitrate(0, 0, 100);
1303 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1304 // Layer 0 got more bandwidth, but still only one layer on
1305 allocation.SetBitrate(0, 0, 200);
1306 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1307 EXPECT_EQ(
1308 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1309}
1310
1311TEST_F(SendStatisticsProxyTest,
1312 QualityLimitationResolutionChangesWithTogglingLayers) {
1313 VideoCodec codec;
1314 codec.simulcastStream[0].active = true;
1315 codec.simulcastStream[1].active = true;
1316 codec.simulcastStream[2].active = true;
1317 VideoBitrateAllocation allocation;
1318 allocation.SetBitrate(0, 0, 100);
1319 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1320 EXPECT_EQ(
1321 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1322 allocation.SetBitrate(1, 0, 300);
1323 allocation.SetBitrate(2, 0, 500);
1324 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1325 EXPECT_EQ(
1326 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1327 // Layer 2 off
1328 allocation.SetBitrate(2, 0, 0);
1329 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1330 EXPECT_EQ(
1331 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1332 // Layer 2 back on
1333 allocation.SetBitrate(2, 0, 500);
1334 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1335 EXPECT_EQ(
1336 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1337 allocation.SetBitrate(0, 0, 0);
1338 allocation.SetBitrate(1, 0, 0);
1339 allocation.SetBitrate(2, 0, 0);
1340 // All layers off
1341 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1342 EXPECT_EQ(
1343 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1344}
1345
1346TEST_F(SendStatisticsProxyTest,
1347 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1348 VideoCodec codec;
1349 // 3 layers
1350 codec.simulcastStream[0].active = true;
1351 codec.simulcastStream[1].active = true;
1352 codec.simulcastStream[2].active = true;
1353 VideoBitrateAllocation allocation;
1354 allocation.SetBitrate(0, 0, 500);
1355 allocation.SetBitrate(1, 0, 500);
1356 allocation.SetBitrate(2, 0, 500);
1357 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1358 EXPECT_EQ(
1359 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1360
1361 // Down to one layer now, triggered by a config change
1362 codec.numberOfSimulcastStreams = 1;
1363 codec.simulcastStream[1].active = false;
1364 codec.simulcastStream[2].active = false;
1365 allocation.SetBitrate(0, 0, 100);
1366 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1367 EXPECT_EQ(
1368 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1369
1370 // Up to 3 layers again.
1371 codec.numberOfSimulcastStreams = 3;
1372 codec.simulcastStream[1].active = true;
1373 codec.simulcastStream[2].active = true;
1374 allocation.SetBitrate(0, 0, 500);
1375 allocation.SetBitrate(1, 0, 500);
1376 allocation.SetBitrate(2, 0, 500);
1377 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1378 EXPECT_EQ(
1379 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1380}
1381
1382TEST_F(SendStatisticsProxyTest,
1383 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1384 VideoCodec codec;
1385 codec.simulcastStream[0].active = true;
1386 codec.spatialLayers[0].active = true;
1387 codec.spatialLayers[1].active = true;
1388 codec.spatialLayers[2].active = true;
1389 VideoBitrateAllocation allocation;
1390 allocation.SetBitrate(0, 0, 500);
1391 allocation.SetBitrate(1, 0, 500);
1392 allocation.SetBitrate(2, 0, 500);
1393 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1394 EXPECT_EQ(
1395 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1396
1397 // Down to one layer now, triggered by a config change
1398 codec.spatialLayers[1].active = false;
1399 codec.spatialLayers[2].active = false;
1400 allocation.SetBitrate(0, 0, 100);
1401 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1402 EXPECT_EQ(
1403 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1404
1405 // Up to 3 layers again.
1406 codec.spatialLayers[1].active = true;
1407 codec.spatialLayers[2].active = true;
1408 allocation.SetBitrate(0, 0, 500);
1409 allocation.SetBitrate(1, 0, 500);
1410 allocation.SetBitrate(2, 0, 500);
1411 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1412 EXPECT_EQ(
1413 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1414}
1415
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001416TEST_F(SendStatisticsProxyTest,
1417 QualityLimitationReasonsAreCorrectForContentType) {
1418 // Realtime case.
1419 // Configure two streams.
1420 VideoEncoderConfig config;
1421 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1422 config.number_of_streams = 2;
1423 VideoStream stream1;
1424 stream1.width = kWidth / 2;
1425 stream1.height = kHeight / 2;
1426 VideoStream stream2;
1427 stream2.width = kWidth;
1428 stream2.height = kHeight;
1429 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1430 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1431 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1432 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1433 QualityLimitationReason::kNone);
1434 // Bw disabled one layer.
1435 VideoCodec codec;
1436 codec.numberOfSimulcastStreams = 2;
1437 codec.simulcastStream[0].active = true;
1438 codec.simulcastStream[1].active = true;
1439 VideoBitrateAllocation allocation;
1440 // Some positive bitrate only on the first stream.
1441 allocation.SetBitrate(0, 0, 10000);
1442 allocation.SetBitrate(1, 0, 0);
1443 allocation.set_bw_limited(true);
1444 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1445 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1446 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1447 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1448 QualityLimitationReason::kBandwidth);
1449 // Bw enabled all layers.
1450 allocation.SetBitrate(1, 0, 10000);
1451 allocation.set_bw_limited(false);
1452 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1453 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1454 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1455 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1456 QualityLimitationReason::kNone);
1457
1458 // Screencast case
1459 // Configure two streams.
1460 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1461 config.number_of_streams = 2;
1462 stream1.width = kWidth;
1463 stream1.height = kHeight;
1464 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1465 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1466 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1467 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1468 QualityLimitationReason::kNone);
1469 // Bw disabled one layer.
1470 // Some positive bitrate only on the second stream.
1471 allocation.SetBitrate(0, 0, 10000);
1472 allocation.SetBitrate(1, 0, 0);
1473 allocation.set_bw_limited(true);
1474 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1475 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1476 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1477 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1478 QualityLimitationReason::kBandwidth);
1479 // Bw enabled all layers.
1480 allocation.SetBitrate(1, 0, 10000);
1481 allocation.set_bw_limited(false);
1482 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1483 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1484 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1485 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1486 QualityLimitationReason::kNone);
1487}
1488
asapersson59bac1a2016-01-07 23:36:00 -08001489TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001490 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001491 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1492
Pera48ddb72016-09-29 11:48:50 +02001493 // No switch, stats should not be updated.
1494 VideoEncoderConfig config;
1495 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001496 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001497 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001498
1499 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001500 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001501 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001502 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001503}
1504
asapersson320e45a2016-11-29 01:40:35 -08001505TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1506 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1507 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001508
asapersson320e45a2016-11-29 01:40:35 -08001509 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001510 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1511 EXPECT_METRIC_EQ(
1512 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1513 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1514 EXPECT_METRIC_EQ(
1515 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001516}
1517
1518TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001519 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001520 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001521 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1522 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1523 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001524 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001525
1526 // Not enough samples, stats should not be updated.
1527 for (int i = 0; i < kMinSamples - 1; ++i) {
1528 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001529 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001530 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1531 }
Åsa Persson0122e842017-10-16 12:19:23 +02001532 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001533 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1534 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001535
1536 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001537 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001538 for (int i = 0; i < kMinSamples; ++i) {
1539 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001540 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001541 encoded_image._encodedWidth = kWidth;
1542 encoded_image._encodedHeight = kHeight;
1543 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1544 encoded_image._encodedWidth = kWidth / 2;
1545 encoded_image._encodedHeight = kHeight / 2;
1546 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1547 }
1548
asapersson320e45a2016-11-29 01:40:35 -08001549 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001550 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1551 EXPECT_METRIC_EQ(
1552 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1553 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1554 EXPECT_METRIC_EQ(
1555 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001556}
1557
1558TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1559 const int kFps = 20;
1560 const int kMinPeriodicSamples = 6;
1561 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1562 for (int i = 0; i <= frames; ++i) {
1563 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1564 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1565 }
1566 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001567 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1568 EXPECT_METRIC_EQ(
1569 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001570}
1571
1572TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1573 EncodedImage encoded_image;
1574 const int kFps = 20;
1575 const int kMinPeriodicSamples = 6;
1576 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001577 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001578 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001579 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001580 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1581 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001582 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1583 }
1584 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001585 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1586 EXPECT_METRIC_EQ(
1587 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001588}
1589
1590TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1591 const int kFps = 20;
1592 const int kSuspendTimeMs = 10000;
1593 const int kMinPeriodicSamples = 6;
1594 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1595 for (int i = 0; i < frames; ++i) {
1596 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1597 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1598 }
1599 // Suspend.
1600 statistics_proxy_->OnSuspendChange(true);
1601 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1602
1603 for (int i = 0; i < frames; ++i) {
1604 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1605 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1606 }
1607 // Suspended time interval should not affect the framerate.
1608 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001609 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1610 EXPECT_METRIC_EQ(
1611 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001612}
1613
1614TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1615 EncodedImage encoded_image;
1616 const int kFps = 20;
1617 const int kSuspendTimeMs = 10000;
1618 const int kMinPeriodicSamples = 6;
1619 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001620 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001621 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001622 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001623 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1624 }
1625 // Suspend.
1626 statistics_proxy_->OnSuspendChange(true);
1627 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1628
Åsa Persson0122e842017-10-16 12:19:23 +02001629 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001630 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001631 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001632 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1633 }
1634 // Suspended time interval should not affect the framerate.
1635 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001636 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1637 EXPECT_METRIC_EQ(
1638 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001639}
1640
asaperssonf4e44af2017-04-19 02:01:06 -07001641TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001642 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1643 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001644
1645 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1646 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1647
1648 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001649 EXPECT_METRIC_EQ(
1650 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001651}
1652
1653TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001654 VideoAdaptationCounters cpu_counts;
1655 VideoAdaptationCounters quality_counts;
1656 cpu_counts.resolution_adaptations = 0;
1657 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001658
perkj803d97f2016-11-01 11:45:46 -07001659 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1660 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1661
Evan Shrubsoledff79252020-04-16 11:34:32 +02001662 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001663 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1664 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001665
1666 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1667 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1668
1669 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001670 EXPECT_METRIC_EQ(
1671 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1672 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001673 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1674}
1675
asapersson4374a092016-07-27 00:39:09 -07001676TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1677 const int64_t kTimeSec = 3;
1678 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1679 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001680 EXPECT_METRIC_EQ(
1681 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1682 EXPECT_METRIC_EQ(
1683 1,
1684 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001685}
1686
1687TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1688 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1689 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001690 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001691}
1692
asapersson66d4b372016-12-19 06:50:53 -08001693TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1694 // First RTP packet sent.
1695 UpdateDataCounters(kFirstSsrc);
1696
1697 // Min runtime has passed.
1698 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1699 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001700 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1701 EXPECT_METRIC_EQ(1,
1702 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001703}
1704
1705TEST_F(SendStatisticsProxyTest,
1706 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1707 // First RTP packet sent.
1708 UpdateDataCounters(kFirstSsrc);
1709
1710 // Min runtime has not passed.
1711 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1712 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001713 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1714 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001715}
1716
1717TEST_F(SendStatisticsProxyTest,
1718 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1719 // First RTP packet not sent.
1720 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1721 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001722 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001723}
1724
1725TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1726 // First RTP packet sent and min runtime passed.
1727 UpdateDataCounters(kFirstSsrc);
1728
1729 // No change. Video: 10000 ms, paused: 0 ms (0%).
1730 statistics_proxy_->OnSetEncoderTargetRate(50000);
1731 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1732 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1733
1734 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001735 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1736 EXPECT_METRIC_EQ(1,
1737 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1738 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1739 EXPECT_METRIC_EQ(1,
1740 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001741}
1742
1743TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1744 // First RTP packet sent and min runtime passed.
1745 UpdateDataCounters(kFirstSsrc);
1746
1747 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1748 statistics_proxy_->OnSetEncoderTargetRate(50000);
1749 fake_clock_.AdvanceTimeMilliseconds(7000);
1750 statistics_proxy_->OnSetEncoderTargetRate(0);
1751 fake_clock_.AdvanceTimeMilliseconds(3000);
1752 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1753
1754 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001755 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1756 EXPECT_METRIC_EQ(1,
1757 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1758 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1759 EXPECT_METRIC_EQ(1,
1760 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001761}
1762
1763TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1764 // First RTP packet sent.
1765 UpdateDataCounters(kFirstSsrc);
1766
1767 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1768 statistics_proxy_->OnSetEncoderTargetRate(0);
1769 fake_clock_.AdvanceTimeMilliseconds(1000);
1770 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1771 fake_clock_.AdvanceTimeMilliseconds(7000);
1772 statistics_proxy_->OnSetEncoderTargetRate(60000);
1773 fake_clock_.AdvanceTimeMilliseconds(3000);
1774 statistics_proxy_->OnSetEncoderTargetRate(0);
1775 fake_clock_.AdvanceTimeMilliseconds(250);
1776 statistics_proxy_->OnSetEncoderTargetRate(0);
1777 fake_clock_.AdvanceTimeMilliseconds(750);
1778 statistics_proxy_->OnSetEncoderTargetRate(60000);
1779 fake_clock_.AdvanceTimeMilliseconds(5000);
1780 statistics_proxy_->OnSetEncoderTargetRate(50000);
1781 fake_clock_.AdvanceTimeMilliseconds(4000);
1782 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1783
1784 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001785 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1786 EXPECT_METRIC_EQ(1,
1787 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1788 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1789 EXPECT_METRIC_EQ(1,
1790 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001791}
1792
1793TEST_F(SendStatisticsProxyTest,
1794 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1795 // First RTP packet sent.
1796 UpdateDataCounters(kFirstSsrc);
1797 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1798
1799 // Min runtime has not passed.
1800 statistics_proxy_->OnSetEncoderTargetRate(50000);
1801 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1802 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1803
1804 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001805 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001806}
1807
asapersson118ef002016-03-31 00:00:19 -07001808TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001809 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001810 CodecSpecificInfo codec_info;
1811 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001812
perkj803d97f2016-11-01 11:45:46 -07001813 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001814 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001815 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001816 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001817 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001818 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001819 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001820 }
1821 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001822 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1823 EXPECT_METRIC_EQ(
1824 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1825 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1826 EXPECT_METRIC_EQ(
1827 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001828}
1829
1830TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1831 VideoSendStream::Config config(nullptr);
1832 config.rtp.ssrcs.push_back(kFirstSsrc);
1833 statistics_proxy_.reset(new SendStatisticsProxy(
1834 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1835
asapersson118ef002016-03-31 00:00:19 -07001836 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001837 CodecSpecificInfo codec_info;
1838 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001839
perkj803d97f2016-11-01 11:45:46 -07001840 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001841 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001842 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001843 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001844 }
1845 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001846 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1847 EXPECT_METRIC_EQ(1,
1848 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001849}
1850
asapersson5265fed2016-04-18 02:58:47 -07001851TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001852 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001853 CodecSpecificInfo codec_info;
1854 codec_info.codecType = kVideoCodecVP9;
1855 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001856
perkj803d97f2016-11-01 11:45:46 -07001857 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001858 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001859 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001860 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001861 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001862 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001863 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001864 }
1865 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001866 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1867 EXPECT_METRIC_EQ(
1868 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1869 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1870 EXPECT_METRIC_EQ(
1871 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001872}
1873
1874TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1875 VideoSendStream::Config config(nullptr);
1876 config.rtp.ssrcs.push_back(kFirstSsrc);
1877 statistics_proxy_.reset(new SendStatisticsProxy(
1878 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1879
asapersson5265fed2016-04-18 02:58:47 -07001880 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001881 CodecSpecificInfo codec_info;
1882 codec_info.codecType = kVideoCodecVP9;
1883 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001884
perkj803d97f2016-11-01 11:45:46 -07001885 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001886 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001887 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001888 }
1889 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001890 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1891 EXPECT_METRIC_EQ(1,
1892 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001893}
1894
asapersson827cab32016-11-02 09:08:47 -07001895TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1896 EncodedImage encoded_image;
1897 CodecSpecificInfo codec_info;
1898 codec_info.codecType = kVideoCodecH264;
1899
1900 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001901 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001902 encoded_image.qp_ = kQpIdx0;
1903 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001904 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001905 encoded_image.qp_ = kQpIdx1;
1906 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001907 }
1908 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001909 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1910 EXPECT_METRIC_EQ(
1911 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1912 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1913 EXPECT_METRIC_EQ(
1914 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001915}
1916
asapersson4ee70462016-10-31 04:05:12 -07001917TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001918 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1919 // Configure one stream.
1920 VideoEncoderConfig config;
1921 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1922 VideoStream stream1;
1923 stream1.width = kWidth;
1924 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001925 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001926
1927 const int64_t kMaxEncodedFrameWindowMs = 800;
1928 const int kFps = 20;
1929 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1930 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1931 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1932
1933 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001934 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001935 encoded_image._encodedWidth = kWidth;
1936 encoded_image._encodedHeight = kHeight;
1937 for (int i = 0; i < kMinSamples; ++i) {
1938 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001939 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1940 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001941 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001942 }
asapersson4ee70462016-10-31 04:05:12 -07001943
1944 // Histograms are updated when the statistics_proxy_ is deleted.
1945 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001946 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1947 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1948 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1949 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001950}
1951
1952TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001953 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1954 // Configure two streams.
1955 VideoEncoderConfig config;
1956 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1957 VideoStream stream1;
1958 stream1.width = kWidth / 2;
1959 stream1.height = kHeight / 2;
1960 VideoStream stream2;
1961 stream2.width = kWidth;
1962 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001963 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001964
1965 const int64_t kMaxEncodedFrameWindowMs = 800;
1966 const int kFps = 20;
1967 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1968 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1969 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1970
1971 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001972 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001973 for (int i = 0; i < kMinSamples; ++i) {
1974 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001975 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1976 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001977 encoded_image._encodedWidth = kWidth;
1978 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001979 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001980 encoded_image._encodedWidth = kWidth / 2;
1981 encoded_image._encodedHeight = kHeight / 2;
1982 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1983 }
asapersson4ee70462016-10-31 04:05:12 -07001984
1985 // Histograms are updated when the statistics_proxy_ is deleted.
1986 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001987 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1988 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1989 EXPECT_METRIC_EQ(
1990 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
1991 0));
asapersson4ee70462016-10-31 04:05:12 -07001992 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01001993 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1994 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001995}
1996
1997TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001998 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1999 // Configure two streams.
2000 VideoEncoderConfig config;
2001 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2002 VideoStream stream1;
2003 stream1.width = kWidth / 2;
2004 stream1.height = kHeight / 2;
2005 VideoStream stream2;
2006 stream2.width = kWidth;
2007 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002008 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002009
2010 const int64_t kMaxEncodedFrameWindowMs = 800;
2011 const int kFps = 20;
2012 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2013 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2014 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2015
2016 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002017 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002018 encoded_image._encodedWidth = kWidth / 2;
2019 encoded_image._encodedHeight = kHeight / 2;
2020 for (int i = 0; i < kMinSamples; ++i) {
2021 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002022 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2023 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002024 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002025 }
asapersson4ee70462016-10-31 04:05:12 -07002026
2027 // Histograms are updated when the statistics_proxy_ is deleted.
2028 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002029 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2030 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2031 EXPECT_METRIC_EQ(
2032 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2033 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002034 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002035 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2036 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2037 EXPECT_METRIC_EQ(
2038 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2039 1));
asapersson4ee70462016-10-31 04:05:12 -07002040}
2041
2042TEST_F(SendStatisticsProxyTest,
2043 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002044 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2045 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002046 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002047 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002048 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002049 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002050
2051 // Histograms are updated when the statistics_proxy_ is deleted.
2052 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002053 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002054 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002055 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2056 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002057}
2058
2059TEST_F(SendStatisticsProxyTest,
2060 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002061 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002062 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002063 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002064 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002065 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002066
2067 // Histograms are updated when the statistics_proxy_ is deleted.
2068 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002069 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002070 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002071 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2072 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002073 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002074 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2075 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002076}
2077
2078TEST_F(SendStatisticsProxyTest,
2079 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2080 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002081 VideoAdaptationCounters cpu_counts;
2082 VideoAdaptationCounters quality_counts;
2083 quality_counts.resolution_adaptations = kDownscales;
2084 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002085 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2086 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002087 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002088 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002089 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002090 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002091 // Histograms are updated when the statistics_proxy_ is deleted.
2092 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002093 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002094 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002095 EXPECT_METRIC_EQ(
2096 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2097 100));
asapersson4ee70462016-10-31 04:05:12 -07002098 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002099 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2100 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2101 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002102 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2103 kDownscales));
2104}
2105
2106TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2107 // Initially false.
2108 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002109
Åsa Perssonaa329e72017-12-15 15:54:44 +01002110 // Configure two streams.
2111 VideoEncoderConfig config;
2112 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002113 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002114 VideoStream stream1;
2115 stream1.width = kWidth / 2;
2116 stream1.height = kHeight / 2;
2117 VideoStream stream2;
2118 stream2.width = kWidth;
2119 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002120 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002121
Åsa Perssonaa329e72017-12-15 15:54:44 +01002122 // One stream encoded.
2123 EncodedImage encoded_image;
2124 encoded_image._encodedWidth = kWidth / 2;
2125 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002126
2127 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002128 VideoAdaptationCounters cpu_counts;
2129 VideoAdaptationCounters quality_counts;
2130 quality_counts.resolution_adaptations = 1;
2131 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2132 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002133 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2134 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002135 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2136 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002137
2138 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002139 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002140 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2141 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002142 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2143 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2144
2145 // Bw disabled one layer.
2146 VideoCodec codec;
2147 codec.numberOfSimulcastStreams = 2;
2148 codec.simulcastStream[0].active = true;
2149 codec.simulcastStream[1].active = true;
2150 VideoBitrateAllocation allocation;
2151 // Some positive bitrate only on the second stream.
2152 allocation.SetBitrate(1, 0, 10000);
2153 allocation.set_bw_limited(true);
2154 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2155 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002156
2157 // Revert for the next test.
2158 allocation.set_bw_limited(false);
2159 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2160 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2161
2162 // Internal encoder scaler reduced resolution.
2163 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2164 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002165}
2166
asapersson66d4b372016-12-19 06:50:53 -08002167TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2168 // Initially zero.
2169 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2170
2171 const int kBitrate = 100000;
2172 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2173 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2174
2175 statistics_proxy_->OnSetEncoderTargetRate(0);
2176 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2177}
2178
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002179TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002180 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002181 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2182 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002183 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002184 // From RtcpStatisticsCallback.
2185 RtcpStatistics rtcp_stats;
2186 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002187 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002188
2189 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002190 uint32_t total = 0;
2191 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002192 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002193 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002194
2195 // From FrameCountObserver.
2196 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002197 FrameCounts frame_counts;
2198 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002199 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002200
2201 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2202 EXPECT_TRUE(stats.substreams.empty());
2203}
2204
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002205TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2206 static const int kEncodedWidth = 123;
2207 static const int kEncodedHeight = 81;
2208 EncodedImage encoded_image;
2209 encoded_image._encodedWidth = kEncodedWidth;
2210 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002211 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002212
kjellander02b3d272016-04-20 05:05:54 -07002213 CodecSpecificInfo codec_info;
2214 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002215
kjellander02b3d272016-04-20 05:05:54 -07002216 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002217 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002218 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002219
2220 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002221 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2222 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2223 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2224 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002225
2226 // Forward almost to timeout, this should not have removed stats.
2227 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2228 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002229 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2230 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002231
2232 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2233 // resolution still times out (no global timeout for all stats).
2234 RtcpStatistics rtcp_statistics;
2235 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2236 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2237
2238 // Report stats for second SSRC to make sure it's not outdated along with the
2239 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002240 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002241
2242 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2243 // reported, but substream 1 should.
2244 fake_clock_.AdvanceTimeMilliseconds(1);
2245 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002246 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2247 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2248 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2249 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002250}
2251
Peter Boström20f3f942015-05-15 11:33:39 +02002252TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2253 static const int kEncodedWidth = 123;
2254 static const int kEncodedHeight = 81;
2255 EncodedImage encoded_image;
2256 encoded_image._encodedWidth = kEncodedWidth;
2257 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002258 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002259
kjellander02b3d272016-04-20 05:05:54 -07002260 CodecSpecificInfo codec_info;
2261 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002262
kjellander02b3d272016-04-20 05:05:54 -07002263 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002264 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002265 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002266
2267 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2268 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2269 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2270 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2271 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2272 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2273}
2274
2275TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002276 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002277 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2278 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2279 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2280
2281 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2282
2283 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002284 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002285 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002286 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002287 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2288 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2289 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2290}
2291
sprang07fb9be2016-02-24 07:55:00 -08002292TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2293 RtcpPacketTypeCounterObserver* proxy =
2294 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2295 RtcpPacketTypeCounter counters;
2296 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2297 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2298 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2299
2300 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2301
2302 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2303 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2304 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2305 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2306 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2307
2308 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2309 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2310
2311 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002312 VideoEncoderConfig config;
2313 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002314 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002315
Ying Wangef3998f2019-12-09 13:06:53 +01002316 EXPECT_METRIC_EQ(
2317 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2318 EXPECT_METRIC_EQ(
2319 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2320 EXPECT_METRIC_EQ(
2321 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2322 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2323 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002324
2325 const int kRate = 60 * 2; // Packets per minute with two streams.
2326
Ying Wangef3998f2019-12-09 13:06:53 +01002327 EXPECT_METRIC_EQ(
2328 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2329 1 * kRate));
2330 EXPECT_METRIC_EQ(
2331 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2332 2 * kRate));
2333 EXPECT_METRIC_EQ(
2334 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2335 3 * kRate));
2336 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002337 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2338 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002339
2340 // New start time but same counter values.
2341 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2342 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2343
2344 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2345
2346 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2347 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2348 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2349 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2350 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2351
2352 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2353 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2354
2355 SetUp(); // Reset stats proxy also causes histograms to be reported.
2356
Ying Wangef3998f2019-12-09 13:06:53 +01002357 EXPECT_METRIC_EQ(
2358 1, metrics::NumSamples(
2359 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2360 EXPECT_METRIC_EQ(1,
2361 metrics::NumSamples(
2362 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2363 EXPECT_METRIC_EQ(1,
2364 metrics::NumSamples(
2365 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2366 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002367 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002368 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2369
Ying Wangef3998f2019-12-09 13:06:53 +01002370 EXPECT_METRIC_EQ(
2371 1,
2372 metrics::NumEvents(
2373 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2374 EXPECT_METRIC_EQ(
2375 1,
2376 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2377 2 * kRate));
2378 EXPECT_METRIC_EQ(
2379 1,
2380 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2381 3 * kRate));
2382 EXPECT_METRIC_EQ(
2383 1, metrics::NumEvents(
2384 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2385 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002386}
2387
Henrik Boströmf45ca372020-03-24 13:30:50 +01002388TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2389 StreamDataCountersCallback* proxy =
2390 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2391 StreamDataCounters counters;
2392 proxy->DataCountersUpdated(counters, kFirstSsrc);
2393 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2394
2395 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2396 VideoSendStream::StreamStats::StreamType::kRtx);
2397 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2398 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2399 VideoSendStream::StreamStats::StreamType::kRtx);
2400 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2401}
2402
asaperssona6a699a2016-11-25 03:52:46 -08002403TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2404 statistics_proxy_.reset(
2405 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2406 VideoEncoderConfig::ContentType::kRealtimeVideo));
2407
2408 StreamDataCountersCallback* proxy =
2409 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2410 StreamDataCounters counters;
2411 proxy->DataCountersUpdated(counters, kFirstSsrc);
2412 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2413
Henrik Boströmf45ca372020-03-24 13:30:50 +01002414 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2415 VideoSendStream::StreamStats::StreamType::kFlexfec);
2416 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2417 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2418 VideoSendStream::StreamStats::StreamType::kFlexfec);
2419 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002420}
2421
2422TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2423 statistics_proxy_.reset(
2424 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2425 VideoEncoderConfig::ContentType::kRealtimeVideo));
2426
2427 StreamDataCountersCallback* proxy =
2428 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002429 StreamDataCounters counters;
2430 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002431
asapersson93e1e232017-02-06 05:18:35 -08002432 const int kMinRequiredPeriodSamples = 8;
2433 const int kPeriodIntervalMs = 2000;
2434 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2435 counters.transmitted.packets += 20;
2436 counters.transmitted.header_bytes += 500;
2437 counters.transmitted.padding_bytes += 1000;
2438 counters.transmitted.payload_bytes += 2000;
2439 counters.retransmitted.packets += 2;
2440 counters.retransmitted.header_bytes += 25;
2441 counters.retransmitted.padding_bytes += 100;
2442 counters.retransmitted.payload_bytes += 250;
2443 counters.fec = counters.retransmitted;
2444 rtx_counters.transmitted = counters.transmitted;
2445 // Advance one interval and update counters.
2446 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2447 proxy->DataCountersUpdated(counters, kFirstSsrc);
2448 proxy->DataCountersUpdated(counters, kSecondSsrc);
2449 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2450 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2451 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2452 }
asaperssona6a699a2016-11-25 03:52:46 -08002453
asaperssona6a699a2016-11-25 03:52:46 -08002454 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002455 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002456 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2457 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002458 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002459 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2460 EXPECT_METRIC_EQ(1,
2461 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002462 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002463 EXPECT_METRIC_EQ(1,
2464 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2465 EXPECT_METRIC_EQ(
2466 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002467 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002468 EXPECT_METRIC_EQ(
2469 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2470 EXPECT_METRIC_EQ(
2471 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002472 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002473 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2474 EXPECT_METRIC_EQ(1,
2475 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002476 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002477 EXPECT_METRIC_EQ(
2478 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2479 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002480 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002481}
2482
Erik Språng22c2b482016-03-01 09:40:42 +01002483TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2484 StreamDataCountersCallback* proxy =
2485 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2486 StreamDataCounters counters;
2487 StreamDataCounters rtx_counters;
2488 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002489
asapersson93e1e232017-02-06 05:18:35 -08002490 const int kMinRequiredPeriodSamples = 8;
2491 const int kPeriodIntervalMs = 2000;
2492 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2493 counters.transmitted.packets += 20;
2494 counters.transmitted.header_bytes += 500;
2495 counters.transmitted.padding_bytes += 1000;
2496 counters.transmitted.payload_bytes += 2000;
2497 counters.retransmitted.packets += 2;
2498 counters.retransmitted.header_bytes += 25;
2499 counters.retransmitted.padding_bytes += 100;
2500 counters.retransmitted.payload_bytes += 250;
2501 counters.fec = counters.retransmitted;
2502 rtx_counters.transmitted = counters.transmitted;
2503 // Advance one interval and update counters.
2504 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2505 proxy->DataCountersUpdated(counters, kFirstSsrc);
2506 proxy->DataCountersUpdated(counters, kSecondSsrc);
2507 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2508 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2509 }
Erik Språng22c2b482016-03-01 09:40:42 +01002510
2511 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002512 VideoEncoderConfig config;
2513 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002514 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002515
asapersson93e1e232017-02-06 05:18:35 -08002516 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002517 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2518 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002519 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002520 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2521 EXPECT_METRIC_EQ(1,
2522 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002523 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002524 EXPECT_METRIC_EQ(1,
2525 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2526 EXPECT_METRIC_EQ(
2527 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002528 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002529 EXPECT_METRIC_EQ(
2530 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2531 EXPECT_METRIC_EQ(
2532 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002533 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002534 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2535 EXPECT_METRIC_EQ(1,
2536 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002537 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002538 EXPECT_METRIC_EQ(
2539 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2540 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002541 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002542
asapersson93e1e232017-02-06 05:18:35 -08002543 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002544 // Double counter values, this should result in the same counts as before but
2545 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002546 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2547 counters.transmitted.packets += 20;
2548 counters.transmitted.header_bytes += 500;
2549 counters.transmitted.padding_bytes += 1000;
2550 counters.transmitted.payload_bytes += 2000;
2551 counters.retransmitted.packets += 2;
2552 counters.retransmitted.header_bytes += 25;
2553 counters.retransmitted.padding_bytes += 100;
2554 counters.retransmitted.payload_bytes += 250;
2555 counters.fec = counters.retransmitted;
2556 rtx_counters.transmitted = counters.transmitted;
2557 // Advance one interval and update counters.
2558 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2559 proxy->DataCountersUpdated(counters, kFirstSsrc);
2560 proxy->DataCountersUpdated(counters, kSecondSsrc);
2561 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2562 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2563 }
Erik Språng22c2b482016-03-01 09:40:42 +01002564
asapersson93e1e232017-02-06 05:18:35 -08002565 // Reset stats proxy also causes histograms to be reported.
2566 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002567
asapersson93e1e232017-02-06 05:18:35 -08002568 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002569 EXPECT_METRIC_EQ(
2570 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2571 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002572 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2573 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002574 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002575 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002576 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2577 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002578 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002579 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2580 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2581 EXPECT_METRIC_EQ(
2582 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2583 12));
asapersson93e1e232017-02-06 05:18:35 -08002584 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002585 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2586 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2587 EXPECT_METRIC_EQ(
2588 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2589 16));
asapersson93e1e232017-02-06 05:18:35 -08002590 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002591 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002592 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002593 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2594 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002595 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002596 EXPECT_METRIC_EQ(
2597 1, metrics::NumSamples(
2598 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2599 EXPECT_METRIC_EQ(
2600 1, metrics::NumEvents(
2601 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002602}
Erik Språng22c2b482016-03-01 09:40:42 +01002603
asapersson93e1e232017-02-06 05:18:35 -08002604TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2605 StreamDataCountersCallback* proxy =
2606 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2607 StreamDataCounters counters;
2608 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002609
asapersson93e1e232017-02-06 05:18:35 -08002610 const int kMinRequiredPeriodSamples = 8;
2611 const int kPeriodIntervalMs = 2000;
2612 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2613 counters.transmitted.packets += 20;
2614 counters.transmitted.header_bytes += 500;
2615 counters.transmitted.payload_bytes += 2000;
2616 counters.fec = counters.retransmitted;
2617 // Advance one interval and update counters.
2618 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2619 proxy->DataCountersUpdated(counters, kFirstSsrc);
2620 }
2621
2622 // RTX enabled. No data sent over RTX.
2623 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002624 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2625 EXPECT_METRIC_EQ(1,
2626 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002627}
2628
2629TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2630 VideoSendStream::Config config(nullptr);
2631 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2632 statistics_proxy_.reset(new SendStatisticsProxy(
2633 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2634
2635 StreamDataCountersCallback* proxy =
2636 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2637 StreamDataCounters counters;
2638
2639 const int kMinRequiredPeriodSamples = 8;
2640 const int kPeriodIntervalMs = 2000;
2641 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2642 counters.transmitted.packets += 20;
2643 counters.transmitted.header_bytes += 500;
2644 counters.transmitted.payload_bytes += 2000;
2645 counters.fec = counters.retransmitted;
2646 // Advance one interval and update counters.
2647 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2648 proxy->DataCountersUpdated(counters, kFirstSsrc);
2649 }
2650
2651 // RTX not enabled.
2652 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002653 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002654}
2655
2656TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2657 StreamDataCountersCallback* proxy =
2658 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2659 StreamDataCounters counters;
2660 StreamDataCounters rtx_counters;
2661
2662 const int kMinRequiredPeriodSamples = 8;
2663 const int kPeriodIntervalMs = 2000;
2664 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2665 counters.transmitted.packets += 20;
2666 counters.transmitted.header_bytes += 500;
2667 counters.transmitted.payload_bytes += 2000;
2668 // Advance one interval and update counters.
2669 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2670 proxy->DataCountersUpdated(counters, kFirstSsrc);
2671 }
2672
2673 // FEC enabled. No FEC data sent.
2674 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002675 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2676 EXPECT_METRIC_EQ(1,
2677 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002678}
2679
2680TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2681 VideoSendStream::Config config(nullptr);
2682 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2683 statistics_proxy_.reset(new SendStatisticsProxy(
2684 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2685
2686 StreamDataCountersCallback* proxy =
2687 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2688 StreamDataCounters counters;
2689
2690 const int kMinRequiredPeriodSamples = 8;
2691 const int kPeriodIntervalMs = 2000;
2692 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2693 counters.transmitted.packets += 20;
2694 counters.transmitted.header_bytes += 500;
2695 counters.transmitted.payload_bytes += 2000;
2696 counters.fec = counters.retransmitted;
2697 // Advance one interval and update counters.
2698 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2699 proxy->DataCountersUpdated(counters, kFirstSsrc);
2700 }
2701
2702 // FEC not enabled.
2703 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002704 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002705}
2706
asapersson8d75ac72017-09-15 06:41:15 -07002707TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002708 const std::string kName = "encoderName";
2709 statistics_proxy_->OnEncoderImplementationChanged(kName);
2710 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002711}
2712
Sergey Silkinbb081a62018-09-04 18:34:22 +02002713TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2714 static const int kEncodedWidth = 123;
2715 static const int kEncodedHeight = 81;
2716 EncodedImage encoded_image;
2717 encoded_image._encodedWidth = kEncodedWidth;
2718 encoded_image._encodedHeight = kEncodedHeight;
2719 encoded_image.SetSpatialIndex(0);
2720
2721 CodecSpecificInfo codec_info;
2722 codec_info.codecType = kVideoCodecVP9;
2723
2724 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002725 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002726 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2727 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2728 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2729 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2730
2731 // Top layer updates resolution.
2732 encoded_image._encodedWidth = kEncodedWidth * 2;
2733 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002734 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002735 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2736 stats = statistics_proxy_->GetStats();
2737 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2738 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2739
2740 // Low layer of next frame doesn't update resolution.
2741 encoded_image._encodedWidth = kEncodedWidth;
2742 encoded_image._encodedHeight = kEncodedHeight;
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 stats = statistics_proxy_->GetStats();
2746 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2747 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2748}
2749
asapersson8d75ac72017-09-15 06:41:15 -07002750class ForcedFallbackTest : public SendStatisticsProxyTest {
2751 public:
2752 explicit ForcedFallbackTest(const std::string& field_trials)
2753 : SendStatisticsProxyTest(field_trials) {
2754 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002755 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002756 encoded_image_._encodedWidth = kWidth;
2757 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002758 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002759 }
2760
2761 ~ForcedFallbackTest() override {}
2762
2763 protected:
2764 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002765 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2766
asapersson8d75ac72017-09-15 06:41:15 -07002767 // First frame is not updating stats, insert initial frame.
2768 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2769 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2770 }
2771 for (int i = 0; i < num_frames; ++i) {
2772 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2773 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2774 }
2775 // Add frame to include last time interval.
2776 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2777 }
2778
2779 EncodedImage encoded_image_;
2780 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002781 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002782 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2783 const int kFrameIntervalMs = 1000;
2784 const int kMinFrames = 20; // Min run time 20 sec.
2785};
2786
2787class ForcedFallbackDisabled : public ForcedFallbackTest {
2788 public:
2789 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002790 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2791 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002792};
2793
2794class ForcedFallbackEnabled : public ForcedFallbackTest {
2795 public:
2796 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002797 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2798 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002799};
2800
2801TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2802 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2803 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002804 EXPECT_METRIC_EQ(0,
2805 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2806 EXPECT_METRIC_EQ(
2807 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002808}
2809
2810TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2811 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002812 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002813 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002814 EXPECT_METRIC_EQ(1,
2815 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2816 EXPECT_METRIC_EQ(
2817 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2818 EXPECT_METRIC_EQ(
2819 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2820 EXPECT_METRIC_EQ(
2821 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002822}
2823
2824TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2825 codec_info_.codecType = kVideoCodecVP9;
2826 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2827 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002828 EXPECT_METRIC_EQ(0,
2829 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2830 EXPECT_METRIC_EQ(
2831 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002832}
2833
2834TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2835 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2836 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2837 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002838 EXPECT_METRIC_EQ(0,
2839 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2840 EXPECT_METRIC_EQ(
2841 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002842}
2843
2844TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002845 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002846 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2847 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002848 EXPECT_METRIC_EQ(0,
2849 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2850 EXPECT_METRIC_EQ(
2851 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002852}
2853
2854TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2855 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2856 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002857 EXPECT_METRIC_EQ(0,
2858 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2859 EXPECT_METRIC_EQ(
2860 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002861}
2862
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002863TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2864 InsertEncodedFrames(1, kFrameIntervalMs);
2865 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2866}
2867
2868TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2869 InsertEncodedFrames(1, kFrameIntervalMs);
2870 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2871}
2872
2873TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002874 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002875 InsertEncodedFrames(1, kFrameIntervalMs);
2876 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2877}
2878
2879TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2880 encoded_image_._encodedWidth = kWidth + 1;
2881 InsertEncodedFrames(1, kFrameIntervalMs);
2882 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2883}
2884
2885TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002886 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002887 InsertEncodedFrames(1, kFrameIntervalMs);
2888 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2889}
2890
2891TEST_F(ForcedFallbackDisabled,
2892 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2893 encoded_image_._encodedWidth = kWidth + 1;
2894 statistics_proxy_->OnMinPixelLimitReached();
2895 InsertEncodedFrames(1, kFrameIntervalMs);
2896 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2897}
2898
asapersson8d75ac72017-09-15 06:41:15 -07002899TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2900 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002901 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002902 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002903 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002904 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002905 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002906 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002907
2908 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002909 EXPECT_METRIC_EQ(1,
2910 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2911 EXPECT_METRIC_EQ(
2912 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2913 EXPECT_METRIC_EQ(
2914 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2915 EXPECT_METRIC_EQ(
2916 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002917}
2918
2919TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2920 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2921 const int kMaxFrameDiffMs = 2000;
2922
2923 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2924 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002925 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002926 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002927 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002928 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002929 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002930 InsertEncodedFrames(20, 1000);
2931 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2932 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002933 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002934 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002935 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002936 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002937 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002938 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002939 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002940
2941 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002942 EXPECT_METRIC_EQ(1,
2943 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2944 EXPECT_METRIC_EQ(
2945 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2946 EXPECT_METRIC_EQ(
2947 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2948 EXPECT_METRIC_EQ(
2949 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002950}
2951
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002952TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2953 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002954 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002955 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2956
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002957 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002958 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002959 EXPECT_METRIC_EQ(0,
2960 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2961 EXPECT_METRIC_EQ(
2962 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002963}
2964
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002965TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2966 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002967 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002968 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2969
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002970 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002971 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002972 EXPECT_METRIC_EQ(1,
2973 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2974 EXPECT_METRIC_EQ(
2975 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002976}
2977
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002978} // namespace webrtc