blob: 08c1230a8b392473f14ef697eae5976391753898 [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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070021#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000023
24namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070025namespace {
26const uint32_t kFirstSsrc = 17;
27const uint32_t kSecondSsrc = 42;
28const uint32_t kFirstRtxSsrc = 18;
29const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080030const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080031const int kFpsPeriodicIntervalMs = 2000;
32const int kWidth = 640;
33const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070034const int kQpIdx0 = 21;
35const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010036const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080037const CodecSpecificInfo kDefaultCodecInfo = []() {
38 CodecSpecificInfo codec_info;
39 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080040 return codec_info;
41}();
asapersson5265fed2016-04-18 02:58:47 -070042} // namespace
sprang07fb9be2016-02-24 07:55:00 -080043
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000044class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000045 public:
asapersson8d75ac72017-09-15 06:41:15 -070046 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
47 explicit SendStatisticsProxyTest(const std::string& field_trials)
48 : override_field_trials_(field_trials),
49 fake_clock_(1234),
50 config_(GetTestConfig()),
51 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070052 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000053 virtual ~SendStatisticsProxyTest() {}
54
55 protected:
56 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070057 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080058 statistics_proxy_.reset(new SendStatisticsProxy(
59 &fake_clock_, GetTestConfig(),
60 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000061 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070062 for (const auto& ssrc : config_.rtp.ssrcs)
63 expected_.substreams[ssrc].is_rtx = false;
64 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
65 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000066 }
67
68 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070069 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080070 config.rtp.ssrcs.push_back(kFirstSsrc);
71 config.rtp.ssrcs.push_back(kSecondSsrc);
72 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
73 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070074 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000075 return config;
76 }
77
asaperssona6a699a2016-11-25 03:52:46 -080078 VideoSendStream::Config GetTestConfigWithFlexFec() {
79 VideoSendStream::Config config(nullptr);
80 config.rtp.ssrcs.push_back(kFirstSsrc);
81 config.rtp.ssrcs.push_back(kSecondSsrc);
82 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
83 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080084 config.rtp.flexfec.payload_type = 50;
85 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080086 return config;
87 }
88
89 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
90 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
91 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
92 stats.substreams.find(ssrc);
93 EXPECT_NE(it, stats.substreams.end());
94 return it->second;
95 }
96
asapersson66d4b372016-12-19 06:50:53 -080097 void UpdateDataCounters(uint32_t ssrc) {
98 StreamDataCountersCallback* proxy =
99 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
100 StreamDataCounters counters;
101 proxy->DataCountersUpdated(counters, ssrc);
102 }
103
sprang@webrtc.org09315702014-02-07 12:06:29 +0000104 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000105 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
106 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000107 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000108 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000109
110 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000111 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000112 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000113 it != one.substreams.end(); ++it) {
114 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
115 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000116 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000117 const VideoSendStream::StreamStats& a = it->second;
118 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000119
asapersson2e5cfcd2016-08-11 08:41:18 -0700120 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000121 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
122 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000123 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000124 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
125 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000126
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000127 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
128 b.rtp_stats.transmitted.payload_bytes);
129 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
130 b.rtp_stats.transmitted.header_bytes);
131 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
132 b.rtp_stats.transmitted.padding_bytes);
133 EXPECT_EQ(a.rtp_stats.transmitted.packets,
134 b.rtp_stats.transmitted.packets);
135 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
136 b.rtp_stats.retransmitted.packets);
137 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000138
139 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700140 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
141 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
142 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000143 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
144 }
145 }
146
asapersson8d75ac72017-09-15 06:41:15 -0700147 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000148 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800149 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000150 VideoSendStream::Config config_;
151 int avg_delay_ms_;
152 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000153 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000154 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
155 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156};
157
158TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
159 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700160 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000161 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000162
163 // Add statistics with some arbitrary, but unique, numbers.
164 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700165 ssrc_stats.rtcp_stats.packets_lost = offset;
166 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000167 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
168 ssrc_stats.rtcp_stats.jitter = offset + 3;
169 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
170 }
asapersson35151f32016-05-02 23:44:01 -0700171 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000172 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000174 // Add statistics with some arbitrary, but unique, numbers.
175 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700176 ssrc_stats.rtcp_stats.packets_lost = offset;
177 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000178 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
179 ssrc_stats.rtcp_stats.jitter = offset + 3;
180 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
181 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000183 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184}
185
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000186TEST_F(SendStatisticsProxyTest, Suspended) {
187 // Verify that the value is false by default.
188 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
189
190 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200191 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000192 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
193
194 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200195 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000196 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
197}
198
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000199TEST_F(SendStatisticsProxyTest, FrameCounts) {
200 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700201 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000202 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000203 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
204 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000205 FrameCounts frame_counts;
206 frame_counts.key_frames = offset;
207 frame_counts.delta_frames = offset + 1;
208 stats.frame_counts = frame_counts;
209 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000210 }
asapersson35151f32016-05-02 23:44:01 -0700211 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000212 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000213 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
214 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000215 FrameCounts frame_counts;
216 frame_counts.key_frames = offset;
217 frame_counts.delta_frames = offset + 1;
218 stats.frame_counts = frame_counts;
219 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000220 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000221
222 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000223 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224}
225
226TEST_F(SendStatisticsProxyTest, DataCounters) {
227 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700228 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000229 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
230 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000231 size_t offset = ssrc * sizeof(StreamDataCounters);
232 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000233 counters.transmitted.payload_bytes = offset;
234 counters.transmitted.header_bytes = offset + 1;
235 counters.fec.packets = offset_uint32 + 2;
236 counters.transmitted.padding_bytes = offset + 3;
237 counters.retransmitted.packets = offset_uint32 + 4;
238 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000239 callback->DataCountersUpdated(counters, ssrc);
240 }
asapersson35151f32016-05-02 23:44:01 -0700241 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000242 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
243 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000244 size_t offset = ssrc * sizeof(StreamDataCounters);
245 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000246 counters.transmitted.payload_bytes = offset;
247 counters.transmitted.header_bytes = offset + 1;
248 counters.fec.packets = offset_uint32 + 2;
249 counters.transmitted.padding_bytes = offset + 3;
250 counters.retransmitted.packets = offset_uint32 + 4;
251 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000252 callback->DataCountersUpdated(counters, ssrc);
253 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000254
255 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000256 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000257}
258
259TEST_F(SendStatisticsProxyTest, Bitrate) {
260 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700261 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700262 uint32_t total;
263 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000264 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700265 total = ssrc;
266 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000267 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700268 expected_.substreams[ssrc].total_bitrate_bps = total;
269 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000270 }
asapersson35151f32016-05-02 23:44:01 -0700271 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700272 uint32_t total;
273 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000274 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700275 total = ssrc;
276 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000277 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700278 expected_.substreams[ssrc].total_bitrate_bps = total;
279 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000281
282 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000283 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000284}
285
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000286TEST_F(SendStatisticsProxyTest, SendSideDelay) {
287 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700288 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000289 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
290 // stream.
291 int avg_delay_ms = ssrc;
292 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200293 uint64_t total_packet_send_delay_ms = ssrc + 2;
294 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
295 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000296 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
297 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200298 expected_.substreams[ssrc].total_packet_send_delay_ms =
299 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000300 }
asapersson35151f32016-05-02 23:44:01 -0700301 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000302 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
303 // stream.
304 int avg_delay_ms = ssrc;
305 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200306 uint64_t total_packet_send_delay_ms = ssrc + 2;
307 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
308 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000309 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
310 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200311 expected_.substreams[ssrc].total_packet_send_delay_ms =
312 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000313 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000314 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000315 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000316}
317
Peter Boströme4499152016-02-05 11:13:28 +0100318TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800319 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200320 int encode_usage_percent = 80;
321 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
322 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800323
324 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
325 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200326 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800327}
328
Henrik Boström5684af52019-04-02 15:05:21 +0200329TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
330 const int kEncodeUsagePercent = 0; // Don't care for this test.
331 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
332 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
333 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
334 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
335 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
336}
337
sakal43536c32016-10-24 01:46:43 -0700338TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
339 EncodedImage encoded_image;
340 CodecSpecificInfo codec_info;
341 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
342 for (uint32_t i = 1; i <= 3; ++i) {
343 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
344 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
345 }
346}
347
sakal87da4042016-10-31 06:53:47 -0700348TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
349 EncodedImage encoded_image;
350 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200351 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700352 encoded_image.qp_ = 3;
353 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100354 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700355 encoded_image.qp_ = 127;
356 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100357 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700358}
359
360TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
361 EncodedImage encoded_image;
362 CodecSpecificInfo codec_info;
363 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200364 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700365 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200366 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700367}
368
asapersson09f05612017-05-15 23:40:18 -0700369TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200370 SendStatisticsProxy::AdaptationSteps cpu_counts;
371 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700372 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700373 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200374 cpu_counts.num_framerate_reductions = 1;
375 cpu_counts.num_resolution_reductions = 0;
376 statistics_proxy_->OnAdaptationChanged(
377 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
378 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700379 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700380 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200381 cpu_counts.num_framerate_reductions = 0;
382 cpu_counts.num_resolution_reductions = 1;
383 statistics_proxy_->OnAdaptationChanged(
384 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
385 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700386 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700387 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200388 cpu_counts.num_framerate_reductions = 1;
389 cpu_counts.num_resolution_reductions = absl::nullopt;
390 statistics_proxy_->OnAdaptationChanged(
391 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
392 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700393 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700394 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200395 cpu_counts.num_framerate_reductions = absl::nullopt;
396 cpu_counts.num_resolution_reductions = absl::nullopt;
397 statistics_proxy_->OnAdaptationChanged(
398 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
399 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700400 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
401 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
402}
403
404TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200405 SendStatisticsProxy::AdaptationSteps cpu_counts;
406 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700407 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
408 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200409 quality_counts.num_framerate_reductions = 1;
410 quality_counts.num_resolution_reductions = 0;
411 statistics_proxy_->OnAdaptationChanged(
412 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
413 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700414 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
415 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200416 quality_counts.num_framerate_reductions = 0;
417 quality_counts.num_resolution_reductions = 1;
418 statistics_proxy_->OnAdaptationChanged(
419 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
420 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700421 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
422 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200423 quality_counts.num_framerate_reductions = 1;
424 quality_counts.num_resolution_reductions = absl::nullopt;
425 statistics_proxy_->OnAdaptationChanged(
426 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
427 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700428 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
429 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200430 quality_counts.num_framerate_reductions = absl::nullopt;
431 quality_counts.num_resolution_reductions = absl::nullopt;
432 statistics_proxy_->OnAdaptationChanged(
433 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
434 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700435 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
436 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
437}
438
439TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200440 SendStatisticsProxy::AdaptationSteps cpu_counts;
441 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700442 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
443
Niels Möller213618e2018-07-24 09:29:58 +0200444 cpu_counts.num_resolution_reductions = 1;
445 statistics_proxy_->OnAdaptationChanged(
446 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
447 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700448 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700449 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
450 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
451
Niels Möller213618e2018-07-24 09:29:58 +0200452 cpu_counts.num_resolution_reductions = 2;
453 statistics_proxy_->OnAdaptationChanged(
454 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
455 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700456 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
457 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700458 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700459 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700460}
461
asapersson09f05612017-05-15 23:40:18 -0700462TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200463 SendStatisticsProxy::AdaptationSteps cpu_counts;
464 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700465 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
466
Niels Möller213618e2018-07-24 09:29:58 +0200467 quality_counts.num_framerate_reductions = 1;
468 statistics_proxy_->OnAdaptationChanged(
469 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
470 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700471 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
472 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700473 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
474
Niels Möller213618e2018-07-24 09:29:58 +0200475 quality_counts.num_framerate_reductions = 0;
476 statistics_proxy_->OnAdaptationChanged(
477 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
478 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700479 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700480 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700481 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
482 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700483}
484
asapersson09f05612017-05-15 23:40:18 -0700485TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700486 // First RTP packet sent.
487 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700488 // Min runtime has passed.
489 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
490 statistics_proxy_.reset();
491 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
492 EXPECT_EQ(0,
493 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
494}
495
496TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700497 // First RTP packet sent.
498 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700499 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200500 SendStatisticsProxy::AdaptationSteps cpu_counts;
501 SendStatisticsProxy::AdaptationSteps quality_counts;
502 statistics_proxy_->OnAdaptationChanged(
503 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
504 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700505 // Min runtime has not passed.
506 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
507 statistics_proxy_.reset();
508 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
509 EXPECT_EQ(0,
510 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
511}
512
asapersson09f05612017-05-15 23:40:18 -0700513TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700514 // First RTP packet sent.
515 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700516 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200517 SendStatisticsProxy::AdaptationSteps cpu_counts;
518 SendStatisticsProxy::AdaptationSteps quality_counts;
519 statistics_proxy_->OnAdaptationChanged(
520 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
521 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700522 // Min runtime has passed.
523 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
524 statistics_proxy_.reset();
525 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
526 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700527 EXPECT_EQ(1,
528 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
529 EXPECT_EQ(
530 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
531}
532
533TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700534 // First RTP packet sent.
535 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700536 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200537 SendStatisticsProxy::AdaptationSteps cpu_counts;
538 SendStatisticsProxy::AdaptationSteps quality_counts;
539 statistics_proxy_->OnAdaptationChanged(
540 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
541 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700542 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200543 statistics_proxy_->OnAdaptationChanged(
544 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
545 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700546 fake_clock_.AdvanceTimeMilliseconds(10000);
547 statistics_proxy_.reset();
548 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
549 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
550}
551
Åsa Persson875841d2018-01-08 08:49:53 +0100552TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
553 // First RTP packet sent.
554 UpdateDataCounters(kFirstSsrc);
555 // 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);
Åsa Persson875841d2018-01-08 08:49:53 +0100561 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200562 statistics_proxy_->OnAdaptationChanged(
563 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
564 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100565 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
566 fake_clock_.AdvanceTimeMilliseconds(10000);
567 statistics_proxy_.reset();
568 EXPECT_EQ(1,
569 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
570 EXPECT_EQ(
571 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
572}
573
574TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
575 // First RTP packet sent.
576 UpdateDataCounters(kFirstSsrc);
577 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200578 SendStatisticsProxy::AdaptationSteps cpu_counts;
579 SendStatisticsProxy::AdaptationSteps quality_counts;
580 statistics_proxy_->OnAdaptationChanged(
581 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
582 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100583 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200584 quality_counts.num_resolution_reductions = 1;
585 statistics_proxy_->OnAdaptationChanged(
586 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
587 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100588 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200589 quality_counts.num_resolution_reductions = 2;
590 statistics_proxy_->OnAdaptationChanged(
591 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
592 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100593 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200594 quality_counts.num_resolution_reductions = 3;
595 statistics_proxy_->OnAdaptationChanged(
596 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
597 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100598 fake_clock_.AdvanceTimeMilliseconds(10000);
599 statistics_proxy_.reset();
600 EXPECT_EQ(1,
601 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
602 EXPECT_EQ(
603 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
604}
605
606TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
607 // First RTP packet sent.
608 UpdateDataCounters(kFirstSsrc);
609 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200610 SendStatisticsProxy::AdaptationSteps cpu_counts;
611 SendStatisticsProxy::AdaptationSteps quality_counts;
612 statistics_proxy_->OnAdaptationChanged(
613 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
614 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100615 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200616 statistics_proxy_->OnAdaptationChanged(
617 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
618 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100619 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
620 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
621 fake_clock_.AdvanceTimeMilliseconds(10000);
622 statistics_proxy_.reset();
623 EXPECT_EQ(1,
624 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
625 EXPECT_EQ(
626 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
627}
628
629TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
630 // First RTP packet sent.
631 UpdateDataCounters(kFirstSsrc);
632 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200633 SendStatisticsProxy::AdaptationSteps cpu_counts;
634 SendStatisticsProxy::AdaptationSteps quality_counts;
635 statistics_proxy_->OnAdaptationChanged(
636 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
637 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100638 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200639 quality_counts.num_resolution_reductions = 1;
640 statistics_proxy_->OnAdaptationChanged(
641 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
642 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100643 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200644 quality_counts.num_resolution_reductions = 2;
645 statistics_proxy_->OnAdaptationChanged(
646 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
647 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100648 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200649 quality_counts.num_resolution_reductions = 3;
650 statistics_proxy_->OnAdaptationChanged(
651 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
652 quality_counts);
653 quality_counts.num_framerate_reductions = 1;
654 statistics_proxy_->OnAdaptationChanged(
655 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
656 quality_counts);
657 quality_counts.num_framerate_reductions = 0;
658 statistics_proxy_->OnAdaptationChanged(
659 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
660 quality_counts);
661 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
662 statistics_proxy_->OnAdaptationChanged(
663 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
664 quality_counts);
665 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
666 statistics_proxy_->OnAdaptationChanged(
667 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
668 quality_counts);
669 quality_counts.num_resolution_reductions = 0;
670 statistics_proxy_->OnAdaptationChanged(
671 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
672 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100673
674 fake_clock_.AdvanceTimeMilliseconds(10000);
675 statistics_proxy_.reset();
676 EXPECT_EQ(1,
677 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
678 EXPECT_EQ(
679 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
680}
681
asapersson6eca98b2017-04-04 23:40:50 -0700682TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700683 // First RTP packet sent.
684 UpdateDataCounters(kFirstSsrc);
685
asapersson09f05612017-05-15 23:40:18 -0700686 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200687 SendStatisticsProxy::AdaptationSteps cpu_counts;
688 SendStatisticsProxy::AdaptationSteps quality_counts;
689 quality_counts.num_framerate_reductions = absl::nullopt;
690 quality_counts.num_resolution_reductions = absl::nullopt;
691 statistics_proxy_->OnAdaptationChanged(
692 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
693 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700694 fake_clock_.AdvanceTimeMilliseconds(10000);
695
asapersson09f05612017-05-15 23:40:18 -0700696 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700697 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200698 quality_counts.num_framerate_reductions = 0;
699 statistics_proxy_->OnAdaptationChanged(
700 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
701 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700702 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200703 statistics_proxy_->OnAdaptationChanged(
704 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
705 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700706 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200707 statistics_proxy_->OnAdaptationChanged(
708 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
709 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700710 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200711 statistics_proxy_->OnAdaptationChanged(
712 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
713 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700714
asapersson09f05612017-05-15 23:40:18 -0700715 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200716 quality_counts.num_framerate_reductions = absl::nullopt;
717 statistics_proxy_->OnAdaptationChanged(
718 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
719 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700720 fake_clock_.AdvanceTimeMilliseconds(30000);
721
asapersson09f05612017-05-15 23:40:18 -0700722 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700723 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200724 quality_counts.num_resolution_reductions = 0;
725 statistics_proxy_->OnAdaptationChanged(
726 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
727 quality_counts);
728 statistics_proxy_->OnAdaptationChanged(
729 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
730 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700731 fake_clock_.AdvanceTimeMilliseconds(10000);
732
asapersson09f05612017-05-15 23:40:18 -0700733 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200734 quality_counts.num_resolution_reductions = absl::nullopt;
735 statistics_proxy_->OnAdaptationChanged(
736 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
737 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700738 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200739 statistics_proxy_->OnAdaptationChanged(
740 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
741 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700742 fake_clock_.AdvanceTimeMilliseconds(20000);
743
asapersson0944a802017-04-07 00:57:58 -0700744 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700745 statistics_proxy_.reset();
746 EXPECT_EQ(1,
747 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
748 EXPECT_EQ(
749 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
750}
751
asapersson0944a802017-04-07 00:57:58 -0700752TEST_F(SendStatisticsProxyTest,
753 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
754 // First RTP packet sent.
755 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700756
asapersson0944a802017-04-07 00:57:58 -0700757 // Suspend and resume video.
758 statistics_proxy_->OnSuspendChange(true);
759 fake_clock_.AdvanceTimeMilliseconds(5000);
760 statistics_proxy_->OnSuspendChange(false);
761
762 // Min runtime has passed but scaling not enabled.
763 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
764 statistics_proxy_.reset();
765 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
766 EXPECT_EQ(0,
767 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
768}
769
770TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
771 // First RTP packet sent.
772 UpdateDataCounters(kFirstSsrc);
773
asapersson09f05612017-05-15 23:40:18 -0700774 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200775 SendStatisticsProxy::AdaptationSteps cpu_counts;
776 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700777 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200778 statistics_proxy_->OnAdaptationChanged(
779 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
780 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700781 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200782 statistics_proxy_->OnAdaptationChanged(
783 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
784 quality_counts);
785 statistics_proxy_->OnAdaptationChanged(
786 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
787 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700788
789 // Suspend and resume video.
790 statistics_proxy_->OnSuspendChange(true);
791 fake_clock_.AdvanceTimeMilliseconds(30000);
792 statistics_proxy_->OnSuspendChange(false);
793
794 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200795 statistics_proxy_->OnAdaptationChanged(
796 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
797 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700798 fake_clock_.AdvanceTimeMilliseconds(10000);
799
800 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
801 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
808TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
809 // First RTP packet sent.
810 UpdateDataCounters(kFirstSsrc);
811
812 // Video not suspended.
813 statistics_proxy_->OnSuspendChange(false);
814 fake_clock_.AdvanceTimeMilliseconds(30000);
815
asapersson09f05612017-05-15 23:40:18 -0700816 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200817 SendStatisticsProxy::AdaptationSteps cpu_counts;
818 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700819 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200820 statistics_proxy_->OnAdaptationChanged(
821 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
822 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700823 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200824 statistics_proxy_->OnAdaptationChanged(
825 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
826 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700827
828 // Video not suspended, stats time already started.
829 statistics_proxy_->OnSuspendChange(false);
830 fake_clock_.AdvanceTimeMilliseconds(10000);
831
asapersson09f05612017-05-15 23:40:18 -0700832 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200833 cpu_counts.num_framerate_reductions = absl::nullopt;
834 cpu_counts.num_resolution_reductions = absl::nullopt;
835 statistics_proxy_->OnAdaptationChanged(
836 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
837 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700838 fake_clock_.AdvanceTimeMilliseconds(30000);
839
840 // Suspend and resume video, stats time not started when scaling not enabled.
841 statistics_proxy_->OnSuspendChange(true);
842 fake_clock_.AdvanceTimeMilliseconds(30000);
843 statistics_proxy_->OnSuspendChange(false);
844 fake_clock_.AdvanceTimeMilliseconds(30000);
845
asapersson09f05612017-05-15 23:40:18 -0700846 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700847 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200848 cpu_counts.num_framerate_reductions = 0;
849 cpu_counts.num_resolution_reductions = 0;
850 statistics_proxy_->OnAdaptationChanged(
851 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
852 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700853 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200854 statistics_proxy_->OnAdaptationChanged(
855 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
856 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700857
858 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
859 statistics_proxy_.reset();
860 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
861 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
862}
863
864TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
865 // First RTP packet sent.
866 UpdateDataCounters(kFirstSsrc);
867
868 // Video suspended.
869 statistics_proxy_->OnSuspendChange(true);
870
asapersson09f05612017-05-15 23:40:18 -0700871 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200872 SendStatisticsProxy::AdaptationSteps cpu_counts;
873 SendStatisticsProxy::AdaptationSteps quality_counts;
874 statistics_proxy_->OnAdaptationChanged(
875 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
876 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700877 fake_clock_.AdvanceTimeMilliseconds(10000);
878
879 // Resume video, stats time started.
880 // Adapt changes: 1, elapsed time: 10 sec.
881 statistics_proxy_->OnSuspendChange(false);
882 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200883 statistics_proxy_->OnAdaptationChanged(
884 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
885 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700886
887 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
888 statistics_proxy_.reset();
889 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
890 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
891}
892
893TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700894 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700895 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200896 SendStatisticsProxy::AdaptationSteps cpu_counts;
897 SendStatisticsProxy::AdaptationSteps quality_counts;
898 statistics_proxy_->OnAdaptationChanged(
899 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
900 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700901 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700902 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700903
asapersson0944a802017-04-07 00:57:58 -0700904 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700905 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200906 statistics_proxy_->OnAdaptationChanged(
907 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
908 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700909 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700910
asapersson0944a802017-04-07 00:57:58 -0700911 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700912 statistics_proxy_.reset();
913 EXPECT_EQ(1,
914 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
915 EXPECT_EQ(
916 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
917}
918
919TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700920 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200921 SendStatisticsProxy::AdaptationSteps cpu_counts;
922 SendStatisticsProxy::AdaptationSteps quality_counts;
923 statistics_proxy_->OnAdaptationChanged(
924 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
925 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700926 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200927 cpu_counts.num_framerate_reductions = absl::nullopt;
928 cpu_counts.num_resolution_reductions = absl::nullopt;
929 statistics_proxy_->OnAdaptationChanged(
930 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
931 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700932
933 // Send first packet, scaling disabled.
934 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700935 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700936 fake_clock_.AdvanceTimeMilliseconds(60000);
937
asapersson09f05612017-05-15 23:40:18 -0700938 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200939 cpu_counts.num_resolution_reductions = 0;
940 statistics_proxy_->OnAdaptationChanged(
941 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
942 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700943 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700944 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700945
asapersson0944a802017-04-07 00:57:58 -0700946 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700947 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200948 statistics_proxy_->OnAdaptationChanged(
949 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
950 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700951
asapersson0944a802017-04-07 00:57:58 -0700952 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700953 statistics_proxy_.reset();
954 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
955 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
956}
957
958TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700959 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700960 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200961 SendStatisticsProxy::AdaptationSteps cpu_counts;
962 SendStatisticsProxy::AdaptationSteps quality_counts;
963 quality_counts.num_framerate_reductions = absl::nullopt;
964 quality_counts.num_resolution_reductions = absl::nullopt;
965 statistics_proxy_->OnAdaptationChanged(
966 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
967 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700968
asapersson0944a802017-04-07 00:57:58 -0700969 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200970 statistics_proxy_->OnAdaptationChanged(
971 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
972 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700973 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200974 statistics_proxy_->OnAdaptationChanged(
975 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
976 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700977 fake_clock_.AdvanceTimeMilliseconds(9000);
978
979 // Switch content type, real-time stats should be updated.
980 VideoEncoderConfig config;
981 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +0200982 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -0700983 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
984 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
985 EXPECT_EQ(0,
986 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
987
asapersson0944a802017-04-07 00:57:58 -0700988 // First RTP packet sent, scaling enabled.
989 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200990 statistics_proxy_->OnAdaptationChanged(
991 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
992 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700993
asapersson0944a802017-04-07 00:57:58 -0700994 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200995 statistics_proxy_->OnAdaptationChanged(
996 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
997 quality_counts);
998 statistics_proxy_->OnAdaptationChanged(
999 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1000 quality_counts);
1001 statistics_proxy_->OnAdaptationChanged(
1002 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1003 quality_counts);
1004 statistics_proxy_->OnAdaptationChanged(
1005 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1006 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001007 fake_clock_.AdvanceTimeMilliseconds(120000);
1008
1009 statistics_proxy_.reset();
1010 EXPECT_EQ(1, metrics::NumSamples(
1011 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1012 EXPECT_EQ(1, metrics::NumEvents(
1013 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1014 EXPECT_EQ(0, metrics::NumSamples(
1015 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
1016}
1017
asapersson59bac1a2016-01-07 23:36:00 -08001018TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001019 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001020 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1021
Pera48ddb72016-09-29 11:48:50 +02001022 // No switch, stats should not be updated.
1023 VideoEncoderConfig config;
1024 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001025 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001026 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001027
1028 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001029 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001030 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001031 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001032}
1033
asapersson320e45a2016-11-29 01:40:35 -08001034TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1035 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1036 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001037
asapersson320e45a2016-11-29 01:40:35 -08001038 statistics_proxy_.reset();
1039 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1040 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1041 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1042 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1043}
1044
1045TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001046 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001047 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001048 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1049 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1050 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001051 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001052
1053 // Not enough samples, stats should not be updated.
1054 for (int i = 0; i < kMinSamples - 1; ++i) {
1055 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001056 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001057 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1058 }
Åsa Persson0122e842017-10-16 12:19:23 +02001059 SetUp(); // Reset stats proxy also causes histograms to be reported.
1060 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1061 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1062
1063 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001064 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001065 for (int i = 0; i < kMinSamples; ++i) {
1066 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001067 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001068 encoded_image._encodedWidth = kWidth;
1069 encoded_image._encodedHeight = kHeight;
1070 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1071 encoded_image._encodedWidth = kWidth / 2;
1072 encoded_image._encodedHeight = kHeight / 2;
1073 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1074 }
1075
asapersson320e45a2016-11-29 01:40:35 -08001076 statistics_proxy_.reset();
1077 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1078 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1079 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1080 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1081}
1082
1083TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1084 const int kFps = 20;
1085 const int kMinPeriodicSamples = 6;
1086 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1087 for (int i = 0; i <= frames; ++i) {
1088 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1089 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1090 }
1091 statistics_proxy_.reset();
1092 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1093 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1094}
1095
1096TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1097 EncodedImage encoded_image;
1098 const int kFps = 20;
1099 const int kMinPeriodicSamples = 6;
1100 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001101 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001102 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001103 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001104 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1105 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001106 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1107 }
1108 statistics_proxy_.reset();
1109 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1110 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1111}
1112
1113TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1114 const int kFps = 20;
1115 const int kSuspendTimeMs = 10000;
1116 const int kMinPeriodicSamples = 6;
1117 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1118 for (int i = 0; i < frames; ++i) {
1119 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1120 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1121 }
1122 // Suspend.
1123 statistics_proxy_->OnSuspendChange(true);
1124 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1125
1126 for (int i = 0; i < frames; ++i) {
1127 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1128 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1129 }
1130 // Suspended time interval should not affect the framerate.
1131 statistics_proxy_.reset();
1132 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1133 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1134}
1135
1136TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1137 EncodedImage encoded_image;
1138 const int kFps = 20;
1139 const int kSuspendTimeMs = 10000;
1140 const int kMinPeriodicSamples = 6;
1141 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001142 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001143 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001144 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001145 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1146 }
1147 // Suspend.
1148 statistics_proxy_->OnSuspendChange(true);
1149 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1150
Åsa Persson0122e842017-10-16 12:19:23 +02001151 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001152 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001153 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001154 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1155 }
1156 // Suspended time interval should not affect the framerate.
1157 statistics_proxy_.reset();
1158 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1159 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1160}
1161
asaperssonf4e44af2017-04-19 02:01:06 -07001162TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001163 SendStatisticsProxy::AdaptationSteps cpu_counts;
1164 SendStatisticsProxy::AdaptationSteps quality_counts;
1165 cpu_counts.num_resolution_reductions = absl::nullopt;
1166 statistics_proxy_->OnAdaptationChanged(
1167 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1168 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001169
1170 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1171 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1172
1173 statistics_proxy_.reset();
1174 EXPECT_EQ(0,
1175 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1176}
1177
1178TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001179 SendStatisticsProxy::AdaptationSteps cpu_counts;
1180 SendStatisticsProxy::AdaptationSteps quality_counts;
1181 cpu_counts.num_resolution_reductions = 0;
1182 statistics_proxy_->OnAdaptationChanged(
1183 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1184 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001185
perkj803d97f2016-11-01 11:45:46 -07001186 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1187 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1188
Niels Möller213618e2018-07-24 09:29:58 +02001189 cpu_counts.num_resolution_reductions = 1;
1190 statistics_proxy_->OnAdaptationChanged(
1191 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1192 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001193
1194 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1195 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1196
1197 statistics_proxy_.reset();
1198 EXPECT_EQ(1,
1199 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1200 EXPECT_EQ(
1201 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1202}
1203
asapersson4374a092016-07-27 00:39:09 -07001204TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1205 const int64_t kTimeSec = 3;
1206 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1207 statistics_proxy_.reset();
1208 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1209 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1210 kTimeSec));
1211}
1212
1213TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1214 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1215 statistics_proxy_.reset();
1216 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1217}
1218
asapersson66d4b372016-12-19 06:50:53 -08001219TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1220 // First RTP packet sent.
1221 UpdateDataCounters(kFirstSsrc);
1222
1223 // Min runtime has passed.
1224 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1225 statistics_proxy_.reset();
1226 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1227 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1228}
1229
1230TEST_F(SendStatisticsProxyTest,
1231 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1232 // First RTP packet sent.
1233 UpdateDataCounters(kFirstSsrc);
1234
1235 // Min runtime has not passed.
1236 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1237 statistics_proxy_.reset();
1238 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1239 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1240}
1241
1242TEST_F(SendStatisticsProxyTest,
1243 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1244 // First RTP packet not sent.
1245 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1246 statistics_proxy_.reset();
1247 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1248}
1249
1250TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1251 // First RTP packet sent and min runtime passed.
1252 UpdateDataCounters(kFirstSsrc);
1253
1254 // No change. Video: 10000 ms, paused: 0 ms (0%).
1255 statistics_proxy_->OnSetEncoderTargetRate(50000);
1256 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1257 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1258
1259 statistics_proxy_.reset();
1260 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1261 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1262 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1263 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1264}
1265
1266TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1267 // First RTP packet sent and min runtime passed.
1268 UpdateDataCounters(kFirstSsrc);
1269
1270 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1271 statistics_proxy_->OnSetEncoderTargetRate(50000);
1272 fake_clock_.AdvanceTimeMilliseconds(7000);
1273 statistics_proxy_->OnSetEncoderTargetRate(0);
1274 fake_clock_.AdvanceTimeMilliseconds(3000);
1275 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1276
1277 statistics_proxy_.reset();
1278 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1279 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1280 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1281 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1282}
1283
1284TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1285 // First RTP packet sent.
1286 UpdateDataCounters(kFirstSsrc);
1287
1288 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1289 statistics_proxy_->OnSetEncoderTargetRate(0);
1290 fake_clock_.AdvanceTimeMilliseconds(1000);
1291 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1292 fake_clock_.AdvanceTimeMilliseconds(7000);
1293 statistics_proxy_->OnSetEncoderTargetRate(60000);
1294 fake_clock_.AdvanceTimeMilliseconds(3000);
1295 statistics_proxy_->OnSetEncoderTargetRate(0);
1296 fake_clock_.AdvanceTimeMilliseconds(250);
1297 statistics_proxy_->OnSetEncoderTargetRate(0);
1298 fake_clock_.AdvanceTimeMilliseconds(750);
1299 statistics_proxy_->OnSetEncoderTargetRate(60000);
1300 fake_clock_.AdvanceTimeMilliseconds(5000);
1301 statistics_proxy_->OnSetEncoderTargetRate(50000);
1302 fake_clock_.AdvanceTimeMilliseconds(4000);
1303 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1304
1305 statistics_proxy_.reset();
1306 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1307 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1308 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1309 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1310}
1311
1312TEST_F(SendStatisticsProxyTest,
1313 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1314 // First RTP packet sent.
1315 UpdateDataCounters(kFirstSsrc);
1316 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1317
1318 // Min runtime has not passed.
1319 statistics_proxy_->OnSetEncoderTargetRate(50000);
1320 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1321 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1322
1323 statistics_proxy_.reset();
1324 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1325}
1326
asapersson118ef002016-03-31 00:00:19 -07001327TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001328 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001329 CodecSpecificInfo codec_info;
1330 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001331
perkj803d97f2016-11-01 11:45:46 -07001332 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001333 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001334 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001335 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001336 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001337 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001338 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001339 }
1340 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001341 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1342 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1343 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1344 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001345}
1346
1347TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1348 VideoSendStream::Config config(nullptr);
1349 config.rtp.ssrcs.push_back(kFirstSsrc);
1350 statistics_proxy_.reset(new SendStatisticsProxy(
1351 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1352
asapersson118ef002016-03-31 00:00:19 -07001353 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001354 CodecSpecificInfo codec_info;
1355 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001356
perkj803d97f2016-11-01 11:45:46 -07001357 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001358 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001359 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001360 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001361 }
1362 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001363 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1364 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001365}
1366
asapersson5265fed2016-04-18 02:58:47 -07001367TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001368 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001369 CodecSpecificInfo codec_info;
1370 codec_info.codecType = kVideoCodecVP9;
1371 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001372
perkj803d97f2016-11-01 11:45:46 -07001373 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001374 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001375 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001376 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001377 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001378 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001379 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001380 }
1381 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001382 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1383 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1384 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1385 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001386}
1387
1388TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1389 VideoSendStream::Config config(nullptr);
1390 config.rtp.ssrcs.push_back(kFirstSsrc);
1391 statistics_proxy_.reset(new SendStatisticsProxy(
1392 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1393
asapersson5265fed2016-04-18 02:58:47 -07001394 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001395 CodecSpecificInfo codec_info;
1396 codec_info.codecType = kVideoCodecVP9;
1397 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001398
perkj803d97f2016-11-01 11:45:46 -07001399 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001400 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001401 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001402 }
1403 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001404 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1405 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001406}
1407
asapersson827cab32016-11-02 09:08:47 -07001408TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1409 EncodedImage encoded_image;
1410 CodecSpecificInfo codec_info;
1411 codec_info.codecType = kVideoCodecH264;
1412
1413 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001414 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001415 encoded_image.qp_ = kQpIdx0;
1416 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001417 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001418 encoded_image.qp_ = kQpIdx1;
1419 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001420 }
1421 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001422 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1423 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1424 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1425 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001426}
1427
asapersson4ee70462016-10-31 04:05:12 -07001428TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001429 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1430 // Configure one stream.
1431 VideoEncoderConfig config;
1432 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1433 VideoStream stream1;
1434 stream1.width = kWidth;
1435 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001436 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001437
1438 const int64_t kMaxEncodedFrameWindowMs = 800;
1439 const int kFps = 20;
1440 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1441 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1442 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1443
1444 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001445 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001446 encoded_image._encodedWidth = kWidth;
1447 encoded_image._encodedHeight = kHeight;
1448 for (int i = 0; i < kMinSamples; ++i) {
1449 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001450 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1451 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001452 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001453 }
asapersson4ee70462016-10-31 04:05:12 -07001454
1455 // Histograms are updated when the statistics_proxy_ is deleted.
1456 statistics_proxy_.reset();
1457 EXPECT_EQ(0, metrics::NumSamples(
1458 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1459 EXPECT_EQ(0, metrics::NumSamples(
1460 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1461}
1462
1463TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001464 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1465 // Configure two streams.
1466 VideoEncoderConfig config;
1467 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1468 VideoStream stream1;
1469 stream1.width = kWidth / 2;
1470 stream1.height = kHeight / 2;
1471 VideoStream stream2;
1472 stream2.width = kWidth;
1473 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001474 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001475
1476 const int64_t kMaxEncodedFrameWindowMs = 800;
1477 const int kFps = 20;
1478 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1479 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1480 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1481
1482 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001483 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001484 for (int i = 0; i < kMinSamples; ++i) {
1485 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001486 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1487 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001488 encoded_image._encodedWidth = kWidth;
1489 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001490 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001491 encoded_image._encodedWidth = kWidth / 2;
1492 encoded_image._encodedHeight = kHeight / 2;
1493 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1494 }
asapersson4ee70462016-10-31 04:05:12 -07001495
1496 // Histograms are updated when the statistics_proxy_ is deleted.
1497 statistics_proxy_.reset();
1498 EXPECT_EQ(1, metrics::NumSamples(
1499 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1500 EXPECT_EQ(1, metrics::NumEvents(
1501 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1502 // No resolution disabled.
1503 EXPECT_EQ(0, metrics::NumSamples(
1504 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1505}
1506
1507TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001508 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1509 // Configure two streams.
1510 VideoEncoderConfig config;
1511 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1512 VideoStream stream1;
1513 stream1.width = kWidth / 2;
1514 stream1.height = kHeight / 2;
1515 VideoStream stream2;
1516 stream2.width = kWidth;
1517 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001518 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001519
1520 const int64_t kMaxEncodedFrameWindowMs = 800;
1521 const int kFps = 20;
1522 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1523 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1524 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1525
1526 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001527 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001528 encoded_image._encodedWidth = kWidth / 2;
1529 encoded_image._encodedHeight = kHeight / 2;
1530 for (int i = 0; i < kMinSamples; ++i) {
1531 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001532 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1533 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001534 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001535 }
asapersson4ee70462016-10-31 04:05:12 -07001536
1537 // Histograms are updated when the statistics_proxy_ is deleted.
1538 statistics_proxy_.reset();
1539 EXPECT_EQ(1, metrics::NumSamples(
1540 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1541 EXPECT_EQ(1, metrics::NumEvents(
1542 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001543 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001544 EXPECT_EQ(1, metrics::NumSamples(
1545 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001546 EXPECT_EQ(1, metrics::NumEvents(
1547 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001548}
1549
1550TEST_F(SendStatisticsProxyTest,
1551 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001552 SendStatisticsProxy::AdaptationSteps cpu_counts;
1553 SendStatisticsProxy::AdaptationSteps quality_counts;
1554 quality_counts.num_resolution_reductions = absl::nullopt;
1555 statistics_proxy_->OnAdaptationChanged(
1556 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1557 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001558 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001559 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001560 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001561 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001562
1563 // Histograms are updated when the statistics_proxy_ is deleted.
1564 statistics_proxy_.reset();
1565 EXPECT_EQ(
1566 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1567 EXPECT_EQ(0, metrics::NumSamples(
1568 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1569}
1570
1571TEST_F(SendStatisticsProxyTest,
1572 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001573 SendStatisticsProxy::AdaptationSteps cpu_counts;
1574 SendStatisticsProxy::AdaptationSteps quality_counts;
1575 quality_counts.num_resolution_reductions = 0;
1576 statistics_proxy_->OnAdaptationChanged(
1577 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1578 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001579 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001580 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001581 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001582 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001583
1584 // Histograms are updated when the statistics_proxy_ is deleted.
1585 statistics_proxy_.reset();
1586 EXPECT_EQ(
1587 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1588 EXPECT_EQ(1, metrics::NumEvents(
1589 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1590 // No resolution downscale.
1591 EXPECT_EQ(0, metrics::NumSamples(
1592 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1593}
1594
1595TEST_F(SendStatisticsProxyTest,
1596 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1597 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001598 SendStatisticsProxy::AdaptationSteps cpu_counts;
1599 SendStatisticsProxy::AdaptationSteps quality_counts;
1600 quality_counts.num_resolution_reductions = kDownscales;
1601 statistics_proxy_->OnAdaptationChanged(
1602 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1603 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001604 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001605 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001606 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001607 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001608 // Histograms are updated when the statistics_proxy_ is deleted.
1609 statistics_proxy_.reset();
1610 EXPECT_EQ(
1611 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1612 EXPECT_EQ(1, metrics::NumEvents(
1613 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1614 // Resolution downscales.
1615 EXPECT_EQ(1, metrics::NumSamples(
1616 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1617 EXPECT_EQ(
1618 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1619 kDownscales));
1620}
1621
1622TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1623 // Initially false.
1624 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001625
Åsa Perssonaa329e72017-12-15 15:54:44 +01001626 // Configure two streams.
1627 VideoEncoderConfig config;
1628 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1629 VideoStream stream1;
1630 stream1.width = kWidth / 2;
1631 stream1.height = kHeight / 2;
1632 VideoStream stream2;
1633 stream2.width = kWidth;
1634 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001635 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001636
1637 const int64_t kMaxEncodedFrameWindowMs = 800;
1638 const int kFps = 20;
1639 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1640 kFps * kMaxEncodedFrameWindowMs / 1000;
1641
1642 // One stream encoded.
1643 EncodedImage encoded_image;
1644 encoded_image._encodedWidth = kWidth / 2;
1645 encoded_image._encodedHeight = kHeight / 2;
1646 for (int i = 0; i < kMinSamples; ++i) {
1647 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001648 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1649 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001650 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1651 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1652 }
1653
1654 // First frame removed from EncodedFrameMap, stats updated.
1655 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001656 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08001657 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1658 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1659
Åsa Perssonaa329e72017-12-15 15:54:44 +01001660 // Two streams encoded.
1661 for (int i = 0; i < kMinSamples; ++i) {
1662 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001663 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1664 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001665 encoded_image._encodedWidth = kWidth;
1666 encoded_image._encodedHeight = kHeight;
1667 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1668 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1669 encoded_image._encodedWidth = kWidth / 2;
1670 encoded_image._encodedHeight = kHeight / 2;
1671 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1672 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1673 }
1674
1675 // First frame with two streams removed, expect no resolution limit.
1676 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001677 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1678 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001679 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1680 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001681
1682 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02001683 SendStatisticsProxy::AdaptationSteps cpu_counts;
1684 SendStatisticsProxy::AdaptationSteps quality_counts;
1685 quality_counts.num_resolution_reductions = 1;
1686 statistics_proxy_->OnAdaptationChanged(
1687 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1688 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001689 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1690 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1691}
1692
asapersson66d4b372016-12-19 06:50:53 -08001693TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1694 // Initially zero.
1695 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1696
1697 const int kBitrate = 100000;
1698 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1699 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1700
1701 statistics_proxy_->OnSetEncoderTargetRate(0);
1702 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1703}
1704
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001705TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001706 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07001707 std::max(*absl::c_max_element(config_.rtp.ssrcs),
1708 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001709 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001710 // From RtcpStatisticsCallback.
1711 RtcpStatistics rtcp_stats;
1712 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001713 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001714
1715 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001716 uint32_t total = 0;
1717 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001718 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001719 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001720
1721 // From FrameCountObserver.
1722 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001723 FrameCounts frame_counts;
1724 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001725 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001726
1727 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1728 EXPECT_TRUE(stats.substreams.empty());
1729}
1730
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001731TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1732 static const int kEncodedWidth = 123;
1733 static const int kEncodedHeight = 81;
1734 EncodedImage encoded_image;
1735 encoded_image._encodedWidth = kEncodedWidth;
1736 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001737 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001738
kjellander02b3d272016-04-20 05:05:54 -07001739 CodecSpecificInfo codec_info;
1740 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001741
kjellander02b3d272016-04-20 05:05:54 -07001742 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001743 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001744 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001745
1746 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001747 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1748 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1749 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1750 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001751
1752 // Forward almost to timeout, this should not have removed stats.
1753 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1754 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001755 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1756 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001757
1758 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1759 // resolution still times out (no global timeout for all stats).
1760 RtcpStatistics rtcp_statistics;
1761 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1762 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1763
1764 // Report stats for second SSRC to make sure it's not outdated along with the
1765 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001766 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001767
1768 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1769 // reported, but substream 1 should.
1770 fake_clock_.AdvanceTimeMilliseconds(1);
1771 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001772 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1773 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1774 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1775 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001776}
1777
Peter Boström20f3f942015-05-15 11:33:39 +02001778TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1779 static const int kEncodedWidth = 123;
1780 static const int kEncodedHeight = 81;
1781 EncodedImage encoded_image;
1782 encoded_image._encodedWidth = kEncodedWidth;
1783 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001784 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02001785
kjellander02b3d272016-04-20 05:05:54 -07001786 CodecSpecificInfo codec_info;
1787 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02001788
kjellander02b3d272016-04-20 05:05:54 -07001789 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001790 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001791 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001792
1793 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1794 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1795 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1796 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1797 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1798 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1799}
1800
1801TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001802 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001803 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1804 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1805 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1806
1807 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1808
1809 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001810 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001811 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001812 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001813 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1814 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1815 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1816}
1817
sprang07fb9be2016-02-24 07:55:00 -08001818TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1819 RtcpPacketTypeCounterObserver* proxy =
1820 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1821 RtcpPacketTypeCounter counters;
1822 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1823 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1824 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1825
1826 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1827
1828 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1829 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1830 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1831 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1832 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1833
1834 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1835 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1836
1837 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001838 VideoEncoderConfig config;
1839 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001840 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001841
asapersson01d70a32016-05-20 06:29:46 -07001842 EXPECT_EQ(1,
1843 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1844 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1845 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1846 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001847 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1848
1849 const int kRate = 60 * 2; // Packets per minute with two streams.
1850
asapersson01d70a32016-05-20 06:29:46 -07001851 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1852 1 * kRate));
1853 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1854 2 * kRate));
1855 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1856 3 * kRate));
1857 EXPECT_EQ(
1858 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1859 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001860
1861 // New start time but same counter values.
1862 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1863 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1864
1865 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1866
1867 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1868 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1869 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1870 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1871 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1872
1873 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1874 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1875
1876 SetUp(); // Reset stats proxy also causes histograms to be reported.
1877
asapersson01d70a32016-05-20 06:29:46 -07001878 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001879 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001880 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001881 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001882 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001883 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1884 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001885 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001886 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1887
asapersson01d70a32016-05-20 06:29:46 -07001888 EXPECT_EQ(1, metrics::NumEvents(
1889 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1890 1 * kRate));
1891 EXPECT_EQ(1, metrics::NumEvents(
1892 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1893 2 * kRate));
1894 EXPECT_EQ(1, metrics::NumEvents(
1895 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1896 3 * kRate));
1897 EXPECT_EQ(1,
1898 metrics::NumEvents(
1899 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1900 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001901}
1902
asaperssona6a699a2016-11-25 03:52:46 -08001903TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1904 statistics_proxy_.reset(
1905 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1906 VideoEncoderConfig::ContentType::kRealtimeVideo));
1907
1908 StreamDataCountersCallback* proxy =
1909 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1910 StreamDataCounters counters;
1911 proxy->DataCountersUpdated(counters, kFirstSsrc);
1912 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1913
1914 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1915 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1916}
1917
1918TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1919 statistics_proxy_.reset(
1920 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1921 VideoEncoderConfig::ContentType::kRealtimeVideo));
1922
1923 StreamDataCountersCallback* proxy =
1924 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001925 StreamDataCounters counters;
1926 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001927
asapersson93e1e232017-02-06 05:18:35 -08001928 const int kMinRequiredPeriodSamples = 8;
1929 const int kPeriodIntervalMs = 2000;
1930 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1931 counters.transmitted.packets += 20;
1932 counters.transmitted.header_bytes += 500;
1933 counters.transmitted.padding_bytes += 1000;
1934 counters.transmitted.payload_bytes += 2000;
1935 counters.retransmitted.packets += 2;
1936 counters.retransmitted.header_bytes += 25;
1937 counters.retransmitted.padding_bytes += 100;
1938 counters.retransmitted.payload_bytes += 250;
1939 counters.fec = counters.retransmitted;
1940 rtx_counters.transmitted = counters.transmitted;
1941 // Advance one interval and update counters.
1942 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1943 proxy->DataCountersUpdated(counters, kFirstSsrc);
1944 proxy->DataCountersUpdated(counters, kSecondSsrc);
1945 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1946 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1947 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1948 }
asaperssona6a699a2016-11-25 03:52:46 -08001949
asaperssona6a699a2016-11-25 03:52:46 -08001950 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001951 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001952 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001953 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1954 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1955 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1956 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1957 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001958 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001959 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1960 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001961 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001962 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1963 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1964 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1965 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1966 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001967 EXPECT_EQ(1,
1968 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001969 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001970 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001971}
1972
Erik Språng22c2b482016-03-01 09:40:42 +01001973TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1974 StreamDataCountersCallback* proxy =
1975 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1976 StreamDataCounters counters;
1977 StreamDataCounters rtx_counters;
1978 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001979
asapersson93e1e232017-02-06 05:18:35 -08001980 const int kMinRequiredPeriodSamples = 8;
1981 const int kPeriodIntervalMs = 2000;
1982 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1983 counters.transmitted.packets += 20;
1984 counters.transmitted.header_bytes += 500;
1985 counters.transmitted.padding_bytes += 1000;
1986 counters.transmitted.payload_bytes += 2000;
1987 counters.retransmitted.packets += 2;
1988 counters.retransmitted.header_bytes += 25;
1989 counters.retransmitted.padding_bytes += 100;
1990 counters.retransmitted.payload_bytes += 250;
1991 counters.fec = counters.retransmitted;
1992 rtx_counters.transmitted = counters.transmitted;
1993 // Advance one interval and update counters.
1994 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1995 proxy->DataCountersUpdated(counters, kFirstSsrc);
1996 proxy->DataCountersUpdated(counters, kSecondSsrc);
1997 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1998 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1999 }
Erik Språng22c2b482016-03-01 09:40:42 +01002000
2001 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002002 VideoEncoderConfig config;
2003 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002004 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002005
asapersson93e1e232017-02-06 05:18:35 -08002006 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002007 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002008 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2009 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2010 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2011 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2012 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002013 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002014 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2015 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002016 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002017 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2018 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2019 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2020 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2021 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002022 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002023 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002024 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002025 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002026
asapersson93e1e232017-02-06 05:18:35 -08002027 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002028 // Double counter values, this should result in the same counts as before but
2029 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002030 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2031 counters.transmitted.packets += 20;
2032 counters.transmitted.header_bytes += 500;
2033 counters.transmitted.padding_bytes += 1000;
2034 counters.transmitted.payload_bytes += 2000;
2035 counters.retransmitted.packets += 2;
2036 counters.retransmitted.header_bytes += 25;
2037 counters.retransmitted.padding_bytes += 100;
2038 counters.retransmitted.payload_bytes += 250;
2039 counters.fec = counters.retransmitted;
2040 rtx_counters.transmitted = counters.transmitted;
2041 // Advance one interval and update counters.
2042 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2043 proxy->DataCountersUpdated(counters, kFirstSsrc);
2044 proxy->DataCountersUpdated(counters, kSecondSsrc);
2045 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2046 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2047 }
Erik Språng22c2b482016-03-01 09:40:42 +01002048
asapersson93e1e232017-02-06 05:18:35 -08002049 // Reset stats proxy also causes histograms to be reported.
2050 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002051
asapersson93e1e232017-02-06 05:18:35 -08002052 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002053 EXPECT_EQ(1,
2054 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002055 EXPECT_EQ(
2056 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2057 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2058 EXPECT_EQ(
2059 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2060 EXPECT_EQ(1, metrics::NumEvents(
2061 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2062 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002063 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002064 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002065 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002066 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2067 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002068 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002069 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002070 EXPECT_EQ(1, metrics::NumEvents(
2071 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2072 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2073 EXPECT_EQ(
2074 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2075 EXPECT_EQ(1, metrics::NumEvents(
2076 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2077 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002078 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002079 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002080 EXPECT_EQ(1,
2081 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002082 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2083}
Erik Språng22c2b482016-03-01 09:40:42 +01002084
asapersson93e1e232017-02-06 05:18:35 -08002085TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2086 StreamDataCountersCallback* proxy =
2087 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2088 StreamDataCounters counters;
2089 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002090
asapersson93e1e232017-02-06 05:18:35 -08002091 const int kMinRequiredPeriodSamples = 8;
2092 const int kPeriodIntervalMs = 2000;
2093 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2094 counters.transmitted.packets += 20;
2095 counters.transmitted.header_bytes += 500;
2096 counters.transmitted.payload_bytes += 2000;
2097 counters.fec = counters.retransmitted;
2098 // Advance one interval and update counters.
2099 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2100 proxy->DataCountersUpdated(counters, kFirstSsrc);
2101 }
2102
2103 // RTX enabled. No data sent over RTX.
2104 statistics_proxy_.reset();
2105 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2106 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2107}
2108
2109TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2110 VideoSendStream::Config config(nullptr);
2111 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2112 statistics_proxy_.reset(new SendStatisticsProxy(
2113 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2114
2115 StreamDataCountersCallback* proxy =
2116 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2117 StreamDataCounters counters;
2118
2119 const int kMinRequiredPeriodSamples = 8;
2120 const int kPeriodIntervalMs = 2000;
2121 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2122 counters.transmitted.packets += 20;
2123 counters.transmitted.header_bytes += 500;
2124 counters.transmitted.payload_bytes += 2000;
2125 counters.fec = counters.retransmitted;
2126 // Advance one interval and update counters.
2127 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2128 proxy->DataCountersUpdated(counters, kFirstSsrc);
2129 }
2130
2131 // RTX not enabled.
2132 statistics_proxy_.reset();
2133 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2134}
2135
2136TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2137 StreamDataCountersCallback* proxy =
2138 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2139 StreamDataCounters counters;
2140 StreamDataCounters rtx_counters;
2141
2142 const int kMinRequiredPeriodSamples = 8;
2143 const int kPeriodIntervalMs = 2000;
2144 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2145 counters.transmitted.packets += 20;
2146 counters.transmitted.header_bytes += 500;
2147 counters.transmitted.payload_bytes += 2000;
2148 // Advance one interval and update counters.
2149 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2150 proxy->DataCountersUpdated(counters, kFirstSsrc);
2151 }
2152
2153 // FEC enabled. No FEC data sent.
2154 statistics_proxy_.reset();
2155 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2156 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2157}
2158
2159TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2160 VideoSendStream::Config config(nullptr);
2161 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2162 statistics_proxy_.reset(new SendStatisticsProxy(
2163 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2164
2165 StreamDataCountersCallback* proxy =
2166 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2167 StreamDataCounters counters;
2168
2169 const int kMinRequiredPeriodSamples = 8;
2170 const int kPeriodIntervalMs = 2000;
2171 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2172 counters.transmitted.packets += 20;
2173 counters.transmitted.header_bytes += 500;
2174 counters.transmitted.payload_bytes += 2000;
2175 counters.fec = counters.retransmitted;
2176 // Advance one interval and update counters.
2177 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2178 proxy->DataCountersUpdated(counters, kFirstSsrc);
2179 }
2180
2181 // FEC not enabled.
2182 statistics_proxy_.reset();
2183 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002184}
2185
asapersson8d75ac72017-09-15 06:41:15 -07002186TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002187 const std::string kName = "encoderName";
2188 statistics_proxy_->OnEncoderImplementationChanged(kName);
2189 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002190}
2191
Sergey Silkinbb081a62018-09-04 18:34:22 +02002192TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2193 static const int kEncodedWidth = 123;
2194 static const int kEncodedHeight = 81;
2195 EncodedImage encoded_image;
2196 encoded_image._encodedWidth = kEncodedWidth;
2197 encoded_image._encodedHeight = kEncodedHeight;
2198 encoded_image.SetSpatialIndex(0);
2199
2200 CodecSpecificInfo codec_info;
2201 codec_info.codecType = kVideoCodecVP9;
2202
2203 // For first picture, it is expected that low layer updates resolution.
2204 codec_info.codecSpecific.VP9.end_of_picture = false;
2205 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2206 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2207 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2208 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2209
2210 // Top layer updates resolution.
2211 encoded_image._encodedWidth = kEncodedWidth * 2;
2212 encoded_image._encodedHeight = kEncodedHeight * 2;
2213 codec_info.codecSpecific.VP9.end_of_picture = true;
2214 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2215 stats = statistics_proxy_->GetStats();
2216 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2217 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2218
2219 // Low layer of next frame doesn't update resolution.
2220 encoded_image._encodedWidth = kEncodedWidth;
2221 encoded_image._encodedHeight = kEncodedHeight;
2222 codec_info.codecSpecific.VP9.end_of_picture = false;
2223 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2224 stats = statistics_proxy_->GetStats();
2225 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2226 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2227}
2228
asapersson8d75ac72017-09-15 06:41:15 -07002229class ForcedFallbackTest : public SendStatisticsProxyTest {
2230 public:
2231 explicit ForcedFallbackTest(const std::string& field_trials)
2232 : SendStatisticsProxyTest(field_trials) {
2233 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002234 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002235 encoded_image_._encodedWidth = kWidth;
2236 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002237 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002238 }
2239
2240 ~ForcedFallbackTest() override {}
2241
2242 protected:
2243 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002244 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2245
asapersson8d75ac72017-09-15 06:41:15 -07002246 // First frame is not updating stats, insert initial frame.
2247 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2248 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2249 }
2250 for (int i = 0; i < num_frames; ++i) {
2251 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2252 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2253 }
2254 // Add frame to include last time interval.
2255 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2256 }
2257
2258 EncodedImage encoded_image_;
2259 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002260 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002261 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2262 const int kFrameIntervalMs = 1000;
2263 const int kMinFrames = 20; // Min run time 20 sec.
2264};
2265
2266class ForcedFallbackDisabled : public ForcedFallbackTest {
2267 public:
2268 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002269 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2270 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002271};
2272
2273class ForcedFallbackEnabled : public ForcedFallbackTest {
2274 public:
2275 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002276 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2277 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002278};
2279
2280TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2281 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2282 statistics_proxy_.reset();
2283 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2284 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2285}
2286
2287TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2288 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002289 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002290 statistics_proxy_.reset();
2291 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2292 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2293 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2294 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2295}
2296
2297TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2298 codec_info_.codecType = kVideoCodecVP9;
2299 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2300 statistics_proxy_.reset();
2301 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2302 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2303}
2304
2305TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2306 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2307 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2308 statistics_proxy_.reset();
2309 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2310 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2311}
2312
2313TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002314 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002315 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2316 statistics_proxy_.reset();
2317 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2318 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2319}
2320
2321TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2322 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2323 statistics_proxy_.reset();
2324 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2325 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2326}
2327
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002328TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2329 InsertEncodedFrames(1, kFrameIntervalMs);
2330 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2331}
2332
2333TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2334 InsertEncodedFrames(1, kFrameIntervalMs);
2335 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2336}
2337
2338TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002339 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002340 InsertEncodedFrames(1, kFrameIntervalMs);
2341 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2342}
2343
2344TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2345 encoded_image_._encodedWidth = kWidth + 1;
2346 InsertEncodedFrames(1, kFrameIntervalMs);
2347 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2348}
2349
2350TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002351 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002352 InsertEncodedFrames(1, kFrameIntervalMs);
2353 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2354}
2355
2356TEST_F(ForcedFallbackDisabled,
2357 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2358 encoded_image_._encodedWidth = kWidth + 1;
2359 statistics_proxy_->OnMinPixelLimitReached();
2360 InsertEncodedFrames(1, kFrameIntervalMs);
2361 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2362}
2363
asapersson8d75ac72017-09-15 06:41:15 -07002364TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2365 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002366 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002367 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002368 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002369 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002370 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002371 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002372
2373 statistics_proxy_.reset();
2374 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2375 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2376 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2377 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2378}
2379
2380TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2381 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2382 const int kMaxFrameDiffMs = 2000;
2383
2384 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2385 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002386 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002387 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002388 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002389 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002390 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002391 InsertEncodedFrames(20, 1000);
2392 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2393 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002394 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002395 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002396 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002397 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002398 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002399 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002400 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002401
2402 statistics_proxy_.reset();
2403 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2404 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2405 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2406 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2407}
2408
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002409TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2410 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002411 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002412 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2413
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002414 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002415 statistics_proxy_.reset();
2416 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2417 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2418}
2419
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002420TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2421 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002422 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002423 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2424
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002425 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002426 statistics_proxy_.reset();
2427 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2428 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2429}
2430
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002431} // namespace webrtc