blob: 58514e526ce48556a3b22e9a70ae91c5a5726943 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
Steve Antonbd631a02019-03-28 10:51:27 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 10:51:27 -070019#include "absl/algorithm/container.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020020#include "api/units/timestamp.h"
21#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070023#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000025
26namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070027namespace {
28const uint32_t kFirstSsrc = 17;
29const uint32_t kSecondSsrc = 42;
30const uint32_t kFirstRtxSsrc = 18;
31const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080032const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080033const int kFpsPeriodicIntervalMs = 2000;
34const int kWidth = 640;
35const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070036const int kQpIdx0 = 21;
37const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010038const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080039const CodecSpecificInfo kDefaultCodecInfo = []() {
40 CodecSpecificInfo codec_info;
41 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080042 return codec_info;
43}();
asapersson5265fed2016-04-18 02:58:47 -070044} // namespace
sprang07fb9be2016-02-24 07:55:00 -080045
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000046class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000047 public:
asapersson8d75ac72017-09-15 06:41:15 -070048 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
49 explicit SendStatisticsProxyTest(const std::string& field_trials)
50 : override_field_trials_(field_trials),
51 fake_clock_(1234),
52 config_(GetTestConfig()),
53 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070054 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000055 virtual ~SendStatisticsProxyTest() {}
56
57 protected:
58 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070059 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080060 statistics_proxy_.reset(new SendStatisticsProxy(
61 &fake_clock_, GetTestConfig(),
62 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000063 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070064 for (const auto& ssrc : config_.rtp.ssrcs)
65 expected_.substreams[ssrc].is_rtx = false;
66 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
67 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000068 }
69
70 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070071 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080072 config.rtp.ssrcs.push_back(kFirstSsrc);
73 config.rtp.ssrcs.push_back(kSecondSsrc);
74 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
75 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070076 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000077 return config;
78 }
79
asaperssona6a699a2016-11-25 03:52:46 -080080 VideoSendStream::Config GetTestConfigWithFlexFec() {
81 VideoSendStream::Config config(nullptr);
82 config.rtp.ssrcs.push_back(kFirstSsrc);
83 config.rtp.ssrcs.push_back(kSecondSsrc);
84 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
85 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080086 config.rtp.flexfec.payload_type = 50;
87 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080088 return config;
89 }
90
91 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
92 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
93 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
94 stats.substreams.find(ssrc);
95 EXPECT_NE(it, stats.substreams.end());
96 return it->second;
97 }
98
asapersson66d4b372016-12-19 06:50:53 -080099 void UpdateDataCounters(uint32_t ssrc) {
100 StreamDataCountersCallback* proxy =
101 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
102 StreamDataCounters counters;
103 proxy->DataCountersUpdated(counters, ssrc);
104 }
105
sprang@webrtc.org09315702014-02-07 12:06:29 +0000106 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000107 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
108 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000109 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000110 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000111
112 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000113 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000114 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000115 it != one.substreams.end(); ++it) {
116 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
117 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000118 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000119 const VideoSendStream::StreamStats& a = it->second;
120 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000121
asapersson2e5cfcd2016-08-11 08:41:18 -0700122 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000123 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
124 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000125 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000126 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
127 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000128
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000129 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
130 b.rtp_stats.transmitted.payload_bytes);
131 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
132 b.rtp_stats.transmitted.header_bytes);
133 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
134 b.rtp_stats.transmitted.padding_bytes);
135 EXPECT_EQ(a.rtp_stats.transmitted.packets,
136 b.rtp_stats.transmitted.packets);
137 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
138 b.rtp_stats.retransmitted.packets);
139 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000140
141 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700142 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
143 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
144 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000145 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
146 }
147 }
148
asapersson8d75ac72017-09-15 06:41:15 -0700149 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000150 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800151 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000152 VideoSendStream::Config config_;
153 int avg_delay_ms_;
154 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000155 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000156 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
157 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000158};
159
160TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
161 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700162 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000163 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000164
165 // Add statistics with some arbitrary, but unique, numbers.
166 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700167 ssrc_stats.rtcp_stats.packets_lost = offset;
168 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000169 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
170 ssrc_stats.rtcp_stats.jitter = offset + 3;
171 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
172 }
asapersson35151f32016-05-02 23:44:01 -0700173 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000174 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000175
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000176 // Add statistics with some arbitrary, but unique, numbers.
177 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700178 ssrc_stats.rtcp_stats.packets_lost = offset;
179 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000180 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
181 ssrc_stats.rtcp_stats.jitter = offset + 3;
182 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
183 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000185 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000186}
187
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000188TEST_F(SendStatisticsProxyTest, Suspended) {
189 // Verify that the value is false by default.
190 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
191
192 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200193 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000194 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
195
196 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200197 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000198 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
199}
200
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000201TEST_F(SendStatisticsProxyTest, FrameCounts) {
202 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700203 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000204 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000205 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
206 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000207 FrameCounts frame_counts;
208 frame_counts.key_frames = offset;
209 frame_counts.delta_frames = offset + 1;
210 stats.frame_counts = frame_counts;
211 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000212 }
asapersson35151f32016-05-02 23:44:01 -0700213 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000214 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000215 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
216 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000217 FrameCounts frame_counts;
218 frame_counts.key_frames = offset;
219 frame_counts.delta_frames = offset + 1;
220 stats.frame_counts = frame_counts;
221 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000222 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000223
224 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000225 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000226}
227
228TEST_F(SendStatisticsProxyTest, DataCounters) {
229 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700230 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000231 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
232 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000233 size_t offset = ssrc * sizeof(StreamDataCounters);
234 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000235 counters.transmitted.payload_bytes = offset;
236 counters.transmitted.header_bytes = offset + 1;
237 counters.fec.packets = offset_uint32 + 2;
238 counters.transmitted.padding_bytes = offset + 3;
239 counters.retransmitted.packets = offset_uint32 + 4;
240 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000241 callback->DataCountersUpdated(counters, ssrc);
242 }
asapersson35151f32016-05-02 23:44:01 -0700243 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000244 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
245 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000246 size_t offset = ssrc * sizeof(StreamDataCounters);
247 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000248 counters.transmitted.payload_bytes = offset;
249 counters.transmitted.header_bytes = offset + 1;
250 counters.fec.packets = offset_uint32 + 2;
251 counters.transmitted.padding_bytes = offset + 3;
252 counters.retransmitted.packets = offset_uint32 + 4;
253 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000254 callback->DataCountersUpdated(counters, ssrc);
255 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000256
257 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000258 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000259}
260
261TEST_F(SendStatisticsProxyTest, Bitrate) {
262 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700263 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700264 uint32_t total;
265 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000266 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700267 total = ssrc;
268 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000269 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700270 expected_.substreams[ssrc].total_bitrate_bps = total;
271 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000272 }
asapersson35151f32016-05-02 23:44:01 -0700273 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700274 uint32_t total;
275 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000276 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700277 total = ssrc;
278 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000279 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700280 expected_.substreams[ssrc].total_bitrate_bps = total;
281 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000282 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000283
284 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000285 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000286}
287
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000288TEST_F(SendStatisticsProxyTest, SendSideDelay) {
289 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700290 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000291 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
292 // stream.
293 int avg_delay_ms = ssrc;
294 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200295 uint64_t total_packet_send_delay_ms = ssrc + 2;
296 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
297 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000298 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
299 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200300 expected_.substreams[ssrc].total_packet_send_delay_ms =
301 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000302 }
asapersson35151f32016-05-02 23:44:01 -0700303 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000304 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
305 // stream.
306 int avg_delay_ms = ssrc;
307 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200308 uint64_t total_packet_send_delay_ms = ssrc + 2;
309 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
310 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000311 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
312 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200313 expected_.substreams[ssrc].total_packet_send_delay_ms =
314 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000315 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000316 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000317 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000318}
319
Peter Boströme4499152016-02-05 11:13:28 +0100320TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800321 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200322 int encode_usage_percent = 80;
323 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
324 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800325
326 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
327 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200328 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800329}
330
Henrik Boström5684af52019-04-02 15:05:21 +0200331TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
332 const int kEncodeUsagePercent = 0; // Don't care for this test.
333 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
334 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
335 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
336 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
337 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
338}
339
sakal43536c32016-10-24 01:46:43 -0700340TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
341 EncodedImage encoded_image;
342 CodecSpecificInfo codec_info;
343 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
344 for (uint32_t i = 1; i <= 3; ++i) {
345 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
346 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
347 }
348}
349
sakal87da4042016-10-31 06:53:47 -0700350TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
351 EncodedImage encoded_image;
352 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200353 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700354 encoded_image.qp_ = 3;
355 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100356 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700357 encoded_image.qp_ = 127;
358 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100359 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700360}
361
362TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
363 EncodedImage encoded_image;
364 CodecSpecificInfo codec_info;
365 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200366 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700367 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200368 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700369}
370
Henrik Boström23aff9b2019-05-20 15:15:38 +0200371TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
372 const uint32_t kTargetBytesPerSecond = 100000;
373 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
374 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
375
376 EncodedImage encoded_image;
377 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
378 // On the first frame we don't know the frame rate yet, calculation yields
379 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
380 // increment by a full |kTargetBytesPerSecond|.
381 EXPECT_EQ(kTargetBytesPerSecond,
382 statistics_proxy_->GetStats().total_encoded_bytes_target);
383}
384
385TEST_F(SendStatisticsProxyTest,
386 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
387 const uint32_t kTargetBytesPerSecond = 100000;
388 const int kInterframeDelayMs = 100;
389
390 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
391 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
392 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
393 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
394 // this test can stop relying on rtc::ScopedFakeClock.
395 rtc::ScopedFakeClock fake_global_clock;
396 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
397
398 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
399 EncodedImage encoded_image;
400
401 // First frame
402 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
403 uint64_t first_total_encoded_bytes_target =
404 statistics_proxy_->GetStats().total_encoded_bytes_target;
405 // Second frame
406 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
407 fake_global_clock.SetTime(Timestamp::ms(fake_clock_.TimeInMilliseconds()));
408 encoded_image.SetTimestamp(encoded_image.Timestamp() +
409 90 * kInterframeDelayMs);
410 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
411
412 auto stats = statistics_proxy_->GetStats();
413 // By the time the second frame arrives, one frame has previously arrived
414 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
415 // the second frame's arrival should be 10 FPS.
416 uint64_t delta_encoded_bytes_target =
417 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
418 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
419}
420
asapersson09f05612017-05-15 23:40:18 -0700421TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200422 SendStatisticsProxy::AdaptationSteps cpu_counts;
423 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700424 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700425 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200426 cpu_counts.num_framerate_reductions = 1;
427 cpu_counts.num_resolution_reductions = 0;
428 statistics_proxy_->OnAdaptationChanged(
429 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
430 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700431 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700432 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200433 cpu_counts.num_framerate_reductions = 0;
434 cpu_counts.num_resolution_reductions = 1;
435 statistics_proxy_->OnAdaptationChanged(
436 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
437 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700438 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700439 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200440 cpu_counts.num_framerate_reductions = 1;
441 cpu_counts.num_resolution_reductions = absl::nullopt;
442 statistics_proxy_->OnAdaptationChanged(
443 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
444 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700445 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700446 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200447 cpu_counts.num_framerate_reductions = absl::nullopt;
448 cpu_counts.num_resolution_reductions = absl::nullopt;
449 statistics_proxy_->OnAdaptationChanged(
450 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
451 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700452 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
453 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
454}
455
456TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200457 SendStatisticsProxy::AdaptationSteps cpu_counts;
458 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700459 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
460 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200461 quality_counts.num_framerate_reductions = 1;
462 quality_counts.num_resolution_reductions = 0;
463 statistics_proxy_->OnAdaptationChanged(
464 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
465 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700466 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
467 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200468 quality_counts.num_framerate_reductions = 0;
469 quality_counts.num_resolution_reductions = 1;
470 statistics_proxy_->OnAdaptationChanged(
471 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
472 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700473 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
474 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200475 quality_counts.num_framerate_reductions = 1;
476 quality_counts.num_resolution_reductions = absl::nullopt;
477 statistics_proxy_->OnAdaptationChanged(
478 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
479 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700480 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
481 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200482 quality_counts.num_framerate_reductions = absl::nullopt;
483 quality_counts.num_resolution_reductions = absl::nullopt;
484 statistics_proxy_->OnAdaptationChanged(
485 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
486 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700487 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
488 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
489}
490
491TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200492 SendStatisticsProxy::AdaptationSteps cpu_counts;
493 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700494 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
495
Niels Möller213618e2018-07-24 09:29:58 +0200496 cpu_counts.num_resolution_reductions = 1;
497 statistics_proxy_->OnAdaptationChanged(
498 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
499 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700500 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700501 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
502 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
503
Niels Möller213618e2018-07-24 09:29:58 +0200504 cpu_counts.num_resolution_reductions = 2;
505 statistics_proxy_->OnAdaptationChanged(
506 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
507 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700508 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
509 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700510 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700511 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700512}
513
asapersson09f05612017-05-15 23:40:18 -0700514TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200515 SendStatisticsProxy::AdaptationSteps cpu_counts;
516 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700517 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
518
Niels Möller213618e2018-07-24 09:29:58 +0200519 quality_counts.num_framerate_reductions = 1;
520 statistics_proxy_->OnAdaptationChanged(
521 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
522 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700523 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
524 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700525 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
526
Niels Möller213618e2018-07-24 09:29:58 +0200527 quality_counts.num_framerate_reductions = 0;
528 statistics_proxy_->OnAdaptationChanged(
529 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
530 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700531 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700532 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700533 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
534 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700535}
536
asapersson09f05612017-05-15 23:40:18 -0700537TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700538 // First RTP packet sent.
539 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700540 // Min runtime has passed.
541 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
542 statistics_proxy_.reset();
543 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
544 EXPECT_EQ(0,
545 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
546}
547
548TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700549 // First RTP packet sent.
550 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700551 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200552 SendStatisticsProxy::AdaptationSteps cpu_counts;
553 SendStatisticsProxy::AdaptationSteps quality_counts;
554 statistics_proxy_->OnAdaptationChanged(
555 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
556 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700557 // Min runtime has not passed.
558 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
559 statistics_proxy_.reset();
560 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
561 EXPECT_EQ(0,
562 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
563}
564
asapersson09f05612017-05-15 23:40:18 -0700565TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700566 // First RTP packet sent.
567 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700568 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200569 SendStatisticsProxy::AdaptationSteps cpu_counts;
570 SendStatisticsProxy::AdaptationSteps quality_counts;
571 statistics_proxy_->OnAdaptationChanged(
572 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
573 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700574 // Min runtime has passed.
575 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
576 statistics_proxy_.reset();
577 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
578 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700579 EXPECT_EQ(1,
580 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
581 EXPECT_EQ(
582 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
583}
584
585TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700586 // First RTP packet sent.
587 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700588 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200589 SendStatisticsProxy::AdaptationSteps cpu_counts;
590 SendStatisticsProxy::AdaptationSteps quality_counts;
591 statistics_proxy_->OnAdaptationChanged(
592 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
593 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700594 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200595 statistics_proxy_->OnAdaptationChanged(
596 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
597 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700598 fake_clock_.AdvanceTimeMilliseconds(10000);
599 statistics_proxy_.reset();
600 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
601 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
602}
603
Åsa Persson875841d2018-01-08 08:49:53 +0100604TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
605 // First RTP packet sent.
606 UpdateDataCounters(kFirstSsrc);
607 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200608 SendStatisticsProxy::AdaptationSteps cpu_counts;
609 SendStatisticsProxy::AdaptationSteps quality_counts;
610 statistics_proxy_->OnAdaptationChanged(
611 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
612 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100613 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200614 statistics_proxy_->OnAdaptationChanged(
615 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
616 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100617 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
618 fake_clock_.AdvanceTimeMilliseconds(10000);
619 statistics_proxy_.reset();
620 EXPECT_EQ(1,
621 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
622 EXPECT_EQ(
623 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
624}
625
626TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
627 // First RTP packet sent.
628 UpdateDataCounters(kFirstSsrc);
629 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200630 SendStatisticsProxy::AdaptationSteps cpu_counts;
631 SendStatisticsProxy::AdaptationSteps quality_counts;
632 statistics_proxy_->OnAdaptationChanged(
633 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
634 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100635 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200636 quality_counts.num_resolution_reductions = 1;
637 statistics_proxy_->OnAdaptationChanged(
638 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
639 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100640 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200641 quality_counts.num_resolution_reductions = 2;
642 statistics_proxy_->OnAdaptationChanged(
643 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
644 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100645 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200646 quality_counts.num_resolution_reductions = 3;
647 statistics_proxy_->OnAdaptationChanged(
648 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
649 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100650 fake_clock_.AdvanceTimeMilliseconds(10000);
651 statistics_proxy_.reset();
652 EXPECT_EQ(1,
653 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
654 EXPECT_EQ(
655 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
656}
657
658TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
659 // First RTP packet sent.
660 UpdateDataCounters(kFirstSsrc);
661 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200662 SendStatisticsProxy::AdaptationSteps cpu_counts;
663 SendStatisticsProxy::AdaptationSteps quality_counts;
664 statistics_proxy_->OnAdaptationChanged(
665 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
666 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100667 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200668 statistics_proxy_->OnAdaptationChanged(
669 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
670 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100671 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
672 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
673 fake_clock_.AdvanceTimeMilliseconds(10000);
674 statistics_proxy_.reset();
675 EXPECT_EQ(1,
676 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
677 EXPECT_EQ(
678 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
679}
680
681TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
682 // First RTP packet sent.
683 UpdateDataCounters(kFirstSsrc);
684 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200685 SendStatisticsProxy::AdaptationSteps cpu_counts;
686 SendStatisticsProxy::AdaptationSteps quality_counts;
687 statistics_proxy_->OnAdaptationChanged(
688 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
689 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100690 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200691 quality_counts.num_resolution_reductions = 1;
692 statistics_proxy_->OnAdaptationChanged(
693 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
694 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100695 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200696 quality_counts.num_resolution_reductions = 2;
697 statistics_proxy_->OnAdaptationChanged(
698 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
699 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100700 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200701 quality_counts.num_resolution_reductions = 3;
702 statistics_proxy_->OnAdaptationChanged(
703 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
704 quality_counts);
705 quality_counts.num_framerate_reductions = 1;
706 statistics_proxy_->OnAdaptationChanged(
707 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
708 quality_counts);
709 quality_counts.num_framerate_reductions = 0;
710 statistics_proxy_->OnAdaptationChanged(
711 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
712 quality_counts);
713 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
714 statistics_proxy_->OnAdaptationChanged(
715 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
716 quality_counts);
717 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
718 statistics_proxy_->OnAdaptationChanged(
719 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
720 quality_counts);
721 quality_counts.num_resolution_reductions = 0;
722 statistics_proxy_->OnAdaptationChanged(
723 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
724 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100725
726 fake_clock_.AdvanceTimeMilliseconds(10000);
727 statistics_proxy_.reset();
728 EXPECT_EQ(1,
729 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
730 EXPECT_EQ(
731 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
732}
733
asapersson6eca98b2017-04-04 23:40:50 -0700734TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700735 // First RTP packet sent.
736 UpdateDataCounters(kFirstSsrc);
737
asapersson09f05612017-05-15 23:40:18 -0700738 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200739 SendStatisticsProxy::AdaptationSteps cpu_counts;
740 SendStatisticsProxy::AdaptationSteps quality_counts;
741 quality_counts.num_framerate_reductions = absl::nullopt;
742 quality_counts.num_resolution_reductions = absl::nullopt;
743 statistics_proxy_->OnAdaptationChanged(
744 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
745 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700746 fake_clock_.AdvanceTimeMilliseconds(10000);
747
asapersson09f05612017-05-15 23:40:18 -0700748 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700749 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200750 quality_counts.num_framerate_reductions = 0;
751 statistics_proxy_->OnAdaptationChanged(
752 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
753 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700754 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200755 statistics_proxy_->OnAdaptationChanged(
756 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
757 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700758 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200759 statistics_proxy_->OnAdaptationChanged(
760 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
761 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700762 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200763 statistics_proxy_->OnAdaptationChanged(
764 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
765 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700766
asapersson09f05612017-05-15 23:40:18 -0700767 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200768 quality_counts.num_framerate_reductions = absl::nullopt;
769 statistics_proxy_->OnAdaptationChanged(
770 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
771 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700772 fake_clock_.AdvanceTimeMilliseconds(30000);
773
asapersson09f05612017-05-15 23:40:18 -0700774 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700775 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200776 quality_counts.num_resolution_reductions = 0;
777 statistics_proxy_->OnAdaptationChanged(
778 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
779 quality_counts);
780 statistics_proxy_->OnAdaptationChanged(
781 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
782 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700783 fake_clock_.AdvanceTimeMilliseconds(10000);
784
asapersson09f05612017-05-15 23:40:18 -0700785 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200786 quality_counts.num_resolution_reductions = absl::nullopt;
787 statistics_proxy_->OnAdaptationChanged(
788 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
789 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700790 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200791 statistics_proxy_->OnAdaptationChanged(
792 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
793 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700794 fake_clock_.AdvanceTimeMilliseconds(20000);
795
asapersson0944a802017-04-07 00:57:58 -0700796 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700797 statistics_proxy_.reset();
798 EXPECT_EQ(1,
799 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
800 EXPECT_EQ(
801 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
802}
803
asapersson0944a802017-04-07 00:57:58 -0700804TEST_F(SendStatisticsProxyTest,
805 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
806 // First RTP packet sent.
807 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700808
asapersson0944a802017-04-07 00:57:58 -0700809 // Suspend and resume video.
810 statistics_proxy_->OnSuspendChange(true);
811 fake_clock_.AdvanceTimeMilliseconds(5000);
812 statistics_proxy_->OnSuspendChange(false);
813
814 // Min runtime has passed but scaling not enabled.
815 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
816 statistics_proxy_.reset();
817 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
818 EXPECT_EQ(0,
819 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
820}
821
822TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
823 // First RTP packet sent.
824 UpdateDataCounters(kFirstSsrc);
825
asapersson09f05612017-05-15 23:40:18 -0700826 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200827 SendStatisticsProxy::AdaptationSteps cpu_counts;
828 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700829 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200830 statistics_proxy_->OnAdaptationChanged(
831 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
832 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700833 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200834 statistics_proxy_->OnAdaptationChanged(
835 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
836 quality_counts);
837 statistics_proxy_->OnAdaptationChanged(
838 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
839 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700840
841 // Suspend and resume video.
842 statistics_proxy_->OnSuspendChange(true);
843 fake_clock_.AdvanceTimeMilliseconds(30000);
844 statistics_proxy_->OnSuspendChange(false);
845
846 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200847 statistics_proxy_->OnAdaptationChanged(
848 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
849 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700850 fake_clock_.AdvanceTimeMilliseconds(10000);
851
852 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
853 statistics_proxy_.reset();
854 EXPECT_EQ(1,
855 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
856 EXPECT_EQ(
857 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
858}
859
860TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
861 // First RTP packet sent.
862 UpdateDataCounters(kFirstSsrc);
863
864 // Video not suspended.
865 statistics_proxy_->OnSuspendChange(false);
866 fake_clock_.AdvanceTimeMilliseconds(30000);
867
asapersson09f05612017-05-15 23:40:18 -0700868 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200869 SendStatisticsProxy::AdaptationSteps cpu_counts;
870 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700871 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200872 statistics_proxy_->OnAdaptationChanged(
873 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
874 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700875 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200876 statistics_proxy_->OnAdaptationChanged(
877 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
878 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700879
880 // Video not suspended, stats time already started.
881 statistics_proxy_->OnSuspendChange(false);
882 fake_clock_.AdvanceTimeMilliseconds(10000);
883
asapersson09f05612017-05-15 23:40:18 -0700884 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200885 cpu_counts.num_framerate_reductions = absl::nullopt;
886 cpu_counts.num_resolution_reductions = absl::nullopt;
887 statistics_proxy_->OnAdaptationChanged(
888 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
889 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700890 fake_clock_.AdvanceTimeMilliseconds(30000);
891
892 // Suspend and resume video, stats time not started when scaling not enabled.
893 statistics_proxy_->OnSuspendChange(true);
894 fake_clock_.AdvanceTimeMilliseconds(30000);
895 statistics_proxy_->OnSuspendChange(false);
896 fake_clock_.AdvanceTimeMilliseconds(30000);
897
asapersson09f05612017-05-15 23:40:18 -0700898 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700899 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200900 cpu_counts.num_framerate_reductions = 0;
901 cpu_counts.num_resolution_reductions = 0;
902 statistics_proxy_->OnAdaptationChanged(
903 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
904 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700905 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200906 statistics_proxy_->OnAdaptationChanged(
907 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
908 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700909
910 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
911 statistics_proxy_.reset();
912 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
913 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
914}
915
916TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
917 // First RTP packet sent.
918 UpdateDataCounters(kFirstSsrc);
919
920 // Video suspended.
921 statistics_proxy_->OnSuspendChange(true);
922
asapersson09f05612017-05-15 23:40:18 -0700923 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200924 SendStatisticsProxy::AdaptationSteps cpu_counts;
925 SendStatisticsProxy::AdaptationSteps quality_counts;
926 statistics_proxy_->OnAdaptationChanged(
927 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
928 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700929 fake_clock_.AdvanceTimeMilliseconds(10000);
930
931 // Resume video, stats time started.
932 // Adapt changes: 1, elapsed time: 10 sec.
933 statistics_proxy_->OnSuspendChange(false);
934 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200935 statistics_proxy_->OnAdaptationChanged(
936 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
937 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700938
939 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
940 statistics_proxy_.reset();
941 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
942 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
943}
944
945TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700946 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700947 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200948 SendStatisticsProxy::AdaptationSteps cpu_counts;
949 SendStatisticsProxy::AdaptationSteps quality_counts;
950 statistics_proxy_->OnAdaptationChanged(
951 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
952 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700953 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700954 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700955
asapersson0944a802017-04-07 00:57:58 -0700956 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700957 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200958 statistics_proxy_->OnAdaptationChanged(
959 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
960 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700961 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700962
asapersson0944a802017-04-07 00:57:58 -0700963 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700964 statistics_proxy_.reset();
965 EXPECT_EQ(1,
966 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
967 EXPECT_EQ(
968 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
969}
970
971TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700972 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200973 SendStatisticsProxy::AdaptationSteps cpu_counts;
974 SendStatisticsProxy::AdaptationSteps quality_counts;
975 statistics_proxy_->OnAdaptationChanged(
976 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
977 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700978 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200979 cpu_counts.num_framerate_reductions = absl::nullopt;
980 cpu_counts.num_resolution_reductions = absl::nullopt;
981 statistics_proxy_->OnAdaptationChanged(
982 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
983 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700984
985 // Send first packet, scaling disabled.
986 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700987 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700988 fake_clock_.AdvanceTimeMilliseconds(60000);
989
asapersson09f05612017-05-15 23:40:18 -0700990 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200991 cpu_counts.num_resolution_reductions = 0;
992 statistics_proxy_->OnAdaptationChanged(
993 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
994 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700995 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700996 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700997
asapersson0944a802017-04-07 00:57:58 -0700998 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700999 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001000 statistics_proxy_->OnAdaptationChanged(
1001 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1002 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001003
asapersson0944a802017-04-07 00:57:58 -07001004 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001005 statistics_proxy_.reset();
1006 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1007 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
1008}
1009
1010TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001011 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001012 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001013 SendStatisticsProxy::AdaptationSteps cpu_counts;
1014 SendStatisticsProxy::AdaptationSteps quality_counts;
1015 quality_counts.num_framerate_reductions = absl::nullopt;
1016 quality_counts.num_resolution_reductions = absl::nullopt;
1017 statistics_proxy_->OnAdaptationChanged(
1018 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1019 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001020
asapersson0944a802017-04-07 00:57:58 -07001021 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001022 statistics_proxy_->OnAdaptationChanged(
1023 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1024 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001025 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +02001026 statistics_proxy_->OnAdaptationChanged(
1027 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1028 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001029 fake_clock_.AdvanceTimeMilliseconds(9000);
1030
1031 // Switch content type, real-time stats should be updated.
1032 VideoEncoderConfig config;
1033 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001034 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -07001035 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1036 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1037 EXPECT_EQ(0,
1038 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1039
asapersson0944a802017-04-07 00:57:58 -07001040 // First RTP packet sent, scaling enabled.
1041 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001042 statistics_proxy_->OnAdaptationChanged(
1043 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1044 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001045
asapersson0944a802017-04-07 00:57:58 -07001046 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001047 statistics_proxy_->OnAdaptationChanged(
1048 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1049 quality_counts);
1050 statistics_proxy_->OnAdaptationChanged(
1051 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1052 quality_counts);
1053 statistics_proxy_->OnAdaptationChanged(
1054 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1055 quality_counts);
1056 statistics_proxy_->OnAdaptationChanged(
1057 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1058 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001059 fake_clock_.AdvanceTimeMilliseconds(120000);
1060
1061 statistics_proxy_.reset();
1062 EXPECT_EQ(1, metrics::NumSamples(
1063 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1064 EXPECT_EQ(1, metrics::NumEvents(
1065 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1066 EXPECT_EQ(0, metrics::NumSamples(
1067 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
1068}
1069
asapersson59bac1a2016-01-07 23:36:00 -08001070TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001071 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001072 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1073
Pera48ddb72016-09-29 11:48:50 +02001074 // No switch, stats should not be updated.
1075 VideoEncoderConfig config;
1076 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001077 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001078 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001079
1080 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001081 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001082 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001083 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001084}
1085
asapersson320e45a2016-11-29 01:40:35 -08001086TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1087 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1088 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001089
asapersson320e45a2016-11-29 01:40:35 -08001090 statistics_proxy_.reset();
1091 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1092 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1093 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1094 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1095}
1096
1097TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001098 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001099 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001100 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1101 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1102 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001103 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001104
1105 // Not enough samples, stats should not be updated.
1106 for (int i = 0; i < kMinSamples - 1; ++i) {
1107 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001108 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001109 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1110 }
Åsa Persson0122e842017-10-16 12:19:23 +02001111 SetUp(); // Reset stats proxy also causes histograms to be reported.
1112 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1113 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1114
1115 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001116 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001117 for (int i = 0; i < kMinSamples; ++i) {
1118 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001119 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001120 encoded_image._encodedWidth = kWidth;
1121 encoded_image._encodedHeight = kHeight;
1122 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1123 encoded_image._encodedWidth = kWidth / 2;
1124 encoded_image._encodedHeight = kHeight / 2;
1125 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1126 }
1127
asapersson320e45a2016-11-29 01:40:35 -08001128 statistics_proxy_.reset();
1129 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1130 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1131 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1132 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1133}
1134
1135TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1136 const int kFps = 20;
1137 const int kMinPeriodicSamples = 6;
1138 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1139 for (int i = 0; i <= frames; ++i) {
1140 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1141 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1142 }
1143 statistics_proxy_.reset();
1144 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1145 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1146}
1147
1148TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1149 EncodedImage encoded_image;
1150 const int kFps = 20;
1151 const int kMinPeriodicSamples = 6;
1152 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001153 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001154 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001155 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001156 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1157 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001158 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1159 }
1160 statistics_proxy_.reset();
1161 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1162 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1163}
1164
1165TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1166 const int kFps = 20;
1167 const int kSuspendTimeMs = 10000;
1168 const int kMinPeriodicSamples = 6;
1169 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1170 for (int i = 0; i < frames; ++i) {
1171 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1172 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1173 }
1174 // Suspend.
1175 statistics_proxy_->OnSuspendChange(true);
1176 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1177
1178 for (int i = 0; i < frames; ++i) {
1179 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1180 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1181 }
1182 // Suspended time interval should not affect the framerate.
1183 statistics_proxy_.reset();
1184 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1185 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1186}
1187
1188TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1189 EncodedImage encoded_image;
1190 const int kFps = 20;
1191 const int kSuspendTimeMs = 10000;
1192 const int kMinPeriodicSamples = 6;
1193 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001194 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001195 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001196 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001197 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1198 }
1199 // Suspend.
1200 statistics_proxy_->OnSuspendChange(true);
1201 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1202
Åsa Persson0122e842017-10-16 12:19:23 +02001203 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001204 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001205 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001206 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1207 }
1208 // Suspended time interval should not affect the framerate.
1209 statistics_proxy_.reset();
1210 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1211 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1212}
1213
asaperssonf4e44af2017-04-19 02:01:06 -07001214TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001215 SendStatisticsProxy::AdaptationSteps cpu_counts;
1216 SendStatisticsProxy::AdaptationSteps quality_counts;
1217 cpu_counts.num_resolution_reductions = absl::nullopt;
1218 statistics_proxy_->OnAdaptationChanged(
1219 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1220 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001221
1222 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1223 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1224
1225 statistics_proxy_.reset();
1226 EXPECT_EQ(0,
1227 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1228}
1229
1230TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001231 SendStatisticsProxy::AdaptationSteps cpu_counts;
1232 SendStatisticsProxy::AdaptationSteps quality_counts;
1233 cpu_counts.num_resolution_reductions = 0;
1234 statistics_proxy_->OnAdaptationChanged(
1235 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1236 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001237
perkj803d97f2016-11-01 11:45:46 -07001238 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1239 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1240
Niels Möller213618e2018-07-24 09:29:58 +02001241 cpu_counts.num_resolution_reductions = 1;
1242 statistics_proxy_->OnAdaptationChanged(
1243 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1244 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001245
1246 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1247 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1248
1249 statistics_proxy_.reset();
1250 EXPECT_EQ(1,
1251 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1252 EXPECT_EQ(
1253 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1254}
1255
asapersson4374a092016-07-27 00:39:09 -07001256TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1257 const int64_t kTimeSec = 3;
1258 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1259 statistics_proxy_.reset();
1260 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1261 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1262 kTimeSec));
1263}
1264
1265TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1266 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1267 statistics_proxy_.reset();
1268 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1269}
1270
asapersson66d4b372016-12-19 06:50:53 -08001271TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1272 // First RTP packet sent.
1273 UpdateDataCounters(kFirstSsrc);
1274
1275 // Min runtime has passed.
1276 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1277 statistics_proxy_.reset();
1278 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1279 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1280}
1281
1282TEST_F(SendStatisticsProxyTest,
1283 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1284 // First RTP packet sent.
1285 UpdateDataCounters(kFirstSsrc);
1286
1287 // Min runtime has not passed.
1288 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1289 statistics_proxy_.reset();
1290 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1291 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1292}
1293
1294TEST_F(SendStatisticsProxyTest,
1295 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1296 // First RTP packet not sent.
1297 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1298 statistics_proxy_.reset();
1299 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1300}
1301
1302TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1303 // First RTP packet sent and min runtime passed.
1304 UpdateDataCounters(kFirstSsrc);
1305
1306 // No change. Video: 10000 ms, paused: 0 ms (0%).
1307 statistics_proxy_->OnSetEncoderTargetRate(50000);
1308 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1309 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1310
1311 statistics_proxy_.reset();
1312 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1313 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1314 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1315 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1316}
1317
1318TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1319 // First RTP packet sent and min runtime passed.
1320 UpdateDataCounters(kFirstSsrc);
1321
1322 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1323 statistics_proxy_->OnSetEncoderTargetRate(50000);
1324 fake_clock_.AdvanceTimeMilliseconds(7000);
1325 statistics_proxy_->OnSetEncoderTargetRate(0);
1326 fake_clock_.AdvanceTimeMilliseconds(3000);
1327 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1328
1329 statistics_proxy_.reset();
1330 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1331 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1332 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1333 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1334}
1335
1336TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1337 // First RTP packet sent.
1338 UpdateDataCounters(kFirstSsrc);
1339
1340 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1341 statistics_proxy_->OnSetEncoderTargetRate(0);
1342 fake_clock_.AdvanceTimeMilliseconds(1000);
1343 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1344 fake_clock_.AdvanceTimeMilliseconds(7000);
1345 statistics_proxy_->OnSetEncoderTargetRate(60000);
1346 fake_clock_.AdvanceTimeMilliseconds(3000);
1347 statistics_proxy_->OnSetEncoderTargetRate(0);
1348 fake_clock_.AdvanceTimeMilliseconds(250);
1349 statistics_proxy_->OnSetEncoderTargetRate(0);
1350 fake_clock_.AdvanceTimeMilliseconds(750);
1351 statistics_proxy_->OnSetEncoderTargetRate(60000);
1352 fake_clock_.AdvanceTimeMilliseconds(5000);
1353 statistics_proxy_->OnSetEncoderTargetRate(50000);
1354 fake_clock_.AdvanceTimeMilliseconds(4000);
1355 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1356
1357 statistics_proxy_.reset();
1358 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1359 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1360 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1361 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1362}
1363
1364TEST_F(SendStatisticsProxyTest,
1365 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1366 // First RTP packet sent.
1367 UpdateDataCounters(kFirstSsrc);
1368 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1369
1370 // Min runtime has not passed.
1371 statistics_proxy_->OnSetEncoderTargetRate(50000);
1372 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1373 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1374
1375 statistics_proxy_.reset();
1376 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1377}
1378
asapersson118ef002016-03-31 00:00:19 -07001379TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001380 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001381 CodecSpecificInfo codec_info;
1382 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001383
perkj803d97f2016-11-01 11:45:46 -07001384 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001385 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001386 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001387 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001388 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001389 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001390 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001391 }
1392 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001393 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1394 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1395 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1396 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001397}
1398
1399TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1400 VideoSendStream::Config config(nullptr);
1401 config.rtp.ssrcs.push_back(kFirstSsrc);
1402 statistics_proxy_.reset(new SendStatisticsProxy(
1403 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1404
asapersson118ef002016-03-31 00:00:19 -07001405 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001406 CodecSpecificInfo codec_info;
1407 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001408
perkj803d97f2016-11-01 11:45:46 -07001409 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001410 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001411 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001412 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001413 }
1414 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001415 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1416 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001417}
1418
asapersson5265fed2016-04-18 02:58:47 -07001419TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001420 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001421 CodecSpecificInfo codec_info;
1422 codec_info.codecType = kVideoCodecVP9;
1423 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001424
perkj803d97f2016-11-01 11:45:46 -07001425 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001426 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001427 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001428 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001429 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001430 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001431 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001432 }
1433 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001434 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1435 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1436 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1437 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001438}
1439
1440TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1441 VideoSendStream::Config config(nullptr);
1442 config.rtp.ssrcs.push_back(kFirstSsrc);
1443 statistics_proxy_.reset(new SendStatisticsProxy(
1444 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1445
asapersson5265fed2016-04-18 02:58:47 -07001446 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001447 CodecSpecificInfo codec_info;
1448 codec_info.codecType = kVideoCodecVP9;
1449 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001450
perkj803d97f2016-11-01 11:45:46 -07001451 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001452 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001453 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001454 }
1455 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001456 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1457 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001458}
1459
asapersson827cab32016-11-02 09:08:47 -07001460TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1461 EncodedImage encoded_image;
1462 CodecSpecificInfo codec_info;
1463 codec_info.codecType = kVideoCodecH264;
1464
1465 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001466 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001467 encoded_image.qp_ = kQpIdx0;
1468 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001469 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001470 encoded_image.qp_ = kQpIdx1;
1471 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001472 }
1473 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001474 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1475 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1476 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1477 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001478}
1479
asapersson4ee70462016-10-31 04:05:12 -07001480TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001481 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1482 // Configure one stream.
1483 VideoEncoderConfig config;
1484 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1485 VideoStream stream1;
1486 stream1.width = kWidth;
1487 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001488 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001489
1490 const int64_t kMaxEncodedFrameWindowMs = 800;
1491 const int kFps = 20;
1492 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1493 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1494 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1495
1496 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001497 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001498 encoded_image._encodedWidth = kWidth;
1499 encoded_image._encodedHeight = kHeight;
1500 for (int i = 0; i < kMinSamples; ++i) {
1501 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001502 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1503 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001504 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001505 }
asapersson4ee70462016-10-31 04:05:12 -07001506
1507 // Histograms are updated when the statistics_proxy_ is deleted.
1508 statistics_proxy_.reset();
1509 EXPECT_EQ(0, metrics::NumSamples(
1510 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1511 EXPECT_EQ(0, metrics::NumSamples(
1512 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1513}
1514
1515TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001516 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1517 // Configure two streams.
1518 VideoEncoderConfig config;
1519 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1520 VideoStream stream1;
1521 stream1.width = kWidth / 2;
1522 stream1.height = kHeight / 2;
1523 VideoStream stream2;
1524 stream2.width = kWidth;
1525 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001526 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001527
1528 const int64_t kMaxEncodedFrameWindowMs = 800;
1529 const int kFps = 20;
1530 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1531 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1532 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1533
1534 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001535 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001536 for (int i = 0; i < kMinSamples; ++i) {
1537 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001538 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1539 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001540 encoded_image._encodedWidth = kWidth;
1541 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001542 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001543 encoded_image._encodedWidth = kWidth / 2;
1544 encoded_image._encodedHeight = kHeight / 2;
1545 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1546 }
asapersson4ee70462016-10-31 04:05:12 -07001547
1548 // Histograms are updated when the statistics_proxy_ is deleted.
1549 statistics_proxy_.reset();
1550 EXPECT_EQ(1, metrics::NumSamples(
1551 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1552 EXPECT_EQ(1, metrics::NumEvents(
1553 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1554 // No resolution disabled.
1555 EXPECT_EQ(0, metrics::NumSamples(
1556 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1557}
1558
1559TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001560 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1561 // Configure two streams.
1562 VideoEncoderConfig config;
1563 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1564 VideoStream stream1;
1565 stream1.width = kWidth / 2;
1566 stream1.height = kHeight / 2;
1567 VideoStream stream2;
1568 stream2.width = kWidth;
1569 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001570 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001571
1572 const int64_t kMaxEncodedFrameWindowMs = 800;
1573 const int kFps = 20;
1574 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1575 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1576 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1577
1578 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001579 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001580 encoded_image._encodedWidth = kWidth / 2;
1581 encoded_image._encodedHeight = kHeight / 2;
1582 for (int i = 0; i < kMinSamples; ++i) {
1583 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001584 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1585 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001586 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001587 }
asapersson4ee70462016-10-31 04:05:12 -07001588
1589 // Histograms are updated when the statistics_proxy_ is deleted.
1590 statistics_proxy_.reset();
1591 EXPECT_EQ(1, metrics::NumSamples(
1592 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1593 EXPECT_EQ(1, metrics::NumEvents(
1594 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001595 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001596 EXPECT_EQ(1, metrics::NumSamples(
1597 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001598 EXPECT_EQ(1, metrics::NumEvents(
1599 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001600}
1601
1602TEST_F(SendStatisticsProxyTest,
1603 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001604 SendStatisticsProxy::AdaptationSteps cpu_counts;
1605 SendStatisticsProxy::AdaptationSteps quality_counts;
1606 quality_counts.num_resolution_reductions = absl::nullopt;
1607 statistics_proxy_->OnAdaptationChanged(
1608 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1609 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001610 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001611 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001612 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001613 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001614
1615 // Histograms are updated when the statistics_proxy_ is deleted.
1616 statistics_proxy_.reset();
1617 EXPECT_EQ(
1618 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1619 EXPECT_EQ(0, metrics::NumSamples(
1620 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1621}
1622
1623TEST_F(SendStatisticsProxyTest,
1624 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001625 SendStatisticsProxy::AdaptationSteps cpu_counts;
1626 SendStatisticsProxy::AdaptationSteps quality_counts;
1627 quality_counts.num_resolution_reductions = 0;
1628 statistics_proxy_->OnAdaptationChanged(
1629 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1630 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001631 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001632 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001633 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001634 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001635
1636 // Histograms are updated when the statistics_proxy_ is deleted.
1637 statistics_proxy_.reset();
1638 EXPECT_EQ(
1639 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1640 EXPECT_EQ(1, metrics::NumEvents(
1641 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1642 // No resolution downscale.
1643 EXPECT_EQ(0, metrics::NumSamples(
1644 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1645}
1646
1647TEST_F(SendStatisticsProxyTest,
1648 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1649 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001650 SendStatisticsProxy::AdaptationSteps cpu_counts;
1651 SendStatisticsProxy::AdaptationSteps quality_counts;
1652 quality_counts.num_resolution_reductions = kDownscales;
1653 statistics_proxy_->OnAdaptationChanged(
1654 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1655 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001656 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001657 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001658 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001659 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001660 // Histograms are updated when the statistics_proxy_ is deleted.
1661 statistics_proxy_.reset();
1662 EXPECT_EQ(
1663 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1664 EXPECT_EQ(1, metrics::NumEvents(
1665 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1666 // Resolution downscales.
1667 EXPECT_EQ(1, metrics::NumSamples(
1668 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1669 EXPECT_EQ(
1670 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1671 kDownscales));
1672}
1673
1674TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1675 // Initially false.
1676 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001677
Åsa Perssonaa329e72017-12-15 15:54:44 +01001678 // Configure two streams.
1679 VideoEncoderConfig config;
1680 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1681 VideoStream stream1;
1682 stream1.width = kWidth / 2;
1683 stream1.height = kHeight / 2;
1684 VideoStream stream2;
1685 stream2.width = kWidth;
1686 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001687 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001688
1689 const int64_t kMaxEncodedFrameWindowMs = 800;
1690 const int kFps = 20;
1691 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1692 kFps * kMaxEncodedFrameWindowMs / 1000;
1693
1694 // One stream encoded.
1695 EncodedImage encoded_image;
1696 encoded_image._encodedWidth = kWidth / 2;
1697 encoded_image._encodedHeight = kHeight / 2;
1698 for (int i = 0; i < kMinSamples; ++i) {
1699 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001700 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1701 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001702 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1703 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1704 }
1705
1706 // First frame removed from EncodedFrameMap, stats updated.
1707 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001708 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08001709 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1710 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1711
Åsa Perssonaa329e72017-12-15 15:54:44 +01001712 // Two streams encoded.
1713 for (int i = 0; i < kMinSamples; ++i) {
1714 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001715 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1716 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001717 encoded_image._encodedWidth = kWidth;
1718 encoded_image._encodedHeight = kHeight;
1719 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1720 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1721 encoded_image._encodedWidth = kWidth / 2;
1722 encoded_image._encodedHeight = kHeight / 2;
1723 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1724 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1725 }
1726
1727 // First frame with two streams removed, expect no resolution limit.
1728 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001729 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1730 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001731 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1732 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001733
1734 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02001735 SendStatisticsProxy::AdaptationSteps cpu_counts;
1736 SendStatisticsProxy::AdaptationSteps quality_counts;
1737 quality_counts.num_resolution_reductions = 1;
1738 statistics_proxy_->OnAdaptationChanged(
1739 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1740 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001741 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1742 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1743}
1744
asapersson66d4b372016-12-19 06:50:53 -08001745TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1746 // Initially zero.
1747 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1748
1749 const int kBitrate = 100000;
1750 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1751 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1752
1753 statistics_proxy_->OnSetEncoderTargetRate(0);
1754 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1755}
1756
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001757TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001758 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07001759 std::max(*absl::c_max_element(config_.rtp.ssrcs),
1760 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001761 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001762 // From RtcpStatisticsCallback.
1763 RtcpStatistics rtcp_stats;
1764 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001765 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001766
1767 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001768 uint32_t total = 0;
1769 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001770 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001771 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001772
1773 // From FrameCountObserver.
1774 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001775 FrameCounts frame_counts;
1776 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001777 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001778
1779 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1780 EXPECT_TRUE(stats.substreams.empty());
1781}
1782
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001783TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1784 static const int kEncodedWidth = 123;
1785 static const int kEncodedHeight = 81;
1786 EncodedImage encoded_image;
1787 encoded_image._encodedWidth = kEncodedWidth;
1788 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001789 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001790
kjellander02b3d272016-04-20 05:05:54 -07001791 CodecSpecificInfo codec_info;
1792 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001793
kjellander02b3d272016-04-20 05:05:54 -07001794 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001795 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001796 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001797
1798 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001799 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1800 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1801 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1802 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001803
1804 // Forward almost to timeout, this should not have removed stats.
1805 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1806 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001807 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1808 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001809
1810 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1811 // resolution still times out (no global timeout for all stats).
1812 RtcpStatistics rtcp_statistics;
1813 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1814 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1815
1816 // Report stats for second SSRC to make sure it's not outdated along with the
1817 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001818 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001819
1820 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1821 // reported, but substream 1 should.
1822 fake_clock_.AdvanceTimeMilliseconds(1);
1823 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001824 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1825 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1826 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1827 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001828}
1829
Peter Boström20f3f942015-05-15 11:33:39 +02001830TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1831 static const int kEncodedWidth = 123;
1832 static const int kEncodedHeight = 81;
1833 EncodedImage encoded_image;
1834 encoded_image._encodedWidth = kEncodedWidth;
1835 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001836 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02001837
kjellander02b3d272016-04-20 05:05:54 -07001838 CodecSpecificInfo codec_info;
1839 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02001840
kjellander02b3d272016-04-20 05:05:54 -07001841 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001842 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001843 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001844
1845 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1846 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1847 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1848 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1849 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1850 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1851}
1852
1853TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001854 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001855 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1856 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1857 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1858
1859 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1860
1861 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001862 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001863 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001864 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001865 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1866 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1867 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1868}
1869
sprang07fb9be2016-02-24 07:55:00 -08001870TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1871 RtcpPacketTypeCounterObserver* proxy =
1872 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1873 RtcpPacketTypeCounter counters;
1874 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1875 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1876 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1877
1878 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1879
1880 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1881 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1882 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1883 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1884 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1885
1886 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1887 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1888
1889 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001890 VideoEncoderConfig config;
1891 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001892 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001893
asapersson01d70a32016-05-20 06:29:46 -07001894 EXPECT_EQ(1,
1895 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1896 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1897 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1898 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001899 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1900
1901 const int kRate = 60 * 2; // Packets per minute with two streams.
1902
asapersson01d70a32016-05-20 06:29:46 -07001903 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1904 1 * kRate));
1905 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1906 2 * kRate));
1907 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1908 3 * kRate));
1909 EXPECT_EQ(
1910 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1911 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001912
1913 // New start time but same counter values.
1914 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1915 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1916
1917 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1918
1919 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1920 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1921 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1922 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1923 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1924
1925 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1926 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1927
1928 SetUp(); // Reset stats proxy also causes histograms to be reported.
1929
asapersson01d70a32016-05-20 06:29:46 -07001930 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001931 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001932 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001933 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001934 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001935 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1936 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001937 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001938 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1939
asapersson01d70a32016-05-20 06:29:46 -07001940 EXPECT_EQ(1, metrics::NumEvents(
1941 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1942 1 * kRate));
1943 EXPECT_EQ(1, metrics::NumEvents(
1944 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1945 2 * kRate));
1946 EXPECT_EQ(1, metrics::NumEvents(
1947 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1948 3 * kRate));
1949 EXPECT_EQ(1,
1950 metrics::NumEvents(
1951 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1952 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001953}
1954
asaperssona6a699a2016-11-25 03:52:46 -08001955TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1956 statistics_proxy_.reset(
1957 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1958 VideoEncoderConfig::ContentType::kRealtimeVideo));
1959
1960 StreamDataCountersCallback* proxy =
1961 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1962 StreamDataCounters counters;
1963 proxy->DataCountersUpdated(counters, kFirstSsrc);
1964 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1965
1966 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1967 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1968}
1969
1970TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1971 statistics_proxy_.reset(
1972 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1973 VideoEncoderConfig::ContentType::kRealtimeVideo));
1974
1975 StreamDataCountersCallback* proxy =
1976 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001977 StreamDataCounters counters;
1978 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001979
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 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2000 }
asaperssona6a699a2016-11-25 03:52:46 -08002001
asaperssona6a699a2016-11-25 03:52:46 -08002002 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002003 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002004 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002005 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2006 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2007 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2008 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2009 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002010 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002011 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2012 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002013 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002014 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2015 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2016 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2017 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2018 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08002019 EXPECT_EQ(1,
2020 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08002021 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002022 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002023}
2024
Erik Språng22c2b482016-03-01 09:40:42 +01002025TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2026 StreamDataCountersCallback* proxy =
2027 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2028 StreamDataCounters counters;
2029 StreamDataCounters rtx_counters;
2030 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002031
asapersson93e1e232017-02-06 05:18:35 -08002032 const int kMinRequiredPeriodSamples = 8;
2033 const int kPeriodIntervalMs = 2000;
2034 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2035 counters.transmitted.packets += 20;
2036 counters.transmitted.header_bytes += 500;
2037 counters.transmitted.padding_bytes += 1000;
2038 counters.transmitted.payload_bytes += 2000;
2039 counters.retransmitted.packets += 2;
2040 counters.retransmitted.header_bytes += 25;
2041 counters.retransmitted.padding_bytes += 100;
2042 counters.retransmitted.payload_bytes += 250;
2043 counters.fec = counters.retransmitted;
2044 rtx_counters.transmitted = counters.transmitted;
2045 // Advance one interval and update counters.
2046 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2047 proxy->DataCountersUpdated(counters, kFirstSsrc);
2048 proxy->DataCountersUpdated(counters, kSecondSsrc);
2049 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2050 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2051 }
Erik Språng22c2b482016-03-01 09:40:42 +01002052
2053 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002054 VideoEncoderConfig config;
2055 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002056 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002057
asapersson93e1e232017-02-06 05:18:35 -08002058 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002059 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002060 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2061 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2062 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2063 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2064 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002065 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002066 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.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("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002069 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2070 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2071 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2072 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2073 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002074 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002075 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002076 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002077 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002078
asapersson93e1e232017-02-06 05:18:35 -08002079 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002080 // Double counter values, this should result in the same counts as before but
2081 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002082 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2083 counters.transmitted.packets += 20;
2084 counters.transmitted.header_bytes += 500;
2085 counters.transmitted.padding_bytes += 1000;
2086 counters.transmitted.payload_bytes += 2000;
2087 counters.retransmitted.packets += 2;
2088 counters.retransmitted.header_bytes += 25;
2089 counters.retransmitted.padding_bytes += 100;
2090 counters.retransmitted.payload_bytes += 250;
2091 counters.fec = counters.retransmitted;
2092 rtx_counters.transmitted = counters.transmitted;
2093 // Advance one interval and update counters.
2094 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2095 proxy->DataCountersUpdated(counters, kFirstSsrc);
2096 proxy->DataCountersUpdated(counters, kSecondSsrc);
2097 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2098 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2099 }
Erik Språng22c2b482016-03-01 09:40:42 +01002100
asapersson93e1e232017-02-06 05:18:35 -08002101 // Reset stats proxy also causes histograms to be reported.
2102 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002103
asapersson93e1e232017-02-06 05:18:35 -08002104 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002105 EXPECT_EQ(1,
2106 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002107 EXPECT_EQ(
2108 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2109 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2110 EXPECT_EQ(
2111 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2112 EXPECT_EQ(1, metrics::NumEvents(
2113 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2114 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002115 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002116 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002117 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002118 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2119 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002120 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002121 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002122 EXPECT_EQ(1, metrics::NumEvents(
2123 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2124 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2125 EXPECT_EQ(
2126 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2127 EXPECT_EQ(1, metrics::NumEvents(
2128 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2129 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002130 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002131 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002132 EXPECT_EQ(1,
2133 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002134 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2135}
Erik Språng22c2b482016-03-01 09:40:42 +01002136
asapersson93e1e232017-02-06 05:18:35 -08002137TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2138 StreamDataCountersCallback* proxy =
2139 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2140 StreamDataCounters counters;
2141 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002142
asapersson93e1e232017-02-06 05:18:35 -08002143 const int kMinRequiredPeriodSamples = 8;
2144 const int kPeriodIntervalMs = 2000;
2145 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2146 counters.transmitted.packets += 20;
2147 counters.transmitted.header_bytes += 500;
2148 counters.transmitted.payload_bytes += 2000;
2149 counters.fec = counters.retransmitted;
2150 // Advance one interval and update counters.
2151 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2152 proxy->DataCountersUpdated(counters, kFirstSsrc);
2153 }
2154
2155 // RTX enabled. No data sent over RTX.
2156 statistics_proxy_.reset();
2157 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2158 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2159}
2160
2161TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2162 VideoSendStream::Config config(nullptr);
2163 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2164 statistics_proxy_.reset(new SendStatisticsProxy(
2165 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2166
2167 StreamDataCountersCallback* proxy =
2168 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2169 StreamDataCounters counters;
2170
2171 const int kMinRequiredPeriodSamples = 8;
2172 const int kPeriodIntervalMs = 2000;
2173 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2174 counters.transmitted.packets += 20;
2175 counters.transmitted.header_bytes += 500;
2176 counters.transmitted.payload_bytes += 2000;
2177 counters.fec = counters.retransmitted;
2178 // Advance one interval and update counters.
2179 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2180 proxy->DataCountersUpdated(counters, kFirstSsrc);
2181 }
2182
2183 // RTX not enabled.
2184 statistics_proxy_.reset();
2185 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2186}
2187
2188TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2189 StreamDataCountersCallback* proxy =
2190 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2191 StreamDataCounters counters;
2192 StreamDataCounters rtx_counters;
2193
2194 const int kMinRequiredPeriodSamples = 8;
2195 const int kPeriodIntervalMs = 2000;
2196 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2197 counters.transmitted.packets += 20;
2198 counters.transmitted.header_bytes += 500;
2199 counters.transmitted.payload_bytes += 2000;
2200 // Advance one interval and update counters.
2201 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2202 proxy->DataCountersUpdated(counters, kFirstSsrc);
2203 }
2204
2205 // FEC enabled. No FEC data sent.
2206 statistics_proxy_.reset();
2207 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2208 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2209}
2210
2211TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2212 VideoSendStream::Config config(nullptr);
2213 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2214 statistics_proxy_.reset(new SendStatisticsProxy(
2215 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2216
2217 StreamDataCountersCallback* proxy =
2218 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2219 StreamDataCounters counters;
2220
2221 const int kMinRequiredPeriodSamples = 8;
2222 const int kPeriodIntervalMs = 2000;
2223 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2224 counters.transmitted.packets += 20;
2225 counters.transmitted.header_bytes += 500;
2226 counters.transmitted.payload_bytes += 2000;
2227 counters.fec = counters.retransmitted;
2228 // Advance one interval and update counters.
2229 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2230 proxy->DataCountersUpdated(counters, kFirstSsrc);
2231 }
2232
2233 // FEC not enabled.
2234 statistics_proxy_.reset();
2235 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002236}
2237
asapersson8d75ac72017-09-15 06:41:15 -07002238TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002239 const std::string kName = "encoderName";
2240 statistics_proxy_->OnEncoderImplementationChanged(kName);
2241 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002242}
2243
Sergey Silkinbb081a62018-09-04 18:34:22 +02002244TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2245 static const int kEncodedWidth = 123;
2246 static const int kEncodedHeight = 81;
2247 EncodedImage encoded_image;
2248 encoded_image._encodedWidth = kEncodedWidth;
2249 encoded_image._encodedHeight = kEncodedHeight;
2250 encoded_image.SetSpatialIndex(0);
2251
2252 CodecSpecificInfo codec_info;
2253 codec_info.codecType = kVideoCodecVP9;
2254
2255 // For first picture, it is expected that low layer updates resolution.
2256 codec_info.codecSpecific.VP9.end_of_picture = false;
2257 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2258 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2259 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2260 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2261
2262 // Top layer updates resolution.
2263 encoded_image._encodedWidth = kEncodedWidth * 2;
2264 encoded_image._encodedHeight = kEncodedHeight * 2;
2265 codec_info.codecSpecific.VP9.end_of_picture = true;
2266 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2267 stats = statistics_proxy_->GetStats();
2268 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2269 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2270
2271 // Low layer of next frame doesn't update resolution.
2272 encoded_image._encodedWidth = kEncodedWidth;
2273 encoded_image._encodedHeight = kEncodedHeight;
2274 codec_info.codecSpecific.VP9.end_of_picture = false;
2275 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2276 stats = statistics_proxy_->GetStats();
2277 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2278 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2279}
2280
asapersson8d75ac72017-09-15 06:41:15 -07002281class ForcedFallbackTest : public SendStatisticsProxyTest {
2282 public:
2283 explicit ForcedFallbackTest(const std::string& field_trials)
2284 : SendStatisticsProxyTest(field_trials) {
2285 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002286 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002287 encoded_image_._encodedWidth = kWidth;
2288 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002289 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002290 }
2291
2292 ~ForcedFallbackTest() override {}
2293
2294 protected:
2295 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002296 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2297
asapersson8d75ac72017-09-15 06:41:15 -07002298 // First frame is not updating stats, insert initial frame.
2299 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2300 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2301 }
2302 for (int i = 0; i < num_frames; ++i) {
2303 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2304 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2305 }
2306 // Add frame to include last time interval.
2307 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2308 }
2309
2310 EncodedImage encoded_image_;
2311 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002312 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002313 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2314 const int kFrameIntervalMs = 1000;
2315 const int kMinFrames = 20; // Min run time 20 sec.
2316};
2317
2318class ForcedFallbackDisabled : public ForcedFallbackTest {
2319 public:
2320 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002321 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2322 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002323};
2324
2325class ForcedFallbackEnabled : public ForcedFallbackTest {
2326 public:
2327 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002328 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2329 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002330};
2331
2332TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2333 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2334 statistics_proxy_.reset();
2335 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2336 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2337}
2338
2339TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2340 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002341 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002342 statistics_proxy_.reset();
2343 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2344 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2345 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2346 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2347}
2348
2349TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2350 codec_info_.codecType = kVideoCodecVP9;
2351 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2352 statistics_proxy_.reset();
2353 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2354 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2355}
2356
2357TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2358 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2359 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2360 statistics_proxy_.reset();
2361 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2362 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2363}
2364
2365TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002366 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002367 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2368 statistics_proxy_.reset();
2369 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2370 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2371}
2372
2373TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2374 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2375 statistics_proxy_.reset();
2376 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2377 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2378}
2379
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002380TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2381 InsertEncodedFrames(1, kFrameIntervalMs);
2382 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2383}
2384
2385TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2386 InsertEncodedFrames(1, kFrameIntervalMs);
2387 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2388}
2389
2390TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002391 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002392 InsertEncodedFrames(1, kFrameIntervalMs);
2393 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2394}
2395
2396TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2397 encoded_image_._encodedWidth = kWidth + 1;
2398 InsertEncodedFrames(1, kFrameIntervalMs);
2399 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2400}
2401
2402TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002403 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002404 InsertEncodedFrames(1, kFrameIntervalMs);
2405 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2406}
2407
2408TEST_F(ForcedFallbackDisabled,
2409 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2410 encoded_image_._encodedWidth = kWidth + 1;
2411 statistics_proxy_->OnMinPixelLimitReached();
2412 InsertEncodedFrames(1, kFrameIntervalMs);
2413 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2414}
2415
asapersson8d75ac72017-09-15 06:41:15 -07002416TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2417 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002418 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002419 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002420 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002421 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002422 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002423 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002424
2425 statistics_proxy_.reset();
2426 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2427 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2428 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2429 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2430}
2431
2432TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2433 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2434 const int kMaxFrameDiffMs = 2000;
2435
2436 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2437 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002438 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002439 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002440 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002441 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002442 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002443 InsertEncodedFrames(20, 1000);
2444 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2445 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002446 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002447 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002448 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002449 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002450 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002451 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002452 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002453
2454 statistics_proxy_.reset();
2455 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2456 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2457 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2458 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2459}
2460
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002461TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2462 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002463 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002464 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2465
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002466 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002467 statistics_proxy_.reset();
2468 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2469 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2470}
2471
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002472TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2473 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002474 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002475 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2476
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002477 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002478 statistics_proxy_.reset();
2479 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2480 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2481}
2482
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002483} // namespace webrtc