blob: 47ce644ddf9035a1feca032213d3f6756d5aa1ed [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 Shrubsolecc62b162019-09-09 11:26:45 +020021#include "api/video/video_bitrate_allocation.h"
22#include "api/video/video_codec_type.h"
23#include "api/video_codecs/video_codec.h"
24#include "api/video_codecs/video_encoder_config.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020025#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070027#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000029
30namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070031namespace {
32const uint32_t kFirstSsrc = 17;
33const uint32_t kSecondSsrc = 42;
34const uint32_t kFirstRtxSsrc = 18;
35const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080036const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080037const int kFpsPeriodicIntervalMs = 2000;
38const int kWidth = 640;
39const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070040const int kQpIdx0 = 21;
41const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010042const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080043const CodecSpecificInfo kDefaultCodecInfo = []() {
44 CodecSpecificInfo codec_info;
45 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080046 return codec_info;
47}();
asapersson5265fed2016-04-18 02:58:47 -070048} // namespace
sprang07fb9be2016-02-24 07:55:00 -080049
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000050class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000051 public:
asapersson8d75ac72017-09-15 06:41:15 -070052 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
53 explicit SendStatisticsProxyTest(const std::string& field_trials)
54 : override_field_trials_(field_trials),
55 fake_clock_(1234),
56 config_(GetTestConfig()),
57 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070058 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000059 virtual ~SendStatisticsProxyTest() {}
60
61 protected:
62 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070063 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080064 statistics_proxy_.reset(new SendStatisticsProxy(
65 &fake_clock_, GetTestConfig(),
66 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000067 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070068 for (const auto& ssrc : config_.rtp.ssrcs)
69 expected_.substreams[ssrc].is_rtx = false;
70 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
71 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000072 }
73
74 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070075 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080076 config.rtp.ssrcs.push_back(kFirstSsrc);
77 config.rtp.ssrcs.push_back(kSecondSsrc);
78 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
79 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070080 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000081 return config;
82 }
83
asaperssona6a699a2016-11-25 03:52:46 -080084 VideoSendStream::Config GetTestConfigWithFlexFec() {
85 VideoSendStream::Config config(nullptr);
86 config.rtp.ssrcs.push_back(kFirstSsrc);
87 config.rtp.ssrcs.push_back(kSecondSsrc);
88 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
89 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080090 config.rtp.flexfec.payload_type = 50;
91 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080092 return config;
93 }
94
95 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
96 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
97 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
98 stats.substreams.find(ssrc);
99 EXPECT_NE(it, stats.substreams.end());
100 return it->second;
101 }
102
asapersson66d4b372016-12-19 06:50:53 -0800103 void UpdateDataCounters(uint32_t ssrc) {
104 StreamDataCountersCallback* proxy =
105 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
106 StreamDataCounters counters;
107 proxy->DataCountersUpdated(counters, ssrc);
108 }
109
sprang@webrtc.org09315702014-02-07 12:06:29 +0000110 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000111 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
112 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000113 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000114 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000115
116 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000117 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000118 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000119 it != one.substreams.end(); ++it) {
120 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
121 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000122 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000123 const VideoSendStream::StreamStats& a = it->second;
124 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000125
asapersson2e5cfcd2016-08-11 08:41:18 -0700126 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000127 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
128 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000129 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000130 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
131 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000133 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
134 b.rtp_stats.transmitted.payload_bytes);
135 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
136 b.rtp_stats.transmitted.header_bytes);
137 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
138 b.rtp_stats.transmitted.padding_bytes);
139 EXPECT_EQ(a.rtp_stats.transmitted.packets,
140 b.rtp_stats.transmitted.packets);
141 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
142 b.rtp_stats.retransmitted.packets);
143 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000144
145 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700146 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
147 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
148 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
150 }
151 }
152
asapersson8d75ac72017-09-15 06:41:15 -0700153 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000154 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800155 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156 VideoSendStream::Config config_;
157 int avg_delay_ms_;
158 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000159 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000160 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
161 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000162};
163
164TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
165 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700166 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000167 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000168
169 // Add statistics with some arbitrary, but unique, numbers.
170 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700171 ssrc_stats.rtcp_stats.packets_lost = offset;
172 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
174 ssrc_stats.rtcp_stats.jitter = offset + 3;
175 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
176 }
asapersson35151f32016-05-02 23:44:01 -0700177 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000178 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000179
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000180 // Add statistics with some arbitrary, but unique, numbers.
181 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700182 ssrc_stats.rtcp_stats.packets_lost = offset;
183 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000184 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
185 ssrc_stats.rtcp_stats.jitter = offset + 3;
186 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
187 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000188 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000189 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000190}
191
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000192TEST_F(SendStatisticsProxyTest, Suspended) {
193 // Verify that the value is false by default.
194 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
195
196 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200197 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000198 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
199
200 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200201 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000202 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
203}
204
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000205TEST_F(SendStatisticsProxyTest, FrameCounts) {
206 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700207 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000208 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000209 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
210 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000211 FrameCounts frame_counts;
212 frame_counts.key_frames = offset;
213 frame_counts.delta_frames = offset + 1;
214 stats.frame_counts = frame_counts;
215 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000216 }
asapersson35151f32016-05-02 23:44:01 -0700217 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000218 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000219 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
220 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000221 FrameCounts frame_counts;
222 frame_counts.key_frames = offset;
223 frame_counts.delta_frames = offset + 1;
224 stats.frame_counts = frame_counts;
225 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000226 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000227
228 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000229 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000230}
231
232TEST_F(SendStatisticsProxyTest, DataCounters) {
233 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700234 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000235 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
236 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000237 size_t offset = ssrc * sizeof(StreamDataCounters);
238 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000239 counters.transmitted.payload_bytes = offset;
240 counters.transmitted.header_bytes = offset + 1;
241 counters.fec.packets = offset_uint32 + 2;
242 counters.transmitted.padding_bytes = offset + 3;
243 counters.retransmitted.packets = offset_uint32 + 4;
244 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000245 callback->DataCountersUpdated(counters, ssrc);
246 }
asapersson35151f32016-05-02 23:44:01 -0700247 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000248 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
249 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000250 size_t offset = ssrc * sizeof(StreamDataCounters);
251 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000252 counters.transmitted.payload_bytes = offset;
253 counters.transmitted.header_bytes = offset + 1;
254 counters.fec.packets = offset_uint32 + 2;
255 counters.transmitted.padding_bytes = offset + 3;
256 counters.retransmitted.packets = offset_uint32 + 4;
257 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000258 callback->DataCountersUpdated(counters, ssrc);
259 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000260
261 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000262 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000263}
264
265TEST_F(SendStatisticsProxyTest, Bitrate) {
266 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700267 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700268 uint32_t total;
269 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000270 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700271 total = ssrc;
272 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000273 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700274 expected_.substreams[ssrc].total_bitrate_bps = total;
275 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000276 }
asapersson35151f32016-05-02 23:44:01 -0700277 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700278 uint32_t total;
279 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700281 total = ssrc;
282 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000283 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700284 expected_.substreams[ssrc].total_bitrate_bps = total;
285 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000286 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000287
288 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000289 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000290}
291
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000292TEST_F(SendStatisticsProxyTest, SendSideDelay) {
293 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700294 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000295 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
296 // stream.
297 int avg_delay_ms = ssrc;
298 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200299 uint64_t total_packet_send_delay_ms = ssrc + 2;
300 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
301 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000302 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
303 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200304 expected_.substreams[ssrc].total_packet_send_delay_ms =
305 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000306 }
asapersson35151f32016-05-02 23:44:01 -0700307 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000308 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
309 // stream.
310 int avg_delay_ms = ssrc;
311 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200312 uint64_t total_packet_send_delay_ms = ssrc + 2;
313 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
314 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000315 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
316 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200317 expected_.substreams[ssrc].total_packet_send_delay_ms =
318 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000319 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000320 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000321 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000322}
323
Peter Boströme4499152016-02-05 11:13:28 +0100324TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800325 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200326 int encode_usage_percent = 80;
327 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
328 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800329
330 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
331 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200332 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800333}
334
Henrik Boström5684af52019-04-02 15:05:21 +0200335TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
336 const int kEncodeUsagePercent = 0; // Don't care for this test.
337 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
338 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
339 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
340 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
341 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
342}
343
sakal43536c32016-10-24 01:46:43 -0700344TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
345 EncodedImage encoded_image;
346 CodecSpecificInfo codec_info;
347 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
348 for (uint32_t i = 1; i <= 3; ++i) {
349 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
350 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
351 }
352}
353
sakal87da4042016-10-31 06:53:47 -0700354TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
355 EncodedImage encoded_image;
356 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200357 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700358 encoded_image.qp_ = 3;
359 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100360 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700361 encoded_image.qp_ = 127;
362 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100363 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700364}
365
366TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
367 EncodedImage encoded_image;
368 CodecSpecificInfo codec_info;
369 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200370 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700371 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200372 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700373}
374
Henrik Boström23aff9b2019-05-20 15:15:38 +0200375TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
376 const uint32_t kTargetBytesPerSecond = 100000;
377 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
378 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
379
380 EncodedImage encoded_image;
381 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
382 // On the first frame we don't know the frame rate yet, calculation yields
383 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
384 // increment by a full |kTargetBytesPerSecond|.
385 EXPECT_EQ(kTargetBytesPerSecond,
386 statistics_proxy_->GetStats().total_encoded_bytes_target);
387}
388
389TEST_F(SendStatisticsProxyTest,
390 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
391 const uint32_t kTargetBytesPerSecond = 100000;
392 const int kInterframeDelayMs = 100;
393
394 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
395 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
396 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
397 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
398 // this test can stop relying on rtc::ScopedFakeClock.
399 rtc::ScopedFakeClock fake_global_clock;
400 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
401
402 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
403 EncodedImage encoded_image;
404
405 // First frame
406 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
407 uint64_t first_total_encoded_bytes_target =
408 statistics_proxy_->GetStats().total_encoded_bytes_target;
409 // Second frame
410 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
411 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
412 encoded_image.SetTimestamp(encoded_image.Timestamp() +
413 90 * kInterframeDelayMs);
414 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
415
416 auto stats = statistics_proxy_->GetStats();
417 // By the time the second frame arrives, one frame has previously arrived
418 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
419 // the second frame's arrival should be 10 FPS.
420 uint64_t delta_encoded_bytes_target =
421 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
422 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
423}
424
asapersson09f05612017-05-15 23:40:18 -0700425TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200426 SendStatisticsProxy::AdaptationSteps cpu_counts;
427 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700428 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700429 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200430 cpu_counts.num_framerate_reductions = 1;
431 cpu_counts.num_resolution_reductions = 0;
432 statistics_proxy_->OnAdaptationChanged(
433 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
434 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700435 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700436 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200437 cpu_counts.num_framerate_reductions = 0;
438 cpu_counts.num_resolution_reductions = 1;
439 statistics_proxy_->OnAdaptationChanged(
440 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
441 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700442 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700443 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200444 cpu_counts.num_framerate_reductions = 1;
445 cpu_counts.num_resolution_reductions = absl::nullopt;
446 statistics_proxy_->OnAdaptationChanged(
447 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
448 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700449 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700450 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200451 cpu_counts.num_framerate_reductions = absl::nullopt;
452 cpu_counts.num_resolution_reductions = absl::nullopt;
453 statistics_proxy_->OnAdaptationChanged(
454 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
455 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700456 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
457 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
458}
459
460TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200461 SendStatisticsProxy::AdaptationSteps cpu_counts;
462 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700463 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
464 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200465 quality_counts.num_framerate_reductions = 1;
466 quality_counts.num_resolution_reductions = 0;
467 statistics_proxy_->OnAdaptationChanged(
468 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
469 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700470 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
471 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200472 quality_counts.num_framerate_reductions = 0;
473 quality_counts.num_resolution_reductions = 1;
474 statistics_proxy_->OnAdaptationChanged(
475 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
476 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700477 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
478 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200479 quality_counts.num_framerate_reductions = 1;
480 quality_counts.num_resolution_reductions = absl::nullopt;
481 statistics_proxy_->OnAdaptationChanged(
482 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
483 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700484 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
485 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200486 quality_counts.num_framerate_reductions = absl::nullopt;
487 quality_counts.num_resolution_reductions = absl::nullopt;
488 statistics_proxy_->OnAdaptationChanged(
489 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
490 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700491 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
492 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
493}
494
495TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200496 SendStatisticsProxy::AdaptationSteps cpu_counts;
497 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700498 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
499
Niels Möller213618e2018-07-24 09:29:58 +0200500 cpu_counts.num_resolution_reductions = 1;
501 statistics_proxy_->OnAdaptationChanged(
502 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
503 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700504 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700505 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
506 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
507
Niels Möller213618e2018-07-24 09:29:58 +0200508 cpu_counts.num_resolution_reductions = 2;
509 statistics_proxy_->OnAdaptationChanged(
510 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
511 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700512 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
513 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700514 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700515 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700516}
517
asapersson09f05612017-05-15 23:40:18 -0700518TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200519 SendStatisticsProxy::AdaptationSteps cpu_counts;
520 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700521 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
522
Niels Möller213618e2018-07-24 09:29:58 +0200523 quality_counts.num_framerate_reductions = 1;
524 statistics_proxy_->OnAdaptationChanged(
525 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
526 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700527 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
528 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700529 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
530
Niels Möller213618e2018-07-24 09:29:58 +0200531 quality_counts.num_framerate_reductions = 0;
532 statistics_proxy_->OnAdaptationChanged(
533 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
534 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700535 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700536 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700537 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
538 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700539}
540
asapersson09f05612017-05-15 23:40:18 -0700541TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700542 // First RTP packet sent.
543 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700544 // Min runtime has passed.
545 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
546 statistics_proxy_.reset();
547 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
548 EXPECT_EQ(0,
549 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
550}
551
552TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700553 // First RTP packet sent.
554 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700555 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200556 SendStatisticsProxy::AdaptationSteps cpu_counts;
557 SendStatisticsProxy::AdaptationSteps quality_counts;
558 statistics_proxy_->OnAdaptationChanged(
559 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
560 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700561 // Min runtime has not passed.
562 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
563 statistics_proxy_.reset();
564 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
565 EXPECT_EQ(0,
566 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
567}
568
asapersson09f05612017-05-15 23:40:18 -0700569TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700570 // First RTP packet sent.
571 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700572 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200573 SendStatisticsProxy::AdaptationSteps cpu_counts;
574 SendStatisticsProxy::AdaptationSteps quality_counts;
575 statistics_proxy_->OnAdaptationChanged(
576 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
577 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700578 // Min runtime has passed.
579 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
580 statistics_proxy_.reset();
581 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
582 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700583 EXPECT_EQ(1,
584 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
585 EXPECT_EQ(
586 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
587}
588
589TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700590 // First RTP packet sent.
591 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700592 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200593 SendStatisticsProxy::AdaptationSteps cpu_counts;
594 SendStatisticsProxy::AdaptationSteps quality_counts;
595 statistics_proxy_->OnAdaptationChanged(
596 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
597 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700598 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200599 statistics_proxy_->OnAdaptationChanged(
600 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
601 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700602 fake_clock_.AdvanceTimeMilliseconds(10000);
603 statistics_proxy_.reset();
604 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
605 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
606}
607
Åsa Persson875841d2018-01-08 08:49:53 +0100608TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
609 // First RTP packet sent.
610 UpdateDataCounters(kFirstSsrc);
611 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200612 SendStatisticsProxy::AdaptationSteps cpu_counts;
613 SendStatisticsProxy::AdaptationSteps quality_counts;
614 statistics_proxy_->OnAdaptationChanged(
615 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
616 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100617 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200618 statistics_proxy_->OnAdaptationChanged(
619 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
620 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100621 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
622 fake_clock_.AdvanceTimeMilliseconds(10000);
623 statistics_proxy_.reset();
624 EXPECT_EQ(1,
625 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
626 EXPECT_EQ(
627 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
628}
629
630TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
631 // First RTP packet sent.
632 UpdateDataCounters(kFirstSsrc);
633 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200634 SendStatisticsProxy::AdaptationSteps cpu_counts;
635 SendStatisticsProxy::AdaptationSteps quality_counts;
636 statistics_proxy_->OnAdaptationChanged(
637 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
638 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100639 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200640 quality_counts.num_resolution_reductions = 1;
641 statistics_proxy_->OnAdaptationChanged(
642 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
643 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100644 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200645 quality_counts.num_resolution_reductions = 2;
646 statistics_proxy_->OnAdaptationChanged(
647 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
648 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100649 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200650 quality_counts.num_resolution_reductions = 3;
651 statistics_proxy_->OnAdaptationChanged(
652 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
653 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100654 fake_clock_.AdvanceTimeMilliseconds(10000);
655 statistics_proxy_.reset();
656 EXPECT_EQ(1,
657 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
658 EXPECT_EQ(
659 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
660}
661
662TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
663 // First RTP packet sent.
664 UpdateDataCounters(kFirstSsrc);
665 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200666 SendStatisticsProxy::AdaptationSteps cpu_counts;
667 SendStatisticsProxy::AdaptationSteps quality_counts;
668 statistics_proxy_->OnAdaptationChanged(
669 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
670 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100671 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200672 statistics_proxy_->OnAdaptationChanged(
673 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
674 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100675 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
676 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
677 fake_clock_.AdvanceTimeMilliseconds(10000);
678 statistics_proxy_.reset();
679 EXPECT_EQ(1,
680 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
681 EXPECT_EQ(
682 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
683}
684
685TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
686 // First RTP packet sent.
687 UpdateDataCounters(kFirstSsrc);
688 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200689 SendStatisticsProxy::AdaptationSteps cpu_counts;
690 SendStatisticsProxy::AdaptationSteps quality_counts;
691 statistics_proxy_->OnAdaptationChanged(
692 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
693 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100694 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200695 quality_counts.num_resolution_reductions = 1;
696 statistics_proxy_->OnAdaptationChanged(
697 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
698 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100699 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200700 quality_counts.num_resolution_reductions = 2;
701 statistics_proxy_->OnAdaptationChanged(
702 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
703 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100704 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200705 quality_counts.num_resolution_reductions = 3;
706 statistics_proxy_->OnAdaptationChanged(
707 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
708 quality_counts);
709 quality_counts.num_framerate_reductions = 1;
710 statistics_proxy_->OnAdaptationChanged(
711 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
712 quality_counts);
713 quality_counts.num_framerate_reductions = 0;
714 statistics_proxy_->OnAdaptationChanged(
715 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
716 quality_counts);
717 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
718 statistics_proxy_->OnAdaptationChanged(
719 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
720 quality_counts);
721 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
722 statistics_proxy_->OnAdaptationChanged(
723 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
724 quality_counts);
725 quality_counts.num_resolution_reductions = 0;
726 statistics_proxy_->OnAdaptationChanged(
727 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
728 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100729
730 fake_clock_.AdvanceTimeMilliseconds(10000);
731 statistics_proxy_.reset();
732 EXPECT_EQ(1,
733 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
734 EXPECT_EQ(
735 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
736}
737
asapersson6eca98b2017-04-04 23:40:50 -0700738TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700739 // First RTP packet sent.
740 UpdateDataCounters(kFirstSsrc);
741
asapersson09f05612017-05-15 23:40:18 -0700742 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200743 SendStatisticsProxy::AdaptationSteps cpu_counts;
744 SendStatisticsProxy::AdaptationSteps quality_counts;
745 quality_counts.num_framerate_reductions = absl::nullopt;
746 quality_counts.num_resolution_reductions = absl::nullopt;
747 statistics_proxy_->OnAdaptationChanged(
748 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
749 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700750 fake_clock_.AdvanceTimeMilliseconds(10000);
751
asapersson09f05612017-05-15 23:40:18 -0700752 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700753 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200754 quality_counts.num_framerate_reductions = 0;
755 statistics_proxy_->OnAdaptationChanged(
756 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
757 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700758 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200759 statistics_proxy_->OnAdaptationChanged(
760 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
761 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700762 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200763 statistics_proxy_->OnAdaptationChanged(
764 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
765 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700766 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200767 statistics_proxy_->OnAdaptationChanged(
768 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
769 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700770
asapersson09f05612017-05-15 23:40:18 -0700771 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200772 quality_counts.num_framerate_reductions = absl::nullopt;
773 statistics_proxy_->OnAdaptationChanged(
774 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
775 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700776 fake_clock_.AdvanceTimeMilliseconds(30000);
777
asapersson09f05612017-05-15 23:40:18 -0700778 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700779 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200780 quality_counts.num_resolution_reductions = 0;
781 statistics_proxy_->OnAdaptationChanged(
782 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
783 quality_counts);
784 statistics_proxy_->OnAdaptationChanged(
785 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
786 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700787 fake_clock_.AdvanceTimeMilliseconds(10000);
788
asapersson09f05612017-05-15 23:40:18 -0700789 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200790 quality_counts.num_resolution_reductions = absl::nullopt;
791 statistics_proxy_->OnAdaptationChanged(
792 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
793 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700794 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200795 statistics_proxy_->OnAdaptationChanged(
796 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
797 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700798 fake_clock_.AdvanceTimeMilliseconds(20000);
799
asapersson0944a802017-04-07 00:57:58 -0700800 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700801 statistics_proxy_.reset();
802 EXPECT_EQ(1,
803 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
804 EXPECT_EQ(
805 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
806}
807
asapersson0944a802017-04-07 00:57:58 -0700808TEST_F(SendStatisticsProxyTest,
809 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
810 // First RTP packet sent.
811 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700812
asapersson0944a802017-04-07 00:57:58 -0700813 // Suspend and resume video.
814 statistics_proxy_->OnSuspendChange(true);
815 fake_clock_.AdvanceTimeMilliseconds(5000);
816 statistics_proxy_->OnSuspendChange(false);
817
818 // Min runtime has passed but scaling not enabled.
819 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
820 statistics_proxy_.reset();
821 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
822 EXPECT_EQ(0,
823 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
824}
825
826TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
827 // First RTP packet sent.
828 UpdateDataCounters(kFirstSsrc);
829
asapersson09f05612017-05-15 23:40:18 -0700830 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200831 SendStatisticsProxy::AdaptationSteps cpu_counts;
832 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700833 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200834 statistics_proxy_->OnAdaptationChanged(
835 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
836 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700837 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200838 statistics_proxy_->OnAdaptationChanged(
839 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
840 quality_counts);
841 statistics_proxy_->OnAdaptationChanged(
842 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
843 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700844
845 // Suspend and resume video.
846 statistics_proxy_->OnSuspendChange(true);
847 fake_clock_.AdvanceTimeMilliseconds(30000);
848 statistics_proxy_->OnSuspendChange(false);
849
850 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200851 statistics_proxy_->OnAdaptationChanged(
852 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
853 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700854 fake_clock_.AdvanceTimeMilliseconds(10000);
855
856 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
857 statistics_proxy_.reset();
858 EXPECT_EQ(1,
859 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
860 EXPECT_EQ(
861 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
862}
863
864TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
865 // First RTP packet sent.
866 UpdateDataCounters(kFirstSsrc);
867
868 // Video not suspended.
869 statistics_proxy_->OnSuspendChange(false);
870 fake_clock_.AdvanceTimeMilliseconds(30000);
871
asapersson09f05612017-05-15 23:40:18 -0700872 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200873 SendStatisticsProxy::AdaptationSteps cpu_counts;
874 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700875 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200876 statistics_proxy_->OnAdaptationChanged(
877 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
878 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700879 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200880 statistics_proxy_->OnAdaptationChanged(
881 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
882 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700883
884 // Video not suspended, stats time already started.
885 statistics_proxy_->OnSuspendChange(false);
886 fake_clock_.AdvanceTimeMilliseconds(10000);
887
asapersson09f05612017-05-15 23:40:18 -0700888 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200889 cpu_counts.num_framerate_reductions = absl::nullopt;
890 cpu_counts.num_resolution_reductions = absl::nullopt;
891 statistics_proxy_->OnAdaptationChanged(
892 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
893 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700894 fake_clock_.AdvanceTimeMilliseconds(30000);
895
896 // Suspend and resume video, stats time not started when scaling not enabled.
897 statistics_proxy_->OnSuspendChange(true);
898 fake_clock_.AdvanceTimeMilliseconds(30000);
899 statistics_proxy_->OnSuspendChange(false);
900 fake_clock_.AdvanceTimeMilliseconds(30000);
901
asapersson09f05612017-05-15 23:40:18 -0700902 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700903 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200904 cpu_counts.num_framerate_reductions = 0;
905 cpu_counts.num_resolution_reductions = 0;
906 statistics_proxy_->OnAdaptationChanged(
907 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
908 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700909 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200910 statistics_proxy_->OnAdaptationChanged(
911 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
912 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700913
914 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
915 statistics_proxy_.reset();
916 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
917 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
918}
919
920TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
921 // First RTP packet sent.
922 UpdateDataCounters(kFirstSsrc);
923
924 // Video suspended.
925 statistics_proxy_->OnSuspendChange(true);
926
asapersson09f05612017-05-15 23:40:18 -0700927 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200928 SendStatisticsProxy::AdaptationSteps cpu_counts;
929 SendStatisticsProxy::AdaptationSteps quality_counts;
930 statistics_proxy_->OnAdaptationChanged(
931 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
932 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700933 fake_clock_.AdvanceTimeMilliseconds(10000);
934
935 // Resume video, stats time started.
936 // Adapt changes: 1, elapsed time: 10 sec.
937 statistics_proxy_->OnSuspendChange(false);
938 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200939 statistics_proxy_->OnAdaptationChanged(
940 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
941 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700942
943 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
944 statistics_proxy_.reset();
945 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
946 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
947}
948
949TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700950 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700951 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200952 SendStatisticsProxy::AdaptationSteps cpu_counts;
953 SendStatisticsProxy::AdaptationSteps quality_counts;
954 statistics_proxy_->OnAdaptationChanged(
955 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
956 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700957 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700958 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700959
asapersson0944a802017-04-07 00:57:58 -0700960 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700961 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200962 statistics_proxy_->OnAdaptationChanged(
963 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
964 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700965 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700966
asapersson0944a802017-04-07 00:57:58 -0700967 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700968 statistics_proxy_.reset();
969 EXPECT_EQ(1,
970 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
971 EXPECT_EQ(
972 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
973}
974
975TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700976 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200977 SendStatisticsProxy::AdaptationSteps cpu_counts;
978 SendStatisticsProxy::AdaptationSteps quality_counts;
979 statistics_proxy_->OnAdaptationChanged(
980 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
981 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700982 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200983 cpu_counts.num_framerate_reductions = absl::nullopt;
984 cpu_counts.num_resolution_reductions = absl::nullopt;
985 statistics_proxy_->OnAdaptationChanged(
986 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
987 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700988
989 // Send first packet, scaling disabled.
990 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700991 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700992 fake_clock_.AdvanceTimeMilliseconds(60000);
993
asapersson09f05612017-05-15 23:40:18 -0700994 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200995 cpu_counts.num_resolution_reductions = 0;
996 statistics_proxy_->OnAdaptationChanged(
997 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
998 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700999 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001000 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001001
asapersson0944a802017-04-07 00:57:58 -07001002 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001003 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001004 statistics_proxy_->OnAdaptationChanged(
1005 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1006 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001007
asapersson0944a802017-04-07 00:57:58 -07001008 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001009 statistics_proxy_.reset();
1010 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1011 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
1012}
1013
1014TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001015 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001016 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001017 SendStatisticsProxy::AdaptationSteps cpu_counts;
1018 SendStatisticsProxy::AdaptationSteps quality_counts;
1019 quality_counts.num_framerate_reductions = absl::nullopt;
1020 quality_counts.num_resolution_reductions = absl::nullopt;
1021 statistics_proxy_->OnAdaptationChanged(
1022 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1023 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001024
asapersson0944a802017-04-07 00:57:58 -07001025 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001026 statistics_proxy_->OnAdaptationChanged(
1027 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1028 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001029 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +02001030 statistics_proxy_->OnAdaptationChanged(
1031 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1032 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001033 fake_clock_.AdvanceTimeMilliseconds(9000);
1034
1035 // Switch content type, real-time stats should be updated.
1036 VideoEncoderConfig config;
1037 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001038 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -07001039 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1040 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1041 EXPECT_EQ(0,
1042 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1043
asapersson0944a802017-04-07 00:57:58 -07001044 // First RTP packet sent, scaling enabled.
1045 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001046 statistics_proxy_->OnAdaptationChanged(
1047 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1048 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001049
asapersson0944a802017-04-07 00:57:58 -07001050 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001051 statistics_proxy_->OnAdaptationChanged(
1052 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1053 quality_counts);
1054 statistics_proxy_->OnAdaptationChanged(
1055 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1056 quality_counts);
1057 statistics_proxy_->OnAdaptationChanged(
1058 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1059 quality_counts);
1060 statistics_proxy_->OnAdaptationChanged(
1061 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1062 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001063 fake_clock_.AdvanceTimeMilliseconds(120000);
1064
1065 statistics_proxy_.reset();
1066 EXPECT_EQ(1, metrics::NumSamples(
1067 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1068 EXPECT_EQ(1, metrics::NumEvents(
1069 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1070 EXPECT_EQ(0, metrics::NumSamples(
1071 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
1072}
1073
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001074TEST_F(SendStatisticsProxyTest,
1075 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
1076 SendStatisticsProxy::AdaptationSteps cpu_counts;
1077 SendStatisticsProxy::AdaptationSteps quality_counts;
1078
1079 cpu_counts.num_resolution_reductions = 1;
1080
1081 statistics_proxy_->OnAdaptationChanged(
1082 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1083 quality_counts);
1084
1085 EXPECT_EQ(QualityLimitationReason::kCpu,
1086 statistics_proxy_->GetStats().quality_limitation_reason);
1087}
1088
1089TEST_F(SendStatisticsProxyTest,
1090 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
1091 SendStatisticsProxy::AdaptationSteps cpu_counts;
1092 SendStatisticsProxy::AdaptationSteps quality_counts;
1093
1094 cpu_counts.num_framerate_reductions = 1;
1095
1096 statistics_proxy_->OnAdaptationChanged(
1097 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1098 quality_counts);
1099
1100 EXPECT_EQ(QualityLimitationReason::kCpu,
1101 statistics_proxy_->GetStats().quality_limitation_reason);
1102}
1103
1104TEST_F(SendStatisticsProxyTest,
1105 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
1106 SendStatisticsProxy::AdaptationSteps cpu_counts;
1107 SendStatisticsProxy::AdaptationSteps quality_counts;
1108
1109 quality_counts.num_resolution_reductions = 1;
1110
1111 statistics_proxy_->OnAdaptationChanged(
1112 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1113 quality_counts);
1114
1115 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1116 statistics_proxy_->GetStats().quality_limitation_reason);
1117}
1118
1119TEST_F(SendStatisticsProxyTest,
1120 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
1121 SendStatisticsProxy::AdaptationSteps cpu_counts;
1122 SendStatisticsProxy::AdaptationSteps quality_counts;
1123
1124 quality_counts.num_framerate_reductions = 1;
1125
1126 statistics_proxy_->OnAdaptationChanged(
1127 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1128 quality_counts);
1129
1130 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1131 statistics_proxy_->GetStats().quality_limitation_reason);
1132}
1133
1134TEST_F(SendStatisticsProxyTest,
1135 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
1136 SendStatisticsProxy::AdaptationSteps cpu_counts;
1137 SendStatisticsProxy::AdaptationSteps quality_counts;
1138
1139 cpu_counts.num_resolution_reductions = 1;
1140 quality_counts.num_resolution_reductions = 1;
1141
1142 // Even if the last adaptation reason is kCpu, if the counters indicate being
1143 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
1144 statistics_proxy_->OnAdaptationChanged(
1145 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1146 quality_counts);
1147
1148 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1149 statistics_proxy_->GetStats().quality_limitation_reason);
1150}
1151
1152TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
1153 SendStatisticsProxy::AdaptationSteps cpu_counts;
1154 SendStatisticsProxy::AdaptationSteps quality_counts;
1155
1156 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1157 // due to "none" being the default value.
1158 cpu_counts.num_resolution_reductions = 1;
1159 statistics_proxy_->OnAdaptationChanged(
1160 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1161 quality_counts);
1162 // Go back to not being limited.
1163 cpu_counts.num_resolution_reductions = 0;
1164 statistics_proxy_->OnAdaptationChanged(
1165 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1166 quality_counts);
1167
1168 EXPECT_EQ(QualityLimitationReason::kNone,
1169 statistics_proxy_->GetStats().quality_limitation_reason);
1170}
1171
1172TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
1173 SendStatisticsProxy::AdaptationSteps cpu_counts;
1174 SendStatisticsProxy::AdaptationSteps quality_counts;
1175
1176 // Not limited for 3000 ms
1177 fake_clock_.AdvanceTimeMilliseconds(3000);
1178 // CPU limited for 2000 ms
1179 cpu_counts.num_resolution_reductions = 1;
1180 statistics_proxy_->OnAdaptationChanged(
1181 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1182 quality_counts);
1183 fake_clock_.AdvanceTimeMilliseconds(2000);
1184 // Bandwidth limited for 1000 ms
1185 cpu_counts.num_resolution_reductions = 0;
1186 quality_counts.num_resolution_reductions = 1;
1187 statistics_proxy_->OnAdaptationChanged(
1188 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1189 quality_counts);
1190 fake_clock_.AdvanceTimeMilliseconds(1000);
1191 // CPU limited for another 2000 ms
1192 cpu_counts.num_resolution_reductions = 1;
1193 quality_counts.num_resolution_reductions = 0;
1194 statistics_proxy_->OnAdaptationChanged(
1195 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1196 quality_counts);
1197 fake_clock_.AdvanceTimeMilliseconds(2000);
1198
1199 auto quality_limitation_durations_ms =
1200 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1201
1202 EXPECT_EQ(3000,
1203 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1204 EXPECT_EQ(4000,
1205 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1206 EXPECT_EQ(
1207 1000,
1208 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1209 EXPECT_EQ(0,
1210 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1211}
1212
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001213TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1214 EXPECT_EQ(
1215 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1216}
1217
1218TEST_F(SendStatisticsProxyTest,
1219 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1220 VideoCodec codec;
1221 VideoBitrateAllocation allocation;
1222 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1223 EXPECT_EQ(
1224 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1225}
1226
1227TEST_F(SendStatisticsProxyTest,
1228 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1229 VideoCodec codec;
1230 codec.simulcastStream[0].active = true;
1231 codec.simulcastStream[1].active = true;
1232 codec.simulcastStream[2].active = true;
1233 VideoBitrateAllocation allocation;
1234 allocation.SetBitrate(0, 0, 100);
1235 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1236 EXPECT_EQ(
1237 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1238}
1239
1240TEST_F(SendStatisticsProxyTest,
1241 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1242 VideoCodec codec;
1243 codec.simulcastStream[0].active = true;
1244 codec.simulcastStream[1].active = true;
1245 codec.simulcastStream[2].active = true;
1246 VideoBitrateAllocation allocation;
1247 allocation.SetBitrate(0, 0, 100);
1248 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1249 allocation.SetBitrate(1, 0, 100);
1250 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1251 EXPECT_EQ(
1252 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1253}
1254
1255TEST_F(SendStatisticsProxyTest,
1256 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1257 VideoCodec codec;
1258 codec.simulcastStream[0].active = true;
1259 VideoBitrateAllocation allocation;
1260 allocation.SetBitrate(0, 0, 100);
1261 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1262 // Layer 0 got more bandwidth, but still only one layer on
1263 allocation.SetBitrate(0, 0, 200);
1264 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1265 EXPECT_EQ(
1266 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1267}
1268
1269TEST_F(SendStatisticsProxyTest,
1270 QualityLimitationResolutionChangesWithTogglingLayers) {
1271 VideoCodec codec;
1272 codec.simulcastStream[0].active = true;
1273 codec.simulcastStream[1].active = true;
1274 codec.simulcastStream[2].active = true;
1275 VideoBitrateAllocation allocation;
1276 allocation.SetBitrate(0, 0, 100);
1277 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1278 EXPECT_EQ(
1279 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1280 allocation.SetBitrate(1, 0, 300);
1281 allocation.SetBitrate(2, 0, 500);
1282 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1283 EXPECT_EQ(
1284 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1285 // Layer 2 off
1286 allocation.SetBitrate(2, 0, 0);
1287 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1288 EXPECT_EQ(
1289 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1290 // Layer 2 back on
1291 allocation.SetBitrate(2, 0, 500);
1292 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1293 EXPECT_EQ(
1294 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1295 allocation.SetBitrate(0, 0, 0);
1296 allocation.SetBitrate(1, 0, 0);
1297 allocation.SetBitrate(2, 0, 0);
1298 // All layers off
1299 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1300 EXPECT_EQ(
1301 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1302}
1303
1304TEST_F(SendStatisticsProxyTest,
1305 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1306 VideoCodec codec;
1307 // 3 layers
1308 codec.simulcastStream[0].active = true;
1309 codec.simulcastStream[1].active = true;
1310 codec.simulcastStream[2].active = true;
1311 VideoBitrateAllocation allocation;
1312 allocation.SetBitrate(0, 0, 500);
1313 allocation.SetBitrate(1, 0, 500);
1314 allocation.SetBitrate(2, 0, 500);
1315 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1316 EXPECT_EQ(
1317 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1318
1319 // Down to one layer now, triggered by a config change
1320 codec.numberOfSimulcastStreams = 1;
1321 codec.simulcastStream[1].active = false;
1322 codec.simulcastStream[2].active = false;
1323 allocation.SetBitrate(0, 0, 100);
1324 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1325 EXPECT_EQ(
1326 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1327
1328 // Up to 3 layers again.
1329 codec.numberOfSimulcastStreams = 3;
1330 codec.simulcastStream[1].active = true;
1331 codec.simulcastStream[2].active = true;
1332 allocation.SetBitrate(0, 0, 500);
1333 allocation.SetBitrate(1, 0, 500);
1334 allocation.SetBitrate(2, 0, 500);
1335 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1336 EXPECT_EQ(
1337 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1338}
1339
1340TEST_F(SendStatisticsProxyTest,
1341 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1342 VideoCodec codec;
1343 codec.simulcastStream[0].active = true;
1344 codec.spatialLayers[0].active = true;
1345 codec.spatialLayers[1].active = true;
1346 codec.spatialLayers[2].active = true;
1347 VideoBitrateAllocation allocation;
1348 allocation.SetBitrate(0, 0, 500);
1349 allocation.SetBitrate(1, 0, 500);
1350 allocation.SetBitrate(2, 0, 500);
1351 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1352 EXPECT_EQ(
1353 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1354
1355 // Down to one layer now, triggered by a config change
1356 codec.spatialLayers[1].active = false;
1357 codec.spatialLayers[2].active = false;
1358 allocation.SetBitrate(0, 0, 100);
1359 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1360 EXPECT_EQ(
1361 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1362
1363 // Up to 3 layers again.
1364 codec.spatialLayers[1].active = true;
1365 codec.spatialLayers[2].active = true;
1366 allocation.SetBitrate(0, 0, 500);
1367 allocation.SetBitrate(1, 0, 500);
1368 allocation.SetBitrate(2, 0, 500);
1369 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1370 EXPECT_EQ(
1371 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1372}
1373
asapersson59bac1a2016-01-07 23:36:00 -08001374TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001375 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001376 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1377
Pera48ddb72016-09-29 11:48:50 +02001378 // No switch, stats should not be updated.
1379 VideoEncoderConfig config;
1380 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001381 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001382 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001383
1384 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001385 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001386 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001387 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001388}
1389
asapersson320e45a2016-11-29 01:40:35 -08001390TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1391 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1392 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001393
asapersson320e45a2016-11-29 01:40:35 -08001394 statistics_proxy_.reset();
1395 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1396 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1397 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1398 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1399}
1400
1401TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001402 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001403 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001404 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1405 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1406 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001407 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001408
1409 // Not enough samples, stats should not be updated.
1410 for (int i = 0; i < kMinSamples - 1; ++i) {
1411 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001412 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001413 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1414 }
Åsa Persson0122e842017-10-16 12:19:23 +02001415 SetUp(); // Reset stats proxy also causes histograms to be reported.
1416 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1417 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1418
1419 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001420 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001421 for (int i = 0; i < kMinSamples; ++i) {
1422 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001423 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001424 encoded_image._encodedWidth = kWidth;
1425 encoded_image._encodedHeight = kHeight;
1426 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1427 encoded_image._encodedWidth = kWidth / 2;
1428 encoded_image._encodedHeight = kHeight / 2;
1429 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1430 }
1431
asapersson320e45a2016-11-29 01:40:35 -08001432 statistics_proxy_.reset();
1433 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1434 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1435 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1436 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1437}
1438
1439TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1440 const int kFps = 20;
1441 const int kMinPeriodicSamples = 6;
1442 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1443 for (int i = 0; i <= frames; ++i) {
1444 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1445 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1446 }
1447 statistics_proxy_.reset();
1448 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1449 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1450}
1451
1452TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1453 EncodedImage encoded_image;
1454 const int kFps = 20;
1455 const int kMinPeriodicSamples = 6;
1456 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001457 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001458 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001459 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001460 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1461 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001462 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1463 }
1464 statistics_proxy_.reset();
1465 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1466 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1467}
1468
1469TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1470 const int kFps = 20;
1471 const int kSuspendTimeMs = 10000;
1472 const int kMinPeriodicSamples = 6;
1473 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1474 for (int i = 0; i < frames; ++i) {
1475 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1476 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1477 }
1478 // Suspend.
1479 statistics_proxy_->OnSuspendChange(true);
1480 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1481
1482 for (int i = 0; i < frames; ++i) {
1483 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1484 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1485 }
1486 // Suspended time interval should not affect the framerate.
1487 statistics_proxy_.reset();
1488 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1489 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1490}
1491
1492TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1493 EncodedImage encoded_image;
1494 const int kFps = 20;
1495 const int kSuspendTimeMs = 10000;
1496 const int kMinPeriodicSamples = 6;
1497 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001498 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001499 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001500 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001501 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1502 }
1503 // Suspend.
1504 statistics_proxy_->OnSuspendChange(true);
1505 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1506
Åsa Persson0122e842017-10-16 12:19:23 +02001507 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001508 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001509 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001510 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1511 }
1512 // Suspended time interval should not affect the framerate.
1513 statistics_proxy_.reset();
1514 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1515 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1516}
1517
asaperssonf4e44af2017-04-19 02:01:06 -07001518TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001519 SendStatisticsProxy::AdaptationSteps cpu_counts;
1520 SendStatisticsProxy::AdaptationSteps quality_counts;
1521 cpu_counts.num_resolution_reductions = absl::nullopt;
1522 statistics_proxy_->OnAdaptationChanged(
1523 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1524 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001525
1526 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1527 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1528
1529 statistics_proxy_.reset();
1530 EXPECT_EQ(0,
1531 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1532}
1533
1534TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001535 SendStatisticsProxy::AdaptationSteps cpu_counts;
1536 SendStatisticsProxy::AdaptationSteps quality_counts;
1537 cpu_counts.num_resolution_reductions = 0;
1538 statistics_proxy_->OnAdaptationChanged(
1539 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1540 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001541
perkj803d97f2016-11-01 11:45:46 -07001542 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1543 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1544
Niels Möller213618e2018-07-24 09:29:58 +02001545 cpu_counts.num_resolution_reductions = 1;
1546 statistics_proxy_->OnAdaptationChanged(
1547 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1548 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001549
1550 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1551 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1552
1553 statistics_proxy_.reset();
1554 EXPECT_EQ(1,
1555 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1556 EXPECT_EQ(
1557 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1558}
1559
asapersson4374a092016-07-27 00:39:09 -07001560TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1561 const int64_t kTimeSec = 3;
1562 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1563 statistics_proxy_.reset();
1564 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1565 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1566 kTimeSec));
1567}
1568
1569TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1570 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1571 statistics_proxy_.reset();
1572 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1573}
1574
asapersson66d4b372016-12-19 06:50:53 -08001575TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1576 // First RTP packet sent.
1577 UpdateDataCounters(kFirstSsrc);
1578
1579 // Min runtime has passed.
1580 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1581 statistics_proxy_.reset();
1582 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1583 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1584}
1585
1586TEST_F(SendStatisticsProxyTest,
1587 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1588 // First RTP packet sent.
1589 UpdateDataCounters(kFirstSsrc);
1590
1591 // Min runtime has not passed.
1592 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1593 statistics_proxy_.reset();
1594 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1595 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1596}
1597
1598TEST_F(SendStatisticsProxyTest,
1599 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1600 // First RTP packet not sent.
1601 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1602 statistics_proxy_.reset();
1603 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1604}
1605
1606TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1607 // First RTP packet sent and min runtime passed.
1608 UpdateDataCounters(kFirstSsrc);
1609
1610 // No change. Video: 10000 ms, paused: 0 ms (0%).
1611 statistics_proxy_->OnSetEncoderTargetRate(50000);
1612 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1613 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1614
1615 statistics_proxy_.reset();
1616 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1617 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1618 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1619 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1620}
1621
1622TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1623 // First RTP packet sent and min runtime passed.
1624 UpdateDataCounters(kFirstSsrc);
1625
1626 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1627 statistics_proxy_->OnSetEncoderTargetRate(50000);
1628 fake_clock_.AdvanceTimeMilliseconds(7000);
1629 statistics_proxy_->OnSetEncoderTargetRate(0);
1630 fake_clock_.AdvanceTimeMilliseconds(3000);
1631 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1632
1633 statistics_proxy_.reset();
1634 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1635 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1636 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1637 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1638}
1639
1640TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1641 // First RTP packet sent.
1642 UpdateDataCounters(kFirstSsrc);
1643
1644 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1645 statistics_proxy_->OnSetEncoderTargetRate(0);
1646 fake_clock_.AdvanceTimeMilliseconds(1000);
1647 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1648 fake_clock_.AdvanceTimeMilliseconds(7000);
1649 statistics_proxy_->OnSetEncoderTargetRate(60000);
1650 fake_clock_.AdvanceTimeMilliseconds(3000);
1651 statistics_proxy_->OnSetEncoderTargetRate(0);
1652 fake_clock_.AdvanceTimeMilliseconds(250);
1653 statistics_proxy_->OnSetEncoderTargetRate(0);
1654 fake_clock_.AdvanceTimeMilliseconds(750);
1655 statistics_proxy_->OnSetEncoderTargetRate(60000);
1656 fake_clock_.AdvanceTimeMilliseconds(5000);
1657 statistics_proxy_->OnSetEncoderTargetRate(50000);
1658 fake_clock_.AdvanceTimeMilliseconds(4000);
1659 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1660
1661 statistics_proxy_.reset();
1662 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1663 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1664 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1665 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1666}
1667
1668TEST_F(SendStatisticsProxyTest,
1669 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1670 // First RTP packet sent.
1671 UpdateDataCounters(kFirstSsrc);
1672 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1673
1674 // Min runtime has not passed.
1675 statistics_proxy_->OnSetEncoderTargetRate(50000);
1676 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1677 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1678
1679 statistics_proxy_.reset();
1680 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1681}
1682
asapersson118ef002016-03-31 00:00:19 -07001683TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001684 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001685 CodecSpecificInfo codec_info;
1686 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001687
perkj803d97f2016-11-01 11:45:46 -07001688 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001689 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001690 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001691 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001692 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001693 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001694 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001695 }
1696 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001697 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1698 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1699 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1700 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001701}
1702
1703TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1704 VideoSendStream::Config config(nullptr);
1705 config.rtp.ssrcs.push_back(kFirstSsrc);
1706 statistics_proxy_.reset(new SendStatisticsProxy(
1707 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1708
asapersson118ef002016-03-31 00:00:19 -07001709 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001710 CodecSpecificInfo codec_info;
1711 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001712
perkj803d97f2016-11-01 11:45:46 -07001713 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001714 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001715 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001716 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001717 }
1718 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001719 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1720 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001721}
1722
asapersson5265fed2016-04-18 02:58:47 -07001723TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001724 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001725 CodecSpecificInfo codec_info;
1726 codec_info.codecType = kVideoCodecVP9;
1727 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001728
perkj803d97f2016-11-01 11:45:46 -07001729 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001730 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001731 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001732 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001733 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001734 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001735 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001736 }
1737 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001738 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1739 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1740 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1741 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001742}
1743
1744TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1745 VideoSendStream::Config config(nullptr);
1746 config.rtp.ssrcs.push_back(kFirstSsrc);
1747 statistics_proxy_.reset(new SendStatisticsProxy(
1748 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1749
asapersson5265fed2016-04-18 02:58:47 -07001750 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001751 CodecSpecificInfo codec_info;
1752 codec_info.codecType = kVideoCodecVP9;
1753 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001754
perkj803d97f2016-11-01 11:45:46 -07001755 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001756 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001757 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001758 }
1759 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001760 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1761 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001762}
1763
asapersson827cab32016-11-02 09:08:47 -07001764TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1765 EncodedImage encoded_image;
1766 CodecSpecificInfo codec_info;
1767 codec_info.codecType = kVideoCodecH264;
1768
1769 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001770 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001771 encoded_image.qp_ = kQpIdx0;
1772 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001773 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001774 encoded_image.qp_ = kQpIdx1;
1775 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001776 }
1777 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001778 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1779 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1780 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1781 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001782}
1783
asapersson4ee70462016-10-31 04:05:12 -07001784TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001785 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1786 // Configure one stream.
1787 VideoEncoderConfig config;
1788 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1789 VideoStream stream1;
1790 stream1.width = kWidth;
1791 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001792 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001793
1794 const int64_t kMaxEncodedFrameWindowMs = 800;
1795 const int kFps = 20;
1796 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1797 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1798 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1799
1800 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001801 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001802 encoded_image._encodedWidth = kWidth;
1803 encoded_image._encodedHeight = kHeight;
1804 for (int i = 0; i < kMinSamples; ++i) {
1805 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001806 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1807 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001808 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001809 }
asapersson4ee70462016-10-31 04:05:12 -07001810
1811 // Histograms are updated when the statistics_proxy_ is deleted.
1812 statistics_proxy_.reset();
1813 EXPECT_EQ(0, metrics::NumSamples(
1814 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1815 EXPECT_EQ(0, metrics::NumSamples(
1816 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1817}
1818
1819TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001820 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1821 // Configure two streams.
1822 VideoEncoderConfig config;
1823 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1824 VideoStream stream1;
1825 stream1.width = kWidth / 2;
1826 stream1.height = kHeight / 2;
1827 VideoStream stream2;
1828 stream2.width = kWidth;
1829 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001830 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001831
1832 const int64_t kMaxEncodedFrameWindowMs = 800;
1833 const int kFps = 20;
1834 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1835 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1836 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1837
1838 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001839 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001840 for (int i = 0; i < kMinSamples; ++i) {
1841 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001842 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1843 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001844 encoded_image._encodedWidth = kWidth;
1845 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001846 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001847 encoded_image._encodedWidth = kWidth / 2;
1848 encoded_image._encodedHeight = kHeight / 2;
1849 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1850 }
asapersson4ee70462016-10-31 04:05:12 -07001851
1852 // Histograms are updated when the statistics_proxy_ is deleted.
1853 statistics_proxy_.reset();
1854 EXPECT_EQ(1, metrics::NumSamples(
1855 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1856 EXPECT_EQ(1, metrics::NumEvents(
1857 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1858 // No resolution disabled.
1859 EXPECT_EQ(0, metrics::NumSamples(
1860 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1861}
1862
1863TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001864 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1865 // Configure two streams.
1866 VideoEncoderConfig config;
1867 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1868 VideoStream stream1;
1869 stream1.width = kWidth / 2;
1870 stream1.height = kHeight / 2;
1871 VideoStream stream2;
1872 stream2.width = kWidth;
1873 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001874 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001875
1876 const int64_t kMaxEncodedFrameWindowMs = 800;
1877 const int kFps = 20;
1878 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1879 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1880 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1881
1882 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001883 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001884 encoded_image._encodedWidth = kWidth / 2;
1885 encoded_image._encodedHeight = kHeight / 2;
1886 for (int i = 0; i < kMinSamples; ++i) {
1887 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001888 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1889 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001890 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001891 }
asapersson4ee70462016-10-31 04:05:12 -07001892
1893 // Histograms are updated when the statistics_proxy_ is deleted.
1894 statistics_proxy_.reset();
1895 EXPECT_EQ(1, metrics::NumSamples(
1896 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1897 EXPECT_EQ(1, metrics::NumEvents(
1898 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001899 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001900 EXPECT_EQ(1, metrics::NumSamples(
1901 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001902 EXPECT_EQ(1, metrics::NumEvents(
1903 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001904}
1905
1906TEST_F(SendStatisticsProxyTest,
1907 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001908 SendStatisticsProxy::AdaptationSteps cpu_counts;
1909 SendStatisticsProxy::AdaptationSteps quality_counts;
1910 quality_counts.num_resolution_reductions = absl::nullopt;
1911 statistics_proxy_->OnAdaptationChanged(
1912 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1913 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001914 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001915 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001916 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001917 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001918
1919 // Histograms are updated when the statistics_proxy_ is deleted.
1920 statistics_proxy_.reset();
1921 EXPECT_EQ(
1922 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1923 EXPECT_EQ(0, metrics::NumSamples(
1924 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1925}
1926
1927TEST_F(SendStatisticsProxyTest,
1928 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001929 SendStatisticsProxy::AdaptationSteps cpu_counts;
1930 SendStatisticsProxy::AdaptationSteps quality_counts;
1931 quality_counts.num_resolution_reductions = 0;
1932 statistics_proxy_->OnAdaptationChanged(
1933 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1934 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001935 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001936 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001937 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001938 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001939
1940 // Histograms are updated when the statistics_proxy_ is deleted.
1941 statistics_proxy_.reset();
1942 EXPECT_EQ(
1943 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1944 EXPECT_EQ(1, metrics::NumEvents(
1945 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1946 // No resolution downscale.
1947 EXPECT_EQ(0, metrics::NumSamples(
1948 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1949}
1950
1951TEST_F(SendStatisticsProxyTest,
1952 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1953 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001954 SendStatisticsProxy::AdaptationSteps cpu_counts;
1955 SendStatisticsProxy::AdaptationSteps quality_counts;
1956 quality_counts.num_resolution_reductions = kDownscales;
1957 statistics_proxy_->OnAdaptationChanged(
1958 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1959 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001960 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001961 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001962 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001963 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001964 // Histograms are updated when the statistics_proxy_ is deleted.
1965 statistics_proxy_.reset();
1966 EXPECT_EQ(
1967 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1968 EXPECT_EQ(1, metrics::NumEvents(
1969 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1970 // Resolution downscales.
1971 EXPECT_EQ(1, metrics::NumSamples(
1972 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1973 EXPECT_EQ(
1974 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1975 kDownscales));
1976}
1977
1978TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1979 // Initially false.
1980 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001981
Åsa Perssonaa329e72017-12-15 15:54:44 +01001982 // Configure two streams.
1983 VideoEncoderConfig config;
1984 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1985 VideoStream stream1;
1986 stream1.width = kWidth / 2;
1987 stream1.height = kHeight / 2;
1988 VideoStream stream2;
1989 stream2.width = kWidth;
1990 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001991 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001992
1993 const int64_t kMaxEncodedFrameWindowMs = 800;
1994 const int kFps = 20;
1995 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1996 kFps * kMaxEncodedFrameWindowMs / 1000;
1997
1998 // One stream encoded.
1999 EncodedImage encoded_image;
2000 encoded_image._encodedWidth = kWidth / 2;
2001 encoded_image._encodedHeight = kHeight / 2;
2002 for (int i = 0; i < kMinSamples; ++i) {
2003 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002004 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2005 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002006 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2007 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2008 }
2009
2010 // First frame removed from EncodedFrameMap, stats updated.
2011 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002012 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08002013 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2014 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2015
Åsa Perssonaa329e72017-12-15 15:54:44 +01002016 // Two streams encoded.
2017 for (int i = 0; i < kMinSamples; ++i) {
2018 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002019 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2020 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002021 encoded_image._encodedWidth = kWidth;
2022 encoded_image._encodedHeight = kHeight;
2023 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2024 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2025 encoded_image._encodedWidth = kWidth / 2;
2026 encoded_image._encodedHeight = kHeight / 2;
2027 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2028 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2029 }
2030
2031 // First frame with two streams removed, expect no resolution limit.
2032 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002033 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2034 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002035 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2036 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08002037
2038 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02002039 SendStatisticsProxy::AdaptationSteps cpu_counts;
2040 SendStatisticsProxy::AdaptationSteps quality_counts;
2041 quality_counts.num_resolution_reductions = 1;
2042 statistics_proxy_->OnAdaptationChanged(
2043 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2044 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002045 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2046 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2047}
2048
asapersson66d4b372016-12-19 06:50:53 -08002049TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2050 // Initially zero.
2051 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2052
2053 const int kBitrate = 100000;
2054 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2055 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2056
2057 statistics_proxy_->OnSetEncoderTargetRate(0);
2058 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2059}
2060
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002061TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002062 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002063 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2064 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002065 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002066 // From RtcpStatisticsCallback.
2067 RtcpStatistics rtcp_stats;
2068 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002069 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002070
2071 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002072 uint32_t total = 0;
2073 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002074 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002075 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002076
2077 // From FrameCountObserver.
2078 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002079 FrameCounts frame_counts;
2080 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002081 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002082
2083 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2084 EXPECT_TRUE(stats.substreams.empty());
2085}
2086
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002087TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2088 static const int kEncodedWidth = 123;
2089 static const int kEncodedHeight = 81;
2090 EncodedImage encoded_image;
2091 encoded_image._encodedWidth = kEncodedWidth;
2092 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002093 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002094
kjellander02b3d272016-04-20 05:05:54 -07002095 CodecSpecificInfo codec_info;
2096 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002097
kjellander02b3d272016-04-20 05:05:54 -07002098 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002099 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002100 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002101
2102 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002103 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2104 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2105 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2106 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002107
2108 // Forward almost to timeout, this should not have removed stats.
2109 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2110 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002111 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2112 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002113
2114 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2115 // resolution still times out (no global timeout for all stats).
2116 RtcpStatistics rtcp_statistics;
2117 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2118 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2119
2120 // Report stats for second SSRC to make sure it's not outdated along with the
2121 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002122 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002123
2124 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2125 // reported, but substream 1 should.
2126 fake_clock_.AdvanceTimeMilliseconds(1);
2127 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002128 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2129 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2130 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2131 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002132}
2133
Peter Boström20f3f942015-05-15 11:33:39 +02002134TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2135 static const int kEncodedWidth = 123;
2136 static const int kEncodedHeight = 81;
2137 EncodedImage encoded_image;
2138 encoded_image._encodedWidth = kEncodedWidth;
2139 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002140 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002141
kjellander02b3d272016-04-20 05:05:54 -07002142 CodecSpecificInfo codec_info;
2143 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002144
kjellander02b3d272016-04-20 05:05:54 -07002145 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002146 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002147 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002148
2149 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2150 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2151 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2152 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2153 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2154 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2155}
2156
2157TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002158 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002159 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2160 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2161 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2162
2163 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2164
2165 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002166 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002167 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002168 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002169 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2170 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2171 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2172}
2173
sprang07fb9be2016-02-24 07:55:00 -08002174TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2175 RtcpPacketTypeCounterObserver* proxy =
2176 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2177 RtcpPacketTypeCounter counters;
2178 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2179 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2180 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2181
2182 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2183
2184 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2185 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2186 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2187 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2188 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2189
2190 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2191 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2192
2193 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002194 VideoEncoderConfig config;
2195 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002196 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002197
asapersson01d70a32016-05-20 06:29:46 -07002198 EXPECT_EQ(1,
2199 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2200 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2201 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2202 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002203 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2204
2205 const int kRate = 60 * 2; // Packets per minute with two streams.
2206
asapersson01d70a32016-05-20 06:29:46 -07002207 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2208 1 * kRate));
2209 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2210 2 * kRate));
2211 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2212 3 * kRate));
2213 EXPECT_EQ(
2214 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2215 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002216
2217 // New start time but same counter values.
2218 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2219 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2220
2221 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2222
2223 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2224 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2225 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2226 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2227 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2228
2229 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2230 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2231
2232 SetUp(); // Reset stats proxy also causes histograms to be reported.
2233
asapersson01d70a32016-05-20 06:29:46 -07002234 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002235 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07002236 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002237 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07002238 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002239 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2240 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002241 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002242 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2243
asapersson01d70a32016-05-20 06:29:46 -07002244 EXPECT_EQ(1, metrics::NumEvents(
2245 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
2246 1 * kRate));
2247 EXPECT_EQ(1, metrics::NumEvents(
2248 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2249 2 * kRate));
2250 EXPECT_EQ(1, metrics::NumEvents(
2251 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2252 3 * kRate));
2253 EXPECT_EQ(1,
2254 metrics::NumEvents(
2255 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2256 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002257}
2258
asaperssona6a699a2016-11-25 03:52:46 -08002259TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2260 statistics_proxy_.reset(
2261 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2262 VideoEncoderConfig::ContentType::kRealtimeVideo));
2263
2264 StreamDataCountersCallback* proxy =
2265 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2266 StreamDataCounters counters;
2267 proxy->DataCountersUpdated(counters, kFirstSsrc);
2268 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2269
2270 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
2271 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
2272}
2273
2274TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2275 statistics_proxy_.reset(
2276 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2277 VideoEncoderConfig::ContentType::kRealtimeVideo));
2278
2279 StreamDataCountersCallback* proxy =
2280 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002281 StreamDataCounters counters;
2282 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002283
asapersson93e1e232017-02-06 05:18:35 -08002284 const int kMinRequiredPeriodSamples = 8;
2285 const int kPeriodIntervalMs = 2000;
2286 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2287 counters.transmitted.packets += 20;
2288 counters.transmitted.header_bytes += 500;
2289 counters.transmitted.padding_bytes += 1000;
2290 counters.transmitted.payload_bytes += 2000;
2291 counters.retransmitted.packets += 2;
2292 counters.retransmitted.header_bytes += 25;
2293 counters.retransmitted.padding_bytes += 100;
2294 counters.retransmitted.payload_bytes += 250;
2295 counters.fec = counters.retransmitted;
2296 rtx_counters.transmitted = counters.transmitted;
2297 // Advance one interval and update counters.
2298 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2299 proxy->DataCountersUpdated(counters, kFirstSsrc);
2300 proxy->DataCountersUpdated(counters, kSecondSsrc);
2301 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2302 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2303 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2304 }
asaperssona6a699a2016-11-25 03:52:46 -08002305
asaperssona6a699a2016-11-25 03:52:46 -08002306 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002307 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002308 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002309 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2310 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2311 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2312 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2313 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002314 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002315 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2316 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002317 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002318 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2319 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2320 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2321 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2322 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002323 EXPECT_EQ(1,
2324 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08002325 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002326 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002327}
2328
Erik Språng22c2b482016-03-01 09:40:42 +01002329TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2330 StreamDataCountersCallback* proxy =
2331 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2332 StreamDataCounters counters;
2333 StreamDataCounters rtx_counters;
2334 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002335
asapersson93e1e232017-02-06 05:18:35 -08002336 const int kMinRequiredPeriodSamples = 8;
2337 const int kPeriodIntervalMs = 2000;
2338 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2339 counters.transmitted.packets += 20;
2340 counters.transmitted.header_bytes += 500;
2341 counters.transmitted.padding_bytes += 1000;
2342 counters.transmitted.payload_bytes += 2000;
2343 counters.retransmitted.packets += 2;
2344 counters.retransmitted.header_bytes += 25;
2345 counters.retransmitted.padding_bytes += 100;
2346 counters.retransmitted.payload_bytes += 250;
2347 counters.fec = counters.retransmitted;
2348 rtx_counters.transmitted = counters.transmitted;
2349 // Advance one interval and update counters.
2350 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2351 proxy->DataCountersUpdated(counters, kFirstSsrc);
2352 proxy->DataCountersUpdated(counters, kSecondSsrc);
2353 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2354 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2355 }
Erik Språng22c2b482016-03-01 09:40:42 +01002356
2357 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002358 VideoEncoderConfig config;
2359 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002360 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002361
asapersson93e1e232017-02-06 05:18:35 -08002362 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002363 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002364 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2365 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2366 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2367 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2368 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002369 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002370 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2371 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002372 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002373 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2374 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2375 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2376 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2377 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002378 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002379 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002380 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002381 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002382
asapersson93e1e232017-02-06 05:18:35 -08002383 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002384 // Double counter values, this should result in the same counts as before but
2385 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002386 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2387 counters.transmitted.packets += 20;
2388 counters.transmitted.header_bytes += 500;
2389 counters.transmitted.padding_bytes += 1000;
2390 counters.transmitted.payload_bytes += 2000;
2391 counters.retransmitted.packets += 2;
2392 counters.retransmitted.header_bytes += 25;
2393 counters.retransmitted.padding_bytes += 100;
2394 counters.retransmitted.payload_bytes += 250;
2395 counters.fec = counters.retransmitted;
2396 rtx_counters.transmitted = counters.transmitted;
2397 // Advance one interval and update counters.
2398 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2399 proxy->DataCountersUpdated(counters, kFirstSsrc);
2400 proxy->DataCountersUpdated(counters, kSecondSsrc);
2401 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2402 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2403 }
Erik Språng22c2b482016-03-01 09:40:42 +01002404
asapersson93e1e232017-02-06 05:18:35 -08002405 // Reset stats proxy also causes histograms to be reported.
2406 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002407
asapersson93e1e232017-02-06 05:18:35 -08002408 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002409 EXPECT_EQ(1,
2410 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002411 EXPECT_EQ(
2412 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2413 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2414 EXPECT_EQ(
2415 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2416 EXPECT_EQ(1, metrics::NumEvents(
2417 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2418 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002419 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002420 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002421 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002422 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2423 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002424 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002425 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002426 EXPECT_EQ(1, metrics::NumEvents(
2427 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2428 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2429 EXPECT_EQ(
2430 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2431 EXPECT_EQ(1, metrics::NumEvents(
2432 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2433 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002434 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002435 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002436 EXPECT_EQ(1,
2437 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002438 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2439}
Erik Språng22c2b482016-03-01 09:40:42 +01002440
asapersson93e1e232017-02-06 05:18:35 -08002441TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2442 StreamDataCountersCallback* proxy =
2443 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2444 StreamDataCounters counters;
2445 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002446
asapersson93e1e232017-02-06 05:18:35 -08002447 const int kMinRequiredPeriodSamples = 8;
2448 const int kPeriodIntervalMs = 2000;
2449 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2450 counters.transmitted.packets += 20;
2451 counters.transmitted.header_bytes += 500;
2452 counters.transmitted.payload_bytes += 2000;
2453 counters.fec = counters.retransmitted;
2454 // Advance one interval and update counters.
2455 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2456 proxy->DataCountersUpdated(counters, kFirstSsrc);
2457 }
2458
2459 // RTX enabled. No data sent over RTX.
2460 statistics_proxy_.reset();
2461 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2462 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2463}
2464
2465TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2466 VideoSendStream::Config config(nullptr);
2467 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2468 statistics_proxy_.reset(new SendStatisticsProxy(
2469 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2470
2471 StreamDataCountersCallback* proxy =
2472 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2473 StreamDataCounters counters;
2474
2475 const int kMinRequiredPeriodSamples = 8;
2476 const int kPeriodIntervalMs = 2000;
2477 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2478 counters.transmitted.packets += 20;
2479 counters.transmitted.header_bytes += 500;
2480 counters.transmitted.payload_bytes += 2000;
2481 counters.fec = counters.retransmitted;
2482 // Advance one interval and update counters.
2483 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2484 proxy->DataCountersUpdated(counters, kFirstSsrc);
2485 }
2486
2487 // RTX not enabled.
2488 statistics_proxy_.reset();
2489 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2490}
2491
2492TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2493 StreamDataCountersCallback* proxy =
2494 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2495 StreamDataCounters counters;
2496 StreamDataCounters rtx_counters;
2497
2498 const int kMinRequiredPeriodSamples = 8;
2499 const int kPeriodIntervalMs = 2000;
2500 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2501 counters.transmitted.packets += 20;
2502 counters.transmitted.header_bytes += 500;
2503 counters.transmitted.payload_bytes += 2000;
2504 // Advance one interval and update counters.
2505 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2506 proxy->DataCountersUpdated(counters, kFirstSsrc);
2507 }
2508
2509 // FEC enabled. No FEC data sent.
2510 statistics_proxy_.reset();
2511 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2512 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2513}
2514
2515TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2516 VideoSendStream::Config config(nullptr);
2517 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2518 statistics_proxy_.reset(new SendStatisticsProxy(
2519 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2520
2521 StreamDataCountersCallback* proxy =
2522 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2523 StreamDataCounters counters;
2524
2525 const int kMinRequiredPeriodSamples = 8;
2526 const int kPeriodIntervalMs = 2000;
2527 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2528 counters.transmitted.packets += 20;
2529 counters.transmitted.header_bytes += 500;
2530 counters.transmitted.payload_bytes += 2000;
2531 counters.fec = counters.retransmitted;
2532 // Advance one interval and update counters.
2533 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2534 proxy->DataCountersUpdated(counters, kFirstSsrc);
2535 }
2536
2537 // FEC not enabled.
2538 statistics_proxy_.reset();
2539 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002540}
2541
asapersson8d75ac72017-09-15 06:41:15 -07002542TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002543 const std::string kName = "encoderName";
2544 statistics_proxy_->OnEncoderImplementationChanged(kName);
2545 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002546}
2547
Sergey Silkinbb081a62018-09-04 18:34:22 +02002548TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2549 static const int kEncodedWidth = 123;
2550 static const int kEncodedHeight = 81;
2551 EncodedImage encoded_image;
2552 encoded_image._encodedWidth = kEncodedWidth;
2553 encoded_image._encodedHeight = kEncodedHeight;
2554 encoded_image.SetSpatialIndex(0);
2555
2556 CodecSpecificInfo codec_info;
2557 codec_info.codecType = kVideoCodecVP9;
2558
2559 // For first picture, it is expected that low layer updates resolution.
2560 codec_info.codecSpecific.VP9.end_of_picture = false;
2561 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2562 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2563 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2564 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2565
2566 // Top layer updates resolution.
2567 encoded_image._encodedWidth = kEncodedWidth * 2;
2568 encoded_image._encodedHeight = kEncodedHeight * 2;
2569 codec_info.codecSpecific.VP9.end_of_picture = true;
2570 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2571 stats = statistics_proxy_->GetStats();
2572 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2573 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2574
2575 // Low layer of next frame doesn't update resolution.
2576 encoded_image._encodedWidth = kEncodedWidth;
2577 encoded_image._encodedHeight = kEncodedHeight;
2578 codec_info.codecSpecific.VP9.end_of_picture = false;
2579 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2580 stats = statistics_proxy_->GetStats();
2581 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2582 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2583}
2584
asapersson8d75ac72017-09-15 06:41:15 -07002585class ForcedFallbackTest : public SendStatisticsProxyTest {
2586 public:
2587 explicit ForcedFallbackTest(const std::string& field_trials)
2588 : SendStatisticsProxyTest(field_trials) {
2589 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002590 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002591 encoded_image_._encodedWidth = kWidth;
2592 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002593 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002594 }
2595
2596 ~ForcedFallbackTest() override {}
2597
2598 protected:
2599 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002600 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2601
asapersson8d75ac72017-09-15 06:41:15 -07002602 // First frame is not updating stats, insert initial frame.
2603 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2604 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2605 }
2606 for (int i = 0; i < num_frames; ++i) {
2607 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2608 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2609 }
2610 // Add frame to include last time interval.
2611 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2612 }
2613
2614 EncodedImage encoded_image_;
2615 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002616 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002617 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2618 const int kFrameIntervalMs = 1000;
2619 const int kMinFrames = 20; // Min run time 20 sec.
2620};
2621
2622class ForcedFallbackDisabled : public ForcedFallbackTest {
2623 public:
2624 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002625 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2626 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002627};
2628
2629class ForcedFallbackEnabled : public ForcedFallbackTest {
2630 public:
2631 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002632 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2633 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002634};
2635
2636TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2637 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2638 statistics_proxy_.reset();
2639 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2640 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2641}
2642
2643TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2644 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002645 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002646 statistics_proxy_.reset();
2647 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2648 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2649 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2650 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2651}
2652
2653TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2654 codec_info_.codecType = kVideoCodecVP9;
2655 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2656 statistics_proxy_.reset();
2657 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2658 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2659}
2660
2661TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2662 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2663 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2664 statistics_proxy_.reset();
2665 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2666 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2667}
2668
2669TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002670 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002671 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2672 statistics_proxy_.reset();
2673 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2674 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2675}
2676
2677TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2678 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2679 statistics_proxy_.reset();
2680 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2681 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2682}
2683
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002684TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2685 InsertEncodedFrames(1, kFrameIntervalMs);
2686 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2687}
2688
2689TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2690 InsertEncodedFrames(1, kFrameIntervalMs);
2691 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2692}
2693
2694TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002695 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002696 InsertEncodedFrames(1, kFrameIntervalMs);
2697 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2698}
2699
2700TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2701 encoded_image_._encodedWidth = kWidth + 1;
2702 InsertEncodedFrames(1, kFrameIntervalMs);
2703 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2704}
2705
2706TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002707 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002708 InsertEncodedFrames(1, kFrameIntervalMs);
2709 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2710}
2711
2712TEST_F(ForcedFallbackDisabled,
2713 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2714 encoded_image_._encodedWidth = kWidth + 1;
2715 statistics_proxy_->OnMinPixelLimitReached();
2716 InsertEncodedFrames(1, kFrameIntervalMs);
2717 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2718}
2719
asapersson8d75ac72017-09-15 06:41:15 -07002720TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2721 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002722 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002723 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002724 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002725 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002726 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002727 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002728
2729 statistics_proxy_.reset();
2730 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2731 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2732 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2733 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2734}
2735
2736TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2737 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2738 const int kMaxFrameDiffMs = 2000;
2739
2740 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2741 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002742 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002743 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002744 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002745 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002746 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002747 InsertEncodedFrames(20, 1000);
2748 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2749 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002750 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002751 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002752 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002753 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002754 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002755 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002756 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002757
2758 statistics_proxy_.reset();
2759 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2760 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2761 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2762 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2763}
2764
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002765TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2766 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002767 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002768 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2769
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002770 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002771 statistics_proxy_.reset();
2772 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2773 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2774}
2775
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002776TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2777 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002778 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002779 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2780
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002781 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002782 statistics_proxy_.reset();
2783 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2784 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2785}
2786
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002787} // namespace webrtc