blob: ab5b491069559b4dab61e252b891d077a21a6b53 [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) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000129 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
130 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000131 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000132 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000133
134 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000135 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000136 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000137 it != one.substreams.end(); ++it) {
138 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
139 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000140 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000141 const VideoSendStream::StreamStats& a = it->second;
142 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000143
Henrik Boströmf45ca372020-03-24 13:30:50 +0100144 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000145 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
146 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000147 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000148 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
149 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000150
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000151 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
152 b.rtp_stats.transmitted.payload_bytes);
153 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
154 b.rtp_stats.transmitted.header_bytes);
155 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
156 b.rtp_stats.transmitted.padding_bytes);
157 EXPECT_EQ(a.rtp_stats.transmitted.packets,
158 b.rtp_stats.transmitted.packets);
159 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
160 b.rtp_stats.retransmitted.packets);
161 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000162
163 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700164 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
165 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
166 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000167 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
168 }
169 }
170
asapersson8d75ac72017-09-15 06:41:15 -0700171 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000172 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800173 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000174 VideoSendStream::Config config_;
175 int avg_delay_ms_;
176 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000177 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000178 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
179 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000180};
181
182TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
183 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700184 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000185 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000186
187 // Add statistics with some arbitrary, but unique, numbers.
188 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700189 ssrc_stats.rtcp_stats.packets_lost = offset;
190 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000191 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
192 ssrc_stats.rtcp_stats.jitter = offset + 3;
193 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
194 }
asapersson35151f32016-05-02 23:44:01 -0700195 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000196 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000197
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000198 // Add statistics with some arbitrary, but unique, numbers.
199 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700200 ssrc_stats.rtcp_stats.packets_lost = offset;
201 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000202 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
203 ssrc_stats.rtcp_stats.jitter = offset + 3;
204 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
205 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000206 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000207 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000208}
209
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000210TEST_F(SendStatisticsProxyTest, Suspended) {
211 // Verify that the value is false by default.
212 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
213
214 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200215 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000216 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
217
218 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200219 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000220 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
221}
222
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000223TEST_F(SendStatisticsProxyTest, FrameCounts) {
224 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700225 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000226 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000227 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
228 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000229 FrameCounts frame_counts;
230 frame_counts.key_frames = offset;
231 frame_counts.delta_frames = offset + 1;
232 stats.frame_counts = frame_counts;
233 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000234 }
asapersson35151f32016-05-02 23:44:01 -0700235 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000236 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000237 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
238 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000239 FrameCounts frame_counts;
240 frame_counts.key_frames = offset;
241 frame_counts.delta_frames = offset + 1;
242 stats.frame_counts = frame_counts;
243 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000244 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000245
246 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000247 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000248}
249
250TEST_F(SendStatisticsProxyTest, DataCounters) {
251 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700252 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000253 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
254 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000255 size_t offset = ssrc * sizeof(StreamDataCounters);
256 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000257 counters.transmitted.payload_bytes = offset;
258 counters.transmitted.header_bytes = offset + 1;
259 counters.fec.packets = offset_uint32 + 2;
260 counters.transmitted.padding_bytes = offset + 3;
261 counters.retransmitted.packets = offset_uint32 + 4;
262 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000263 callback->DataCountersUpdated(counters, ssrc);
264 }
asapersson35151f32016-05-02 23:44:01 -0700265 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000266 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
267 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000268 size_t offset = ssrc * sizeof(StreamDataCounters);
269 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000270 counters.transmitted.payload_bytes = offset;
271 counters.transmitted.header_bytes = offset + 1;
272 counters.fec.packets = offset_uint32 + 2;
273 counters.transmitted.padding_bytes = offset + 3;
274 counters.retransmitted.packets = offset_uint32 + 4;
275 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000276 callback->DataCountersUpdated(counters, ssrc);
277 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000278
279 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000280 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000281}
282
283TEST_F(SendStatisticsProxyTest, Bitrate) {
284 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700285 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700286 uint32_t total;
287 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000288 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700289 total = ssrc;
290 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000291 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700292 expected_.substreams[ssrc].total_bitrate_bps = total;
293 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000294 }
asapersson35151f32016-05-02 23:44:01 -0700295 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700296 uint32_t total;
297 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000298 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700299 total = ssrc;
300 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000301 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700302 expected_.substreams[ssrc].total_bitrate_bps = total;
303 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000304 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000305
306 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000307 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000308}
309
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000310TEST_F(SendStatisticsProxyTest, SendSideDelay) {
311 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700312 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000313 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
314 // stream.
315 int avg_delay_ms = ssrc;
316 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200317 uint64_t total_packet_send_delay_ms = ssrc + 2;
318 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
319 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000320 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
321 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200322 expected_.substreams[ssrc].total_packet_send_delay_ms =
323 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000324 }
asapersson35151f32016-05-02 23:44:01 -0700325 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000326 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
327 // stream.
328 int avg_delay_ms = ssrc;
329 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200330 uint64_t total_packet_send_delay_ms = ssrc + 2;
331 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
332 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000333 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
334 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200335 expected_.substreams[ssrc].total_packet_send_delay_ms =
336 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000337 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000338 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000339 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000340}
341
Peter Boströme4499152016-02-05 11:13:28 +0100342TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800343 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200344 int encode_usage_percent = 80;
345 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
346 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800347
348 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
349 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200350 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800351}
352
Henrik Boström5684af52019-04-02 15:05:21 +0200353TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
354 const int kEncodeUsagePercent = 0; // Don't care for this test.
355 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
356 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
357 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
358 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
359 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
360}
361
sakal43536c32016-10-24 01:46:43 -0700362TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
363 EncodedImage encoded_image;
364 CodecSpecificInfo codec_info;
365 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
366 for (uint32_t i = 1; i <= 3; ++i) {
367 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
368 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
369 }
370}
371
sakal87da4042016-10-31 06:53:47 -0700372TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
373 EncodedImage encoded_image;
374 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200375 auto ssrc = config_.rtp.ssrcs[0];
376 EXPECT_EQ(absl::nullopt,
377 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700378 encoded_image.qp_ = 3;
379 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200380 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700381 encoded_image.qp_ = 127;
382 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200383 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700384}
385
386TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
387 EncodedImage encoded_image;
388 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200389 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700390 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200391 EXPECT_EQ(absl::nullopt,
392 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700393 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200394 EXPECT_EQ(absl::nullopt,
395 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700396}
397
Henrik Boström23aff9b2019-05-20 15:15:38 +0200398TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
399 const uint32_t kTargetBytesPerSecond = 100000;
400 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
401 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
402
403 EncodedImage encoded_image;
404 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
405 // On the first frame we don't know the frame rate yet, calculation yields
406 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
407 // increment by a full |kTargetBytesPerSecond|.
408 EXPECT_EQ(kTargetBytesPerSecond,
409 statistics_proxy_->GetStats().total_encoded_bytes_target);
410}
411
412TEST_F(SendStatisticsProxyTest,
413 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
414 const uint32_t kTargetBytesPerSecond = 100000;
415 const int kInterframeDelayMs = 100;
416
417 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
418 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
419 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
420 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
421 // this test can stop relying on rtc::ScopedFakeClock.
422 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100423 fake_global_clock.SetTime(
424 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200425
426 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
427 EncodedImage encoded_image;
428
429 // First frame
430 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
431 uint64_t first_total_encoded_bytes_target =
432 statistics_proxy_->GetStats().total_encoded_bytes_target;
433 // Second frame
434 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100435 fake_global_clock.SetTime(
436 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200437 encoded_image.SetTimestamp(encoded_image.Timestamp() +
438 90 * kInterframeDelayMs);
439 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
440
441 auto stats = statistics_proxy_->GetStats();
442 // By the time the second frame arrives, one frame has previously arrived
443 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
444 // the second frame's arrival should be 10 FPS.
445 uint64_t delta_encoded_bytes_target =
446 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
447 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
448}
449
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200450TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
451 const int kInterframeDelayMs = 100;
452 auto ssrc = config_.rtp.ssrcs[0];
453 rtc::ScopedFakeClock fake_global_clock;
454 fake_global_clock.SetTime(
455 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
456
457 EncodedImage encoded_image;
458
459 // First frame
460 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
461 // Second frame
462 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
463 fake_global_clock.SetTime(
464 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
465 encoded_image.SetTimestamp(encoded_image.Timestamp() +
466 90 * kInterframeDelayMs);
467 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
468
469 auto stats = statistics_proxy_->GetStats();
470 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
471}
472
asapersson09f05612017-05-15 23:40:18 -0700473TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200474 VideoAdaptationCounters cpu_counts;
475 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700476 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700477 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200478 cpu_counts.fps_adaptations = 1;
479 cpu_counts.resolution_adaptations = 0;
480 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200481 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
482 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700483 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700484 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200485 cpu_counts.fps_adaptations = 0;
486 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200487 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
488 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700489 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700490 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200491 cpu_counts.fps_adaptations = 1;
492 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
493 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200494 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
495 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700496 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700497 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200498 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
499 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200500 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
501 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700502 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
503 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
504}
505
506TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200507 VideoAdaptationCounters cpu_counts;
508 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700509 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
510 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200511 quality_counts.fps_adaptations = 1;
512 quality_counts.resolution_adaptations = 0;
513 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200514 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
515 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700516 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
517 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200518 quality_counts.fps_adaptations = 0;
519 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200520 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
521 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700522 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
523 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200524 quality_counts.fps_adaptations = 1;
525 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
526 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200527 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
528 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700529 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
530 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200531 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
532 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200533 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
534 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700535 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
536 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
537}
538
539TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200540 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
541 VideoAdaptationCounters cpu_counts;
542 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700543 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
544
Evan Shrubsoledff79252020-04-16 11:34:32 +0200545 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200546 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
547 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700548 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700549 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
550 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
551
Evan Shrubsoledff79252020-04-16 11:34:32 +0200552 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200553 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
554 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700555 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
556 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700557 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700558 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700559}
560
asapersson09f05612017-05-15 23:40:18 -0700561TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200562 VideoAdaptationCounters cpu_counts;
563 VideoAdaptationCounters quality_counts;
564 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700565 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
566
Evan Shrubsoledff79252020-04-16 11:34:32 +0200567 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200568 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
569 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700570 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
571 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700572 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
573
Evan Shrubsoledff79252020-04-16 11:34:32 +0200574 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200575 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
576 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700577 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700578 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700579 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
580 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700581}
582
Evan Shrubsoledff79252020-04-16 11:34:32 +0200583TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
584 VideoAdaptationCounters cpu_counts;
585 VideoAdaptationCounters quality_counts;
586 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
587 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
588 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
589
590 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200591 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
592 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200593 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200594 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
595 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200596 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200597 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
598 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200599 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200600 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
601 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200602 // We have 1 fps and resolution reduction for both cpu and quality
603 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
604 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
605 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
606 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
607 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
608 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
609
610 // Disable quality scaling. Expect quality scaling not limited.
611 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
612 kScalingDisabled);
613 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
614 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
615 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
616 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
617 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
618 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
619
620 // Disable framerate scaling.
621 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
622 kFramerateScalingDisabled);
623 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
624 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
625 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
626 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
627 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
628 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
629
630 // Disable resolution scaling.
631 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
632 kResolutionScalingDisabled);
633 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
634 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
635 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
636 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
637 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
638 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
639
640 // Enable all
641 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
642 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
643 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
644 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
645 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
646 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
647 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
648}
649
asapersson09f05612017-05-15 23:40:18 -0700650TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700651 // First RTP packet sent.
652 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700653 // Min runtime has passed.
654 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
655 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100656 EXPECT_METRIC_EQ(
657 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
658 EXPECT_METRIC_EQ(
659 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700660}
661
662TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700663 // First RTP packet sent.
664 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700665 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200666 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700667 // Min runtime has not passed.
668 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
669 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100670 EXPECT_METRIC_EQ(
671 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
672 EXPECT_METRIC_EQ(
673 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700674}
675
asapersson09f05612017-05-15 23:40:18 -0700676TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700677 // First RTP packet sent.
678 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700679 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200680 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700681 // Min runtime has passed.
682 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
683 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100684 EXPECT_METRIC_EQ(
685 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
686 EXPECT_METRIC_EQ(
687 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
688 EXPECT_METRIC_EQ(
689 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
690 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700691 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
692}
693
694TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700695 // First RTP packet sent.
696 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700697 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200698 VideoAdaptationCounters cpu_counts;
699 VideoAdaptationCounters quality_counts;
700 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700701 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200702 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
703 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700704 fake_clock_.AdvanceTimeMilliseconds(10000);
705 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100706 EXPECT_METRIC_EQ(
707 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
708 EXPECT_METRIC_EQ(
709 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700710}
711
Åsa Persson875841d2018-01-08 08:49:53 +0100712TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
713 // First RTP packet sent.
714 UpdateDataCounters(kFirstSsrc);
715 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200716 VideoAdaptationCounters cpu_counts;
717 VideoAdaptationCounters quality_counts;
718 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100719 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200720 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
721 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100722 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
723 fake_clock_.AdvanceTimeMilliseconds(10000);
724 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100725 EXPECT_METRIC_EQ(
726 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
727 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100728 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
729}
730
731TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
732 // First RTP packet sent.
733 UpdateDataCounters(kFirstSsrc);
734 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200735 VideoAdaptationCounters cpu_counts;
736 VideoAdaptationCounters quality_counts;
737 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100738 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200739 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200740 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
741 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100742 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200743 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200744 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
745 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100746 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200747 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200748 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
749 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100750 fake_clock_.AdvanceTimeMilliseconds(10000);
751 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100752 EXPECT_METRIC_EQ(
753 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
754 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100755 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
756}
757
758TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
759 // First RTP packet sent.
760 UpdateDataCounters(kFirstSsrc);
761 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200762 VideoAdaptationCounters cpu_counts;
763 VideoAdaptationCounters quality_counts;
764 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100765 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200766 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
767 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100768 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
769 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
770 fake_clock_.AdvanceTimeMilliseconds(10000);
771 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100772 EXPECT_METRIC_EQ(
773 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
774 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100775 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
776}
777
778TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
779 // First RTP packet sent.
780 UpdateDataCounters(kFirstSsrc);
781 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200782 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
783 VideoAdaptationCounters cpu_counts;
784 VideoAdaptationCounters quality_counts;
785 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100786 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200787 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200788 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
789 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100790 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200791 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200792 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
793 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100794 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200795 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200796 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
797 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200798 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200799 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
800 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200801 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200802 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
803 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200804 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200805 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
806 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200807 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200808 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
809 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200810 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200811 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
812 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100813
814 fake_clock_.AdvanceTimeMilliseconds(10000);
815 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100816 EXPECT_METRIC_EQ(
817 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
818 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100819 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
820}
821
asapersson6eca98b2017-04-04 23:40:50 -0700822TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700823 // First RTP packet sent.
824 UpdateDataCounters(kFirstSsrc);
825
asapersson09f05612017-05-15 23:40:18 -0700826 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200827 VideoAdaptationCounters cpu_counts;
828 VideoAdaptationCounters quality_counts;
829 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
830 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700831 fake_clock_.AdvanceTimeMilliseconds(10000);
832
asapersson09f05612017-05-15 23:40:18 -0700833 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700834 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200835 quality_counts.fps_adaptations = 0;
836 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
837 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700838 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200839 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
840 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700841 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200842 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
843 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700844 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200845 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
846 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700847
asapersson09f05612017-05-15 23:40:18 -0700848 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200849 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
850 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700851 fake_clock_.AdvanceTimeMilliseconds(30000);
852
asapersson09f05612017-05-15 23:40:18 -0700853 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700854 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200855 quality_counts.resolution_adaptations = 0;
856 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
857 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200858 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
859 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700860 fake_clock_.AdvanceTimeMilliseconds(10000);
861
asapersson09f05612017-05-15 23:40:18 -0700862 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200863 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
864 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700865 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200866 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
867 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700868 fake_clock_.AdvanceTimeMilliseconds(20000);
869
asapersson0944a802017-04-07 00:57:58 -0700870 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700871 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100872 EXPECT_METRIC_EQ(
873 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
874 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700875 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
876}
877
asapersson0944a802017-04-07 00:57:58 -0700878TEST_F(SendStatisticsProxyTest,
879 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
880 // First RTP packet sent.
881 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700882
asapersson0944a802017-04-07 00:57:58 -0700883 // Suspend and resume video.
884 statistics_proxy_->OnSuspendChange(true);
885 fake_clock_.AdvanceTimeMilliseconds(5000);
886 statistics_proxy_->OnSuspendChange(false);
887
888 // Min runtime has passed but scaling not enabled.
889 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
890 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100891 EXPECT_METRIC_EQ(
892 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
893 EXPECT_METRIC_EQ(
894 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700895}
896
897TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
898 // First RTP packet sent.
899 UpdateDataCounters(kFirstSsrc);
900
asapersson09f05612017-05-15 23:40:18 -0700901 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200902 VideoAdaptationCounters cpu_counts;
903 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700904 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200905 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700906 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200907 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
908 cpu_counts, quality_counts);
909 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
910 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700911
912 // Suspend and resume video.
913 statistics_proxy_->OnSuspendChange(true);
914 fake_clock_.AdvanceTimeMilliseconds(30000);
915 statistics_proxy_->OnSuspendChange(false);
916
917 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200918 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
919 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700920 fake_clock_.AdvanceTimeMilliseconds(10000);
921
922 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
923 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100924 EXPECT_METRIC_EQ(
925 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
926 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700927 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
928}
929
930TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
931 // First RTP packet sent.
932 UpdateDataCounters(kFirstSsrc);
933
934 // Video not suspended.
935 statistics_proxy_->OnSuspendChange(false);
936 fake_clock_.AdvanceTimeMilliseconds(30000);
937
asapersson09f05612017-05-15 23:40:18 -0700938 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200939 VideoAdaptationCounters cpu_counts;
940 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700941 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200942 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700943 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200944 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
945 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700946
947 // Video not suspended, stats time already started.
948 statistics_proxy_->OnSuspendChange(false);
949 fake_clock_.AdvanceTimeMilliseconds(10000);
950
asapersson09f05612017-05-15 23:40:18 -0700951 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200952 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
953 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -0700954 fake_clock_.AdvanceTimeMilliseconds(30000);
955
956 // Suspend and resume video, stats time not started when scaling not enabled.
957 statistics_proxy_->OnSuspendChange(true);
958 fake_clock_.AdvanceTimeMilliseconds(30000);
959 statistics_proxy_->OnSuspendChange(false);
960 fake_clock_.AdvanceTimeMilliseconds(30000);
961
asapersson09f05612017-05-15 23:40:18 -0700962 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700963 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200964 cpu_counts.fps_adaptations = 0;
965 cpu_counts.resolution_adaptations = 0;
966 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700967 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200968 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
969 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700970
971 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
972 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100973 EXPECT_METRIC_EQ(
974 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
975 EXPECT_METRIC_EQ(
976 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700977}
978
979TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
980 // First RTP packet sent.
981 UpdateDataCounters(kFirstSsrc);
982
983 // Video suspended.
984 statistics_proxy_->OnSuspendChange(true);
985
asapersson09f05612017-05-15 23:40:18 -0700986 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200987 VideoAdaptationCounters cpu_counts;
988 VideoAdaptationCounters quality_counts;
989 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700990 fake_clock_.AdvanceTimeMilliseconds(10000);
991
992 // Resume video, stats time started.
993 // Adapt changes: 1, elapsed time: 10 sec.
994 statistics_proxy_->OnSuspendChange(false);
995 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200996 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
997 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700998
999 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1000 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001001 EXPECT_METRIC_EQ(
1002 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1003 EXPECT_METRIC_EQ(
1004 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -07001005}
1006
1007TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001008 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001009 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001010 VideoAdaptationCounters cpu_counts;
1011 VideoAdaptationCounters quality_counts;
1012 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001013 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001014 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001015
asapersson0944a802017-04-07 00:57:58 -07001016 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001017 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001018 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1019 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001020 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001021
asapersson0944a802017-04-07 00:57:58 -07001022 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001023 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001024 EXPECT_METRIC_EQ(
1025 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1026 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001027 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1028}
1029
1030TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001031 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001032 VideoAdaptationCounters cpu_counts;
1033 VideoAdaptationCounters quality_counts;
1034 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001035 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001036 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1037 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001038
1039 // Send first packet, scaling disabled.
1040 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001041 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001042 fake_clock_.AdvanceTimeMilliseconds(60000);
1043
asapersson09f05612017-05-15 23:40:18 -07001044 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001045 cpu_counts.resolution_adaptations = 0;
1046 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1047 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001048 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001049 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001050
asapersson0944a802017-04-07 00:57:58 -07001051 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001052 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001053 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1054 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001055
asapersson0944a802017-04-07 00:57:58 -07001056 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001057 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001058 EXPECT_METRIC_EQ(
1059 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1060 EXPECT_METRIC_EQ(
1061 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001062}
1063
1064TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001065 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001066 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001067 VideoAdaptationCounters cpu_counts;
1068 VideoAdaptationCounters quality_counts;
1069 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1070 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001071
asapersson0944a802017-04-07 00:57:58 -07001072 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001073 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1074 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001075 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001076 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1077 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001078 fake_clock_.AdvanceTimeMilliseconds(9000);
1079
1080 // Switch content type, real-time stats should be updated.
1081 VideoEncoderConfig config;
1082 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001083 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001084 EXPECT_METRIC_EQ(
1085 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1086 EXPECT_METRIC_EQ(
1087 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1088 EXPECT_METRIC_EQ(
1089 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001090
asapersson0944a802017-04-07 00:57:58 -07001091 // First RTP packet sent, scaling enabled.
1092 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001093 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1094 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001095
asapersson0944a802017-04-07 00:57:58 -07001096 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001097 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1098 cpu_counts, quality_counts);
1099 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1100 cpu_counts, quality_counts);
1101 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1102 cpu_counts, quality_counts);
1103 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1104 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001105 fake_clock_.AdvanceTimeMilliseconds(120000);
1106
1107 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001108 EXPECT_METRIC_EQ(1,
1109 metrics::NumSamples(
1110 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1111 EXPECT_METRIC_EQ(
1112 1, metrics::NumEvents(
1113 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1114 EXPECT_METRIC_EQ(
1115 0, metrics::NumSamples(
1116 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001117}
1118
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001119TEST_F(SendStatisticsProxyTest,
1120 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001121 VideoAdaptationCounters cpu_counts;
1122 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001123
Evan Shrubsoledff79252020-04-16 11:34:32 +02001124 cpu_counts.resolution_adaptations = 1;
1125 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001126 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1127 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001128
1129 EXPECT_EQ(QualityLimitationReason::kCpu,
1130 statistics_proxy_->GetStats().quality_limitation_reason);
1131}
1132
1133TEST_F(SendStatisticsProxyTest,
1134 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001135 VideoAdaptationCounters cpu_counts;
1136 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001137
Evan Shrubsoledff79252020-04-16 11:34:32 +02001138 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001139
Evan Shrubsoledff79252020-04-16 11:34:32 +02001140 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001141 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1142 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001143
1144 EXPECT_EQ(QualityLimitationReason::kCpu,
1145 statistics_proxy_->GetStats().quality_limitation_reason);
1146}
1147
1148TEST_F(SendStatisticsProxyTest,
1149 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001150 VideoAdaptationCounters cpu_counts;
1151 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001152
Evan Shrubsoledff79252020-04-16 11:34:32 +02001153 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001154
Evan Shrubsoledff79252020-04-16 11:34:32 +02001155 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001156 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1157 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001158
1159 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1160 statistics_proxy_->GetStats().quality_limitation_reason);
1161}
1162
1163TEST_F(SendStatisticsProxyTest,
1164 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001165 VideoAdaptationCounters cpu_counts;
1166 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001167
Evan Shrubsoledff79252020-04-16 11:34:32 +02001168 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001169
Evan Shrubsoledff79252020-04-16 11:34:32 +02001170 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001171 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1172 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001173
1174 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1175 statistics_proxy_->GetStats().quality_limitation_reason);
1176}
1177
1178TEST_F(SendStatisticsProxyTest,
1179 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001180 VideoAdaptationCounters cpu_counts;
1181 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001182
Evan Shrubsoledff79252020-04-16 11:34:32 +02001183 cpu_counts.resolution_adaptations = 1;
1184 quality_counts.resolution_adaptations = 1;
1185 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001186
1187 // Even if the last adaptation reason is kCpu, if the counters indicate being
1188 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001189 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1190 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001191
1192 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1193 statistics_proxy_->GetStats().quality_limitation_reason);
1194}
1195
1196TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001197 VideoAdaptationCounters cpu_counts;
1198 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001199
1200 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1201 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001202 cpu_counts.resolution_adaptations = 1;
1203 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001204 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1205 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001206 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001207 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001208 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1209 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001210
1211 EXPECT_EQ(QualityLimitationReason::kNone,
1212 statistics_proxy_->GetStats().quality_limitation_reason);
1213}
1214
1215TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001216 VideoAdaptationCounters cpu_counts;
1217 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001218
Evan Shrubsoledff79252020-04-16 11:34:32 +02001219 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001220 // Not limited for 3000 ms
1221 fake_clock_.AdvanceTimeMilliseconds(3000);
1222 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001223 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001224 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1225 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001226 fake_clock_.AdvanceTimeMilliseconds(2000);
1227 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001228 cpu_counts.resolution_adaptations = 0;
1229 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001230 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1231 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001232 fake_clock_.AdvanceTimeMilliseconds(1000);
1233 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001234 cpu_counts.resolution_adaptations = 1;
1235 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001236 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1237 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001238 fake_clock_.AdvanceTimeMilliseconds(2000);
1239
1240 auto quality_limitation_durations_ms =
1241 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1242
1243 EXPECT_EQ(3000,
1244 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1245 EXPECT_EQ(4000,
1246 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1247 EXPECT_EQ(
1248 1000,
1249 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1250 EXPECT_EQ(0,
1251 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1252}
1253
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001254TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1255 EXPECT_EQ(
1256 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1257}
1258
1259TEST_F(SendStatisticsProxyTest,
1260 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1261 VideoCodec codec;
1262 VideoBitrateAllocation allocation;
1263 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1264 EXPECT_EQ(
1265 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1266}
1267
1268TEST_F(SendStatisticsProxyTest,
1269 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1270 VideoCodec codec;
1271 codec.simulcastStream[0].active = true;
1272 codec.simulcastStream[1].active = true;
1273 codec.simulcastStream[2].active = true;
1274 VideoBitrateAllocation allocation;
1275 allocation.SetBitrate(0, 0, 100);
1276 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1277 EXPECT_EQ(
1278 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1279}
1280
1281TEST_F(SendStatisticsProxyTest,
1282 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1283 VideoCodec codec;
1284 codec.simulcastStream[0].active = true;
1285 codec.simulcastStream[1].active = true;
1286 codec.simulcastStream[2].active = true;
1287 VideoBitrateAllocation allocation;
1288 allocation.SetBitrate(0, 0, 100);
1289 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1290 allocation.SetBitrate(1, 0, 100);
1291 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1292 EXPECT_EQ(
1293 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1294}
1295
1296TEST_F(SendStatisticsProxyTest,
1297 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1298 VideoCodec codec;
1299 codec.simulcastStream[0].active = true;
1300 VideoBitrateAllocation allocation;
1301 allocation.SetBitrate(0, 0, 100);
1302 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1303 // Layer 0 got more bandwidth, but still only one layer on
1304 allocation.SetBitrate(0, 0, 200);
1305 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1306 EXPECT_EQ(
1307 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1308}
1309
1310TEST_F(SendStatisticsProxyTest,
1311 QualityLimitationResolutionChangesWithTogglingLayers) {
1312 VideoCodec codec;
1313 codec.simulcastStream[0].active = true;
1314 codec.simulcastStream[1].active = true;
1315 codec.simulcastStream[2].active = true;
1316 VideoBitrateAllocation allocation;
1317 allocation.SetBitrate(0, 0, 100);
1318 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1319 EXPECT_EQ(
1320 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1321 allocation.SetBitrate(1, 0, 300);
1322 allocation.SetBitrate(2, 0, 500);
1323 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1324 EXPECT_EQ(
1325 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1326 // Layer 2 off
1327 allocation.SetBitrate(2, 0, 0);
1328 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1329 EXPECT_EQ(
1330 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1331 // Layer 2 back on
1332 allocation.SetBitrate(2, 0, 500);
1333 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1334 EXPECT_EQ(
1335 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1336 allocation.SetBitrate(0, 0, 0);
1337 allocation.SetBitrate(1, 0, 0);
1338 allocation.SetBitrate(2, 0, 0);
1339 // All layers off
1340 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1341 EXPECT_EQ(
1342 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1343}
1344
1345TEST_F(SendStatisticsProxyTest,
1346 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1347 VideoCodec codec;
1348 // 3 layers
1349 codec.simulcastStream[0].active = true;
1350 codec.simulcastStream[1].active = true;
1351 codec.simulcastStream[2].active = true;
1352 VideoBitrateAllocation allocation;
1353 allocation.SetBitrate(0, 0, 500);
1354 allocation.SetBitrate(1, 0, 500);
1355 allocation.SetBitrate(2, 0, 500);
1356 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1357 EXPECT_EQ(
1358 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1359
1360 // Down to one layer now, triggered by a config change
1361 codec.numberOfSimulcastStreams = 1;
1362 codec.simulcastStream[1].active = false;
1363 codec.simulcastStream[2].active = false;
1364 allocation.SetBitrate(0, 0, 100);
1365 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1366 EXPECT_EQ(
1367 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1368
1369 // Up to 3 layers again.
1370 codec.numberOfSimulcastStreams = 3;
1371 codec.simulcastStream[1].active = true;
1372 codec.simulcastStream[2].active = true;
1373 allocation.SetBitrate(0, 0, 500);
1374 allocation.SetBitrate(1, 0, 500);
1375 allocation.SetBitrate(2, 0, 500);
1376 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1377 EXPECT_EQ(
1378 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1379}
1380
1381TEST_F(SendStatisticsProxyTest,
1382 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1383 VideoCodec codec;
1384 codec.simulcastStream[0].active = true;
1385 codec.spatialLayers[0].active = true;
1386 codec.spatialLayers[1].active = true;
1387 codec.spatialLayers[2].active = true;
1388 VideoBitrateAllocation allocation;
1389 allocation.SetBitrate(0, 0, 500);
1390 allocation.SetBitrate(1, 0, 500);
1391 allocation.SetBitrate(2, 0, 500);
1392 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1393 EXPECT_EQ(
1394 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1395
1396 // Down to one layer now, triggered by a config change
1397 codec.spatialLayers[1].active = false;
1398 codec.spatialLayers[2].active = false;
1399 allocation.SetBitrate(0, 0, 100);
1400 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1401 EXPECT_EQ(
1402 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1403
1404 // Up to 3 layers again.
1405 codec.spatialLayers[1].active = true;
1406 codec.spatialLayers[2].active = true;
1407 allocation.SetBitrate(0, 0, 500);
1408 allocation.SetBitrate(1, 0, 500);
1409 allocation.SetBitrate(2, 0, 500);
1410 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1411 EXPECT_EQ(
1412 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1413}
1414
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001415TEST_F(SendStatisticsProxyTest,
1416 QualityLimitationReasonsAreCorrectForContentType) {
1417 // Realtime case.
1418 // Configure two streams.
1419 VideoEncoderConfig config;
1420 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1421 config.number_of_streams = 2;
1422 VideoStream stream1;
1423 stream1.width = kWidth / 2;
1424 stream1.height = kHeight / 2;
1425 VideoStream stream2;
1426 stream2.width = kWidth;
1427 stream2.height = kHeight;
1428 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1429 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1430 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1431 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1432 QualityLimitationReason::kNone);
1433 // Bw disabled one layer.
1434 VideoCodec codec;
1435 codec.numberOfSimulcastStreams = 2;
1436 codec.simulcastStream[0].active = true;
1437 codec.simulcastStream[1].active = true;
1438 VideoBitrateAllocation allocation;
1439 // Some positive bitrate only on the first stream.
1440 allocation.SetBitrate(0, 0, 10000);
1441 allocation.SetBitrate(1, 0, 0);
1442 allocation.set_bw_limited(true);
1443 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1444 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1445 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1446 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1447 QualityLimitationReason::kBandwidth);
1448 // Bw enabled all layers.
1449 allocation.SetBitrate(1, 0, 10000);
1450 allocation.set_bw_limited(false);
1451 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1452 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1453 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1454 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1455 QualityLimitationReason::kNone);
1456
1457 // Screencast case
1458 // Configure two streams.
1459 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1460 config.number_of_streams = 2;
1461 stream1.width = kWidth;
1462 stream1.height = kHeight;
1463 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1464 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1465 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1466 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1467 QualityLimitationReason::kNone);
1468 // Bw disabled one layer.
1469 // Some positive bitrate only on the second stream.
1470 allocation.SetBitrate(0, 0, 10000);
1471 allocation.SetBitrate(1, 0, 0);
1472 allocation.set_bw_limited(true);
1473 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1474 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1475 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1476 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1477 QualityLimitationReason::kBandwidth);
1478 // Bw enabled all layers.
1479 allocation.SetBitrate(1, 0, 10000);
1480 allocation.set_bw_limited(false);
1481 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1482 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1483 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1484 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1485 QualityLimitationReason::kNone);
1486}
1487
asapersson59bac1a2016-01-07 23:36:00 -08001488TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001489 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001490 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1491
Pera48ddb72016-09-29 11:48:50 +02001492 // No switch, stats should not be updated.
1493 VideoEncoderConfig config;
1494 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001495 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001496 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001497
1498 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001499 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001500 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001501 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001502}
1503
asapersson320e45a2016-11-29 01:40:35 -08001504TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1505 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1506 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001507
asapersson320e45a2016-11-29 01:40:35 -08001508 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001509 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1510 EXPECT_METRIC_EQ(
1511 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1512 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1513 EXPECT_METRIC_EQ(
1514 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001515}
1516
1517TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001518 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001519 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001520 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1521 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1522 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001523 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001524
1525 // Not enough samples, stats should not be updated.
1526 for (int i = 0; i < kMinSamples - 1; ++i) {
1527 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001528 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001529 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1530 }
Åsa Persson0122e842017-10-16 12:19:23 +02001531 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001532 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1533 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001534
1535 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001536 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001537 for (int i = 0; i < kMinSamples; ++i) {
1538 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001539 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001540 encoded_image._encodedWidth = kWidth;
1541 encoded_image._encodedHeight = kHeight;
1542 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1543 encoded_image._encodedWidth = kWidth / 2;
1544 encoded_image._encodedHeight = kHeight / 2;
1545 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1546 }
1547
asapersson320e45a2016-11-29 01:40:35 -08001548 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001549 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1550 EXPECT_METRIC_EQ(
1551 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1552 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1553 EXPECT_METRIC_EQ(
1554 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001555}
1556
1557TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1558 const int kFps = 20;
1559 const int kMinPeriodicSamples = 6;
1560 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1561 for (int i = 0; i <= frames; ++i) {
1562 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1563 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1564 }
1565 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001566 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1567 EXPECT_METRIC_EQ(
1568 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001569}
1570
1571TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1572 EncodedImage encoded_image;
1573 const int kFps = 20;
1574 const int kMinPeriodicSamples = 6;
1575 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001576 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001577 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001578 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001579 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1580 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001581 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1582 }
1583 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001584 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1585 EXPECT_METRIC_EQ(
1586 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001587}
1588
1589TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1590 const int kFps = 20;
1591 const int kSuspendTimeMs = 10000;
1592 const int kMinPeriodicSamples = 6;
1593 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1594 for (int i = 0; i < frames; ++i) {
1595 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1596 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1597 }
1598 // Suspend.
1599 statistics_proxy_->OnSuspendChange(true);
1600 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1601
1602 for (int i = 0; i < frames; ++i) {
1603 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1604 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1605 }
1606 // Suspended time interval should not affect the framerate.
1607 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001608 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1609 EXPECT_METRIC_EQ(
1610 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001611}
1612
1613TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1614 EncodedImage encoded_image;
1615 const int kFps = 20;
1616 const int kSuspendTimeMs = 10000;
1617 const int kMinPeriodicSamples = 6;
1618 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001619 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001620 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001621 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001622 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1623 }
1624 // Suspend.
1625 statistics_proxy_->OnSuspendChange(true);
1626 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1627
Åsa Persson0122e842017-10-16 12:19:23 +02001628 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001629 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001630 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001631 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1632 }
1633 // Suspended time interval should not affect the framerate.
1634 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001635 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1636 EXPECT_METRIC_EQ(
1637 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001638}
1639
asaperssonf4e44af2017-04-19 02:01:06 -07001640TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001641 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1642 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001643
1644 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1645 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1646
1647 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001648 EXPECT_METRIC_EQ(
1649 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001650}
1651
1652TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001653 VideoAdaptationCounters cpu_counts;
1654 VideoAdaptationCounters quality_counts;
1655 cpu_counts.resolution_adaptations = 0;
1656 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001657
perkj803d97f2016-11-01 11:45:46 -07001658 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1659 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1660
Evan Shrubsoledff79252020-04-16 11:34:32 +02001661 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001662 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1663 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001664
1665 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1666 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1667
1668 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001669 EXPECT_METRIC_EQ(
1670 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1671 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001672 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1673}
1674
asapersson4374a092016-07-27 00:39:09 -07001675TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1676 const int64_t kTimeSec = 3;
1677 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1678 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001679 EXPECT_METRIC_EQ(
1680 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1681 EXPECT_METRIC_EQ(
1682 1,
1683 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001684}
1685
1686TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1687 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1688 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001689 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001690}
1691
asapersson66d4b372016-12-19 06:50:53 -08001692TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1693 // First RTP packet sent.
1694 UpdateDataCounters(kFirstSsrc);
1695
1696 // Min runtime has passed.
1697 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1698 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001699 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1700 EXPECT_METRIC_EQ(1,
1701 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001702}
1703
1704TEST_F(SendStatisticsProxyTest,
1705 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1706 // First RTP packet sent.
1707 UpdateDataCounters(kFirstSsrc);
1708
1709 // Min runtime has not passed.
1710 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1711 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001712 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1713 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001714}
1715
1716TEST_F(SendStatisticsProxyTest,
1717 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1718 // First RTP packet not sent.
1719 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1720 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001721 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001722}
1723
1724TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1725 // First RTP packet sent and min runtime passed.
1726 UpdateDataCounters(kFirstSsrc);
1727
1728 // No change. Video: 10000 ms, paused: 0 ms (0%).
1729 statistics_proxy_->OnSetEncoderTargetRate(50000);
1730 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1731 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1732
1733 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001734 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1735 EXPECT_METRIC_EQ(1,
1736 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1737 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1738 EXPECT_METRIC_EQ(1,
1739 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001740}
1741
1742TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1743 // First RTP packet sent and min runtime passed.
1744 UpdateDataCounters(kFirstSsrc);
1745
1746 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1747 statistics_proxy_->OnSetEncoderTargetRate(50000);
1748 fake_clock_.AdvanceTimeMilliseconds(7000);
1749 statistics_proxy_->OnSetEncoderTargetRate(0);
1750 fake_clock_.AdvanceTimeMilliseconds(3000);
1751 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1752
1753 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001754 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1755 EXPECT_METRIC_EQ(1,
1756 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1757 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1758 EXPECT_METRIC_EQ(1,
1759 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001760}
1761
1762TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1763 // First RTP packet sent.
1764 UpdateDataCounters(kFirstSsrc);
1765
1766 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1767 statistics_proxy_->OnSetEncoderTargetRate(0);
1768 fake_clock_.AdvanceTimeMilliseconds(1000);
1769 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1770 fake_clock_.AdvanceTimeMilliseconds(7000);
1771 statistics_proxy_->OnSetEncoderTargetRate(60000);
1772 fake_clock_.AdvanceTimeMilliseconds(3000);
1773 statistics_proxy_->OnSetEncoderTargetRate(0);
1774 fake_clock_.AdvanceTimeMilliseconds(250);
1775 statistics_proxy_->OnSetEncoderTargetRate(0);
1776 fake_clock_.AdvanceTimeMilliseconds(750);
1777 statistics_proxy_->OnSetEncoderTargetRate(60000);
1778 fake_clock_.AdvanceTimeMilliseconds(5000);
1779 statistics_proxy_->OnSetEncoderTargetRate(50000);
1780 fake_clock_.AdvanceTimeMilliseconds(4000);
1781 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1782
1783 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001784 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1785 EXPECT_METRIC_EQ(1,
1786 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1787 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1788 EXPECT_METRIC_EQ(1,
1789 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001790}
1791
1792TEST_F(SendStatisticsProxyTest,
1793 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1794 // First RTP packet sent.
1795 UpdateDataCounters(kFirstSsrc);
1796 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1797
1798 // Min runtime has not passed.
1799 statistics_proxy_->OnSetEncoderTargetRate(50000);
1800 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1801 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1802
1803 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001804 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001805}
1806
asapersson118ef002016-03-31 00:00:19 -07001807TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001808 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001809 CodecSpecificInfo codec_info;
1810 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001811
perkj803d97f2016-11-01 11:45:46 -07001812 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001813 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001814 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001815 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001816 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001817 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001818 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001819 }
1820 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001821 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1822 EXPECT_METRIC_EQ(
1823 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1824 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1825 EXPECT_METRIC_EQ(
1826 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001827}
1828
1829TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1830 VideoSendStream::Config config(nullptr);
1831 config.rtp.ssrcs.push_back(kFirstSsrc);
1832 statistics_proxy_.reset(new SendStatisticsProxy(
1833 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1834
asapersson118ef002016-03-31 00:00:19 -07001835 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001836 CodecSpecificInfo codec_info;
1837 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001838
perkj803d97f2016-11-01 11:45:46 -07001839 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001840 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001841 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001842 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001843 }
1844 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001845 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1846 EXPECT_METRIC_EQ(1,
1847 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001848}
1849
asapersson5265fed2016-04-18 02:58:47 -07001850TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001851 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001852 CodecSpecificInfo codec_info;
1853 codec_info.codecType = kVideoCodecVP9;
1854 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001855
perkj803d97f2016-11-01 11:45:46 -07001856 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001857 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001858 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001859 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001860 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001861 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001862 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001863 }
1864 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001865 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1866 EXPECT_METRIC_EQ(
1867 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1868 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1869 EXPECT_METRIC_EQ(
1870 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001871}
1872
1873TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1874 VideoSendStream::Config config(nullptr);
1875 config.rtp.ssrcs.push_back(kFirstSsrc);
1876 statistics_proxy_.reset(new SendStatisticsProxy(
1877 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1878
asapersson5265fed2016-04-18 02:58:47 -07001879 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001880 CodecSpecificInfo codec_info;
1881 codec_info.codecType = kVideoCodecVP9;
1882 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001883
perkj803d97f2016-11-01 11:45:46 -07001884 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001885 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001886 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001887 }
1888 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001889 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1890 EXPECT_METRIC_EQ(1,
1891 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001892}
1893
asapersson827cab32016-11-02 09:08:47 -07001894TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1895 EncodedImage encoded_image;
1896 CodecSpecificInfo codec_info;
1897 codec_info.codecType = kVideoCodecH264;
1898
1899 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001900 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001901 encoded_image.qp_ = kQpIdx0;
1902 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001903 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001904 encoded_image.qp_ = kQpIdx1;
1905 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001906 }
1907 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001908 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1909 EXPECT_METRIC_EQ(
1910 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1911 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1912 EXPECT_METRIC_EQ(
1913 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001914}
1915
asapersson4ee70462016-10-31 04:05:12 -07001916TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001917 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1918 // Configure one stream.
1919 VideoEncoderConfig config;
1920 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1921 VideoStream stream1;
1922 stream1.width = kWidth;
1923 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001924 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001925
1926 const int64_t kMaxEncodedFrameWindowMs = 800;
1927 const int kFps = 20;
1928 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1929 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1930 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1931
1932 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001933 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001934 encoded_image._encodedWidth = kWidth;
1935 encoded_image._encodedHeight = kHeight;
1936 for (int i = 0; i < kMinSamples; ++i) {
1937 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001938 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1939 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001940 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001941 }
asapersson4ee70462016-10-31 04:05:12 -07001942
1943 // Histograms are updated when the statistics_proxy_ is deleted.
1944 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001945 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1946 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1947 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1948 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001949}
1950
1951TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001952 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1953 // Configure two streams.
1954 VideoEncoderConfig config;
1955 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1956 VideoStream stream1;
1957 stream1.width = kWidth / 2;
1958 stream1.height = kHeight / 2;
1959 VideoStream stream2;
1960 stream2.width = kWidth;
1961 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001962 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001963
1964 const int64_t kMaxEncodedFrameWindowMs = 800;
1965 const int kFps = 20;
1966 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1967 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1968 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1969
1970 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001971 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001972 for (int i = 0; i < kMinSamples; ++i) {
1973 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001974 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1975 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001976 encoded_image._encodedWidth = kWidth;
1977 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001978 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001979 encoded_image._encodedWidth = kWidth / 2;
1980 encoded_image._encodedHeight = kHeight / 2;
1981 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1982 }
asapersson4ee70462016-10-31 04:05:12 -07001983
1984 // Histograms are updated when the statistics_proxy_ is deleted.
1985 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001986 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1987 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1988 EXPECT_METRIC_EQ(
1989 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
1990 0));
asapersson4ee70462016-10-31 04:05:12 -07001991 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01001992 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1993 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001994}
1995
1996TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001997 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1998 // Configure two streams.
1999 VideoEncoderConfig config;
2000 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2001 VideoStream stream1;
2002 stream1.width = kWidth / 2;
2003 stream1.height = kHeight / 2;
2004 VideoStream stream2;
2005 stream2.width = kWidth;
2006 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002007 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002008
2009 const int64_t kMaxEncodedFrameWindowMs = 800;
2010 const int kFps = 20;
2011 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2012 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2013 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2014
2015 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002016 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002017 encoded_image._encodedWidth = kWidth / 2;
2018 encoded_image._encodedHeight = kHeight / 2;
2019 for (int i = 0; i < kMinSamples; ++i) {
2020 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002021 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2022 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002023 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002024 }
asapersson4ee70462016-10-31 04:05:12 -07002025
2026 // Histograms are updated when the statistics_proxy_ is deleted.
2027 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002028 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2029 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2030 EXPECT_METRIC_EQ(
2031 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2032 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002033 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002034 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2035 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2036 EXPECT_METRIC_EQ(
2037 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2038 1));
asapersson4ee70462016-10-31 04:05:12 -07002039}
2040
2041TEST_F(SendStatisticsProxyTest,
2042 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002043 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2044 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002045 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002046 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002047 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002048 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002049
2050 // Histograms are updated when the statistics_proxy_ is deleted.
2051 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002052 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002053 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002054 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2055 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002056}
2057
2058TEST_F(SendStatisticsProxyTest,
2059 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002060 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002061 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002062 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002063 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002064 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002065
2066 // Histograms are updated when the statistics_proxy_ is deleted.
2067 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002068 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002069 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002070 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2071 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002072 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002073 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2074 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002075}
2076
2077TEST_F(SendStatisticsProxyTest,
2078 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2079 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002080 VideoAdaptationCounters cpu_counts;
2081 VideoAdaptationCounters quality_counts;
2082 quality_counts.resolution_adaptations = kDownscales;
2083 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002084 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2085 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002086 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002087 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002088 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002089 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002090 // Histograms are updated when the statistics_proxy_ is deleted.
2091 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002092 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002093 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002094 EXPECT_METRIC_EQ(
2095 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2096 100));
asapersson4ee70462016-10-31 04:05:12 -07002097 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002098 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2099 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2100 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002101 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2102 kDownscales));
2103}
2104
2105TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2106 // Initially false.
2107 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002108
Åsa Perssonaa329e72017-12-15 15:54:44 +01002109 // Configure two streams.
2110 VideoEncoderConfig config;
2111 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002112 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002113 VideoStream stream1;
2114 stream1.width = kWidth / 2;
2115 stream1.height = kHeight / 2;
2116 VideoStream stream2;
2117 stream2.width = kWidth;
2118 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002119 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002120
Åsa Perssonaa329e72017-12-15 15:54:44 +01002121 // One stream encoded.
2122 EncodedImage encoded_image;
2123 encoded_image._encodedWidth = kWidth / 2;
2124 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002125
2126 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002127 VideoAdaptationCounters cpu_counts;
2128 VideoAdaptationCounters quality_counts;
2129 quality_counts.resolution_adaptations = 1;
2130 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2131 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002132 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2133 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002134 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2135 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002136
2137 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002138 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002139 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2140 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002141 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2142 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2143
2144 // Bw disabled one layer.
2145 VideoCodec codec;
2146 codec.numberOfSimulcastStreams = 2;
2147 codec.simulcastStream[0].active = true;
2148 codec.simulcastStream[1].active = true;
2149 VideoBitrateAllocation allocation;
2150 // Some positive bitrate only on the second stream.
2151 allocation.SetBitrate(1, 0, 10000);
2152 allocation.set_bw_limited(true);
2153 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2154 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002155
2156 // Revert for the next test.
2157 allocation.set_bw_limited(false);
2158 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2159 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2160
2161 // Internal encoder scaler reduced resolution.
2162 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2163 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002164}
2165
asapersson66d4b372016-12-19 06:50:53 -08002166TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2167 // Initially zero.
2168 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2169
2170 const int kBitrate = 100000;
2171 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2172 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2173
2174 statistics_proxy_->OnSetEncoderTargetRate(0);
2175 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2176}
2177
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002178TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002179 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002180 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2181 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002182 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002183 // From RtcpStatisticsCallback.
2184 RtcpStatistics rtcp_stats;
2185 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002186 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002187
2188 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002189 uint32_t total = 0;
2190 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002191 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002192 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002193
2194 // From FrameCountObserver.
2195 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002196 FrameCounts frame_counts;
2197 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002198 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002199
2200 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2201 EXPECT_TRUE(stats.substreams.empty());
2202}
2203
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002204TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2205 static const int kEncodedWidth = 123;
2206 static const int kEncodedHeight = 81;
2207 EncodedImage encoded_image;
2208 encoded_image._encodedWidth = kEncodedWidth;
2209 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002210 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002211
kjellander02b3d272016-04-20 05:05:54 -07002212 CodecSpecificInfo codec_info;
2213 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002214
kjellander02b3d272016-04-20 05:05:54 -07002215 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002216 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002217 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002218
2219 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002220 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2221 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2222 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2223 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002224
2225 // Forward almost to timeout, this should not have removed stats.
2226 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2227 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002228 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2229 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002230
2231 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2232 // resolution still times out (no global timeout for all stats).
2233 RtcpStatistics rtcp_statistics;
2234 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2235 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2236
2237 // Report stats for second SSRC to make sure it's not outdated along with the
2238 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002239 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002240
2241 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2242 // reported, but substream 1 should.
2243 fake_clock_.AdvanceTimeMilliseconds(1);
2244 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002245 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2246 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2247 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2248 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002249}
2250
Peter Boström20f3f942015-05-15 11:33:39 +02002251TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2252 static const int kEncodedWidth = 123;
2253 static const int kEncodedHeight = 81;
2254 EncodedImage encoded_image;
2255 encoded_image._encodedWidth = kEncodedWidth;
2256 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002257 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002258
kjellander02b3d272016-04-20 05:05:54 -07002259 CodecSpecificInfo codec_info;
2260 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002261
kjellander02b3d272016-04-20 05:05:54 -07002262 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002263 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002264 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002265
2266 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2267 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2268 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2269 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2270 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2271 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2272}
2273
2274TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002275 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002276 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2277 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2278 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2279
2280 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2281
2282 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002283 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002284 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002285 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002286 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2287 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2288 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2289}
2290
sprang07fb9be2016-02-24 07:55:00 -08002291TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2292 RtcpPacketTypeCounterObserver* proxy =
2293 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2294 RtcpPacketTypeCounter counters;
2295 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2296 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2297 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2298
2299 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2300
2301 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2302 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2303 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2304 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2305 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2306
2307 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2308 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2309
2310 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002311 VideoEncoderConfig config;
2312 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002313 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002314
Ying Wangef3998f2019-12-09 13:06:53 +01002315 EXPECT_METRIC_EQ(
2316 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2317 EXPECT_METRIC_EQ(
2318 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2319 EXPECT_METRIC_EQ(
2320 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2321 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2322 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002323
2324 const int kRate = 60 * 2; // Packets per minute with two streams.
2325
Ying Wangef3998f2019-12-09 13:06:53 +01002326 EXPECT_METRIC_EQ(
2327 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2328 1 * kRate));
2329 EXPECT_METRIC_EQ(
2330 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2331 2 * kRate));
2332 EXPECT_METRIC_EQ(
2333 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2334 3 * kRate));
2335 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002336 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2337 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002338
2339 // New start time but same counter values.
2340 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2341 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2342
2343 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2344
2345 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2346 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2347 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2348 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2349 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2350
2351 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2352 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2353
2354 SetUp(); // Reset stats proxy also causes histograms to be reported.
2355
Ying Wangef3998f2019-12-09 13:06:53 +01002356 EXPECT_METRIC_EQ(
2357 1, metrics::NumSamples(
2358 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2359 EXPECT_METRIC_EQ(1,
2360 metrics::NumSamples(
2361 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2362 EXPECT_METRIC_EQ(1,
2363 metrics::NumSamples(
2364 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2365 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002366 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002367 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2368
Ying Wangef3998f2019-12-09 13:06:53 +01002369 EXPECT_METRIC_EQ(
2370 1,
2371 metrics::NumEvents(
2372 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2373 EXPECT_METRIC_EQ(
2374 1,
2375 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2376 2 * kRate));
2377 EXPECT_METRIC_EQ(
2378 1,
2379 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2380 3 * kRate));
2381 EXPECT_METRIC_EQ(
2382 1, metrics::NumEvents(
2383 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2384 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002385}
2386
Henrik Boströmf45ca372020-03-24 13:30:50 +01002387TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2388 StreamDataCountersCallback* proxy =
2389 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2390 StreamDataCounters counters;
2391 proxy->DataCountersUpdated(counters, kFirstSsrc);
2392 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2393
2394 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2395 VideoSendStream::StreamStats::StreamType::kRtx);
2396 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2397 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2398 VideoSendStream::StreamStats::StreamType::kRtx);
2399 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2400}
2401
asaperssona6a699a2016-11-25 03:52:46 -08002402TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2403 statistics_proxy_.reset(
2404 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2405 VideoEncoderConfig::ContentType::kRealtimeVideo));
2406
2407 StreamDataCountersCallback* proxy =
2408 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2409 StreamDataCounters counters;
2410 proxy->DataCountersUpdated(counters, kFirstSsrc);
2411 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2412
Henrik Boströmf45ca372020-03-24 13:30:50 +01002413 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2414 VideoSendStream::StreamStats::StreamType::kFlexfec);
2415 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2416 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2417 VideoSendStream::StreamStats::StreamType::kFlexfec);
2418 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002419}
2420
2421TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2422 statistics_proxy_.reset(
2423 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2424 VideoEncoderConfig::ContentType::kRealtimeVideo));
2425
2426 StreamDataCountersCallback* proxy =
2427 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002428 StreamDataCounters counters;
2429 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002430
asapersson93e1e232017-02-06 05:18:35 -08002431 const int kMinRequiredPeriodSamples = 8;
2432 const int kPeriodIntervalMs = 2000;
2433 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2434 counters.transmitted.packets += 20;
2435 counters.transmitted.header_bytes += 500;
2436 counters.transmitted.padding_bytes += 1000;
2437 counters.transmitted.payload_bytes += 2000;
2438 counters.retransmitted.packets += 2;
2439 counters.retransmitted.header_bytes += 25;
2440 counters.retransmitted.padding_bytes += 100;
2441 counters.retransmitted.payload_bytes += 250;
2442 counters.fec = counters.retransmitted;
2443 rtx_counters.transmitted = counters.transmitted;
2444 // Advance one interval and update counters.
2445 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2446 proxy->DataCountersUpdated(counters, kFirstSsrc);
2447 proxy->DataCountersUpdated(counters, kSecondSsrc);
2448 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2449 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2450 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2451 }
asaperssona6a699a2016-11-25 03:52:46 -08002452
asaperssona6a699a2016-11-25 03:52:46 -08002453 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002454 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002455 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2456 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002457 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002458 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2459 EXPECT_METRIC_EQ(1,
2460 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002461 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002462 EXPECT_METRIC_EQ(1,
2463 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2464 EXPECT_METRIC_EQ(
2465 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002466 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002467 EXPECT_METRIC_EQ(
2468 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2469 EXPECT_METRIC_EQ(
2470 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002471 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002472 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2473 EXPECT_METRIC_EQ(1,
2474 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002475 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002476 EXPECT_METRIC_EQ(
2477 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2478 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002479 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002480}
2481
Erik Språng22c2b482016-03-01 09:40:42 +01002482TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2483 StreamDataCountersCallback* proxy =
2484 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2485 StreamDataCounters counters;
2486 StreamDataCounters rtx_counters;
2487 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002488
asapersson93e1e232017-02-06 05:18:35 -08002489 const int kMinRequiredPeriodSamples = 8;
2490 const int kPeriodIntervalMs = 2000;
2491 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2492 counters.transmitted.packets += 20;
2493 counters.transmitted.header_bytes += 500;
2494 counters.transmitted.padding_bytes += 1000;
2495 counters.transmitted.payload_bytes += 2000;
2496 counters.retransmitted.packets += 2;
2497 counters.retransmitted.header_bytes += 25;
2498 counters.retransmitted.padding_bytes += 100;
2499 counters.retransmitted.payload_bytes += 250;
2500 counters.fec = counters.retransmitted;
2501 rtx_counters.transmitted = counters.transmitted;
2502 // Advance one interval and update counters.
2503 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2504 proxy->DataCountersUpdated(counters, kFirstSsrc);
2505 proxy->DataCountersUpdated(counters, kSecondSsrc);
2506 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2507 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2508 }
Erik Språng22c2b482016-03-01 09:40:42 +01002509
2510 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002511 VideoEncoderConfig config;
2512 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002513 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002514
asapersson93e1e232017-02-06 05:18:35 -08002515 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002516 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2517 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002518 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002519 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2520 EXPECT_METRIC_EQ(1,
2521 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002522 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002523 EXPECT_METRIC_EQ(1,
2524 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2525 EXPECT_METRIC_EQ(
2526 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002527 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002528 EXPECT_METRIC_EQ(
2529 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2530 EXPECT_METRIC_EQ(
2531 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002532 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002533 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2534 EXPECT_METRIC_EQ(1,
2535 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002536 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002537 EXPECT_METRIC_EQ(
2538 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2539 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002540 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002541
asapersson93e1e232017-02-06 05:18:35 -08002542 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002543 // Double counter values, this should result in the same counts as before but
2544 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002545 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2546 counters.transmitted.packets += 20;
2547 counters.transmitted.header_bytes += 500;
2548 counters.transmitted.padding_bytes += 1000;
2549 counters.transmitted.payload_bytes += 2000;
2550 counters.retransmitted.packets += 2;
2551 counters.retransmitted.header_bytes += 25;
2552 counters.retransmitted.padding_bytes += 100;
2553 counters.retransmitted.payload_bytes += 250;
2554 counters.fec = counters.retransmitted;
2555 rtx_counters.transmitted = counters.transmitted;
2556 // Advance one interval and update counters.
2557 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2558 proxy->DataCountersUpdated(counters, kFirstSsrc);
2559 proxy->DataCountersUpdated(counters, kSecondSsrc);
2560 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2561 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2562 }
Erik Språng22c2b482016-03-01 09:40:42 +01002563
asapersson93e1e232017-02-06 05:18:35 -08002564 // Reset stats proxy also causes histograms to be reported.
2565 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002566
asapersson93e1e232017-02-06 05:18:35 -08002567 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002568 EXPECT_METRIC_EQ(
2569 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2570 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002571 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2572 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002573 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002574 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002575 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2576 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002577 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002578 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2579 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2580 EXPECT_METRIC_EQ(
2581 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2582 12));
asapersson93e1e232017-02-06 05:18:35 -08002583 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002584 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2585 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2586 EXPECT_METRIC_EQ(
2587 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2588 16));
asapersson93e1e232017-02-06 05:18:35 -08002589 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002590 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002591 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002592 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2593 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002594 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002595 EXPECT_METRIC_EQ(
2596 1, metrics::NumSamples(
2597 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2598 EXPECT_METRIC_EQ(
2599 1, metrics::NumEvents(
2600 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002601}
Erik Språng22c2b482016-03-01 09:40:42 +01002602
asapersson93e1e232017-02-06 05:18:35 -08002603TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2604 StreamDataCountersCallback* proxy =
2605 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2606 StreamDataCounters counters;
2607 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002608
asapersson93e1e232017-02-06 05:18:35 -08002609 const int kMinRequiredPeriodSamples = 8;
2610 const int kPeriodIntervalMs = 2000;
2611 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2612 counters.transmitted.packets += 20;
2613 counters.transmitted.header_bytes += 500;
2614 counters.transmitted.payload_bytes += 2000;
2615 counters.fec = counters.retransmitted;
2616 // Advance one interval and update counters.
2617 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2618 proxy->DataCountersUpdated(counters, kFirstSsrc);
2619 }
2620
2621 // RTX enabled. No data sent over RTX.
2622 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002623 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2624 EXPECT_METRIC_EQ(1,
2625 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002626}
2627
2628TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2629 VideoSendStream::Config config(nullptr);
2630 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2631 statistics_proxy_.reset(new SendStatisticsProxy(
2632 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2633
2634 StreamDataCountersCallback* proxy =
2635 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2636 StreamDataCounters counters;
2637
2638 const int kMinRequiredPeriodSamples = 8;
2639 const int kPeriodIntervalMs = 2000;
2640 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2641 counters.transmitted.packets += 20;
2642 counters.transmitted.header_bytes += 500;
2643 counters.transmitted.payload_bytes += 2000;
2644 counters.fec = counters.retransmitted;
2645 // Advance one interval and update counters.
2646 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2647 proxy->DataCountersUpdated(counters, kFirstSsrc);
2648 }
2649
2650 // RTX not enabled.
2651 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002652 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002653}
2654
2655TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2656 StreamDataCountersCallback* proxy =
2657 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2658 StreamDataCounters counters;
2659 StreamDataCounters rtx_counters;
2660
2661 const int kMinRequiredPeriodSamples = 8;
2662 const int kPeriodIntervalMs = 2000;
2663 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2664 counters.transmitted.packets += 20;
2665 counters.transmitted.header_bytes += 500;
2666 counters.transmitted.payload_bytes += 2000;
2667 // Advance one interval and update counters.
2668 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2669 proxy->DataCountersUpdated(counters, kFirstSsrc);
2670 }
2671
2672 // FEC enabled. No FEC data sent.
2673 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002674 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2675 EXPECT_METRIC_EQ(1,
2676 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002677}
2678
2679TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2680 VideoSendStream::Config config(nullptr);
2681 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2682 statistics_proxy_.reset(new SendStatisticsProxy(
2683 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2684
2685 StreamDataCountersCallback* proxy =
2686 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2687 StreamDataCounters counters;
2688
2689 const int kMinRequiredPeriodSamples = 8;
2690 const int kPeriodIntervalMs = 2000;
2691 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2692 counters.transmitted.packets += 20;
2693 counters.transmitted.header_bytes += 500;
2694 counters.transmitted.payload_bytes += 2000;
2695 counters.fec = counters.retransmitted;
2696 // Advance one interval and update counters.
2697 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2698 proxy->DataCountersUpdated(counters, kFirstSsrc);
2699 }
2700
2701 // FEC not enabled.
2702 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002703 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002704}
2705
asapersson8d75ac72017-09-15 06:41:15 -07002706TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002707 const std::string kName = "encoderName";
2708 statistics_proxy_->OnEncoderImplementationChanged(kName);
2709 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002710}
2711
Sergey Silkinbb081a62018-09-04 18:34:22 +02002712TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2713 static const int kEncodedWidth = 123;
2714 static const int kEncodedHeight = 81;
2715 EncodedImage encoded_image;
2716 encoded_image._encodedWidth = kEncodedWidth;
2717 encoded_image._encodedHeight = kEncodedHeight;
2718 encoded_image.SetSpatialIndex(0);
2719
2720 CodecSpecificInfo codec_info;
2721 codec_info.codecType = kVideoCodecVP9;
2722
2723 // For first picture, it is expected that low layer updates resolution.
2724 codec_info.codecSpecific.VP9.end_of_picture = false;
2725 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2726 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2727 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2728 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2729
2730 // Top layer updates resolution.
2731 encoded_image._encodedWidth = kEncodedWidth * 2;
2732 encoded_image._encodedHeight = kEncodedHeight * 2;
2733 codec_info.codecSpecific.VP9.end_of_picture = true;
2734 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2735 stats = statistics_proxy_->GetStats();
2736 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2737 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2738
2739 // Low layer of next frame doesn't update resolution.
2740 encoded_image._encodedWidth = kEncodedWidth;
2741 encoded_image._encodedHeight = kEncodedHeight;
2742 codec_info.codecSpecific.VP9.end_of_picture = false;
2743 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2744 stats = statistics_proxy_->GetStats();
2745 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2746 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2747}
2748
asapersson8d75ac72017-09-15 06:41:15 -07002749class ForcedFallbackTest : public SendStatisticsProxyTest {
2750 public:
2751 explicit ForcedFallbackTest(const std::string& field_trials)
2752 : SendStatisticsProxyTest(field_trials) {
2753 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002754 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002755 encoded_image_._encodedWidth = kWidth;
2756 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002757 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002758 }
2759
2760 ~ForcedFallbackTest() override {}
2761
2762 protected:
2763 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002764 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2765
asapersson8d75ac72017-09-15 06:41:15 -07002766 // First frame is not updating stats, insert initial frame.
2767 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2768 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2769 }
2770 for (int i = 0; i < num_frames; ++i) {
2771 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2772 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2773 }
2774 // Add frame to include last time interval.
2775 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2776 }
2777
2778 EncodedImage encoded_image_;
2779 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002780 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002781 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2782 const int kFrameIntervalMs = 1000;
2783 const int kMinFrames = 20; // Min run time 20 sec.
2784};
2785
2786class ForcedFallbackDisabled : public ForcedFallbackTest {
2787 public:
2788 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002789 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2790 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002791};
2792
2793class ForcedFallbackEnabled : public ForcedFallbackTest {
2794 public:
2795 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002796 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2797 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002798};
2799
2800TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2801 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2802 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002803 EXPECT_METRIC_EQ(0,
2804 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2805 EXPECT_METRIC_EQ(
2806 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002807}
2808
2809TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2810 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002811 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002812 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002813 EXPECT_METRIC_EQ(1,
2814 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2815 EXPECT_METRIC_EQ(
2816 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2817 EXPECT_METRIC_EQ(
2818 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2819 EXPECT_METRIC_EQ(
2820 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002821}
2822
2823TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2824 codec_info_.codecType = kVideoCodecVP9;
2825 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2826 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002827 EXPECT_METRIC_EQ(0,
2828 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2829 EXPECT_METRIC_EQ(
2830 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002831}
2832
2833TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2834 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2835 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2836 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002837 EXPECT_METRIC_EQ(0,
2838 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2839 EXPECT_METRIC_EQ(
2840 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002841}
2842
2843TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002844 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002845 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2846 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002847 EXPECT_METRIC_EQ(0,
2848 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2849 EXPECT_METRIC_EQ(
2850 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002851}
2852
2853TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2854 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2855 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002856 EXPECT_METRIC_EQ(0,
2857 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2858 EXPECT_METRIC_EQ(
2859 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002860}
2861
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002862TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2863 InsertEncodedFrames(1, kFrameIntervalMs);
2864 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2865}
2866
2867TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2868 InsertEncodedFrames(1, kFrameIntervalMs);
2869 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2870}
2871
2872TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002873 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002874 InsertEncodedFrames(1, kFrameIntervalMs);
2875 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2876}
2877
2878TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2879 encoded_image_._encodedWidth = kWidth + 1;
2880 InsertEncodedFrames(1, kFrameIntervalMs);
2881 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2882}
2883
2884TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002885 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002886 InsertEncodedFrames(1, kFrameIntervalMs);
2887 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2888}
2889
2890TEST_F(ForcedFallbackDisabled,
2891 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2892 encoded_image_._encodedWidth = kWidth + 1;
2893 statistics_proxy_->OnMinPixelLimitReached();
2894 InsertEncodedFrames(1, kFrameIntervalMs);
2895 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2896}
2897
asapersson8d75ac72017-09-15 06:41:15 -07002898TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2899 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002900 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002901 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002902 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002903 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002904 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002905 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002906
2907 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002908 EXPECT_METRIC_EQ(1,
2909 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2910 EXPECT_METRIC_EQ(
2911 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2912 EXPECT_METRIC_EQ(
2913 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2914 EXPECT_METRIC_EQ(
2915 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002916}
2917
2918TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2919 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2920 const int kMaxFrameDiffMs = 2000;
2921
2922 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2923 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002924 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002925 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002926 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002927 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002928 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002929 InsertEncodedFrames(20, 1000);
2930 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2931 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002932 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002933 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002934 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002935 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002936 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002937 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002938 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002939
2940 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002941 EXPECT_METRIC_EQ(1,
2942 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2943 EXPECT_METRIC_EQ(
2944 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2945 EXPECT_METRIC_EQ(
2946 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2947 EXPECT_METRIC_EQ(
2948 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002949}
2950
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002951TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2952 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002953 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002954 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2955
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002956 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002957 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002958 EXPECT_METRIC_EQ(0,
2959 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2960 EXPECT_METRIC_EQ(
2961 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002962}
2963
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002964TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2965 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002966 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002967 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2968
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002969 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002970 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002971 EXPECT_METRIC_EQ(1,
2972 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2973 EXPECT_METRIC_EQ(
2974 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002975}
2976
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002977} // namespace webrtc