blob: 586d57fb284880fff1733ec9e7c82055b48f339b [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
13#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080014#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000015#include <string>
16#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070019#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000021
22namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070023namespace {
24const uint32_t kFirstSsrc = 17;
25const uint32_t kSecondSsrc = 42;
26const uint32_t kFirstRtxSsrc = 18;
27const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080028const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080029const int kFpsPeriodicIntervalMs = 2000;
30const int kWidth = 640;
31const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070032const int kQpIdx0 = 21;
33const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010034const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080035const CodecSpecificInfo kDefaultCodecInfo = []() {
36 CodecSpecificInfo codec_info;
37 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080038 return codec_info;
39}();
asapersson5265fed2016-04-18 02:58:47 -070040} // namespace
sprang07fb9be2016-02-24 07:55:00 -080041
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000042class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000043 public:
asapersson8d75ac72017-09-15 06:41:15 -070044 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
45 explicit SendStatisticsProxyTest(const std::string& field_trials)
46 : override_field_trials_(field_trials),
47 fake_clock_(1234),
48 config_(GetTestConfig()),
49 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070050 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000051 virtual ~SendStatisticsProxyTest() {}
52
53 protected:
54 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070055 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080056 statistics_proxy_.reset(new SendStatisticsProxy(
57 &fake_clock_, GetTestConfig(),
58 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000059 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070060 for (const auto& ssrc : config_.rtp.ssrcs)
61 expected_.substreams[ssrc].is_rtx = false;
62 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
63 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000064 }
65
66 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070067 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080068 config.rtp.ssrcs.push_back(kFirstSsrc);
69 config.rtp.ssrcs.push_back(kSecondSsrc);
70 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
71 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070072 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000073 return config;
74 }
75
asaperssona6a699a2016-11-25 03:52:46 -080076 VideoSendStream::Config GetTestConfigWithFlexFec() {
77 VideoSendStream::Config config(nullptr);
78 config.rtp.ssrcs.push_back(kFirstSsrc);
79 config.rtp.ssrcs.push_back(kSecondSsrc);
80 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
81 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080082 config.rtp.flexfec.payload_type = 50;
83 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080084 return config;
85 }
86
87 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
88 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
89 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
90 stats.substreams.find(ssrc);
91 EXPECT_NE(it, stats.substreams.end());
92 return it->second;
93 }
94
asapersson66d4b372016-12-19 06:50:53 -080095 void UpdateDataCounters(uint32_t ssrc) {
96 StreamDataCountersCallback* proxy =
97 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
98 StreamDataCounters counters;
99 proxy->DataCountersUpdated(counters, ssrc);
100 }
101
sprang@webrtc.org09315702014-02-07 12:06:29 +0000102 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000103 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
104 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000105 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000106 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000107
108 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000109 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000110 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000111 it != one.substreams.end(); ++it) {
112 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
113 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000114 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000115 const VideoSendStream::StreamStats& a = it->second;
116 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000117
asapersson2e5cfcd2016-08-11 08:41:18 -0700118 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000119 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
120 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000121 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000122 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
123 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000124
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000125 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
126 b.rtp_stats.transmitted.payload_bytes);
127 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
128 b.rtp_stats.transmitted.header_bytes);
129 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
130 b.rtp_stats.transmitted.padding_bytes);
131 EXPECT_EQ(a.rtp_stats.transmitted.packets,
132 b.rtp_stats.transmitted.packets);
133 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
134 b.rtp_stats.retransmitted.packets);
135 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000136
137 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700138 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
139 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
140 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000141 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
142 }
143 }
144
asapersson8d75ac72017-09-15 06:41:15 -0700145 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000146 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800147 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000148 VideoSendStream::Config config_;
149 int avg_delay_ms_;
150 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000151 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000152 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
153 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000154};
155
156TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
157 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700158 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000159 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000160
161 // Add statistics with some arbitrary, but unique, numbers.
162 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700163 ssrc_stats.rtcp_stats.packets_lost = offset;
164 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000165 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
166 ssrc_stats.rtcp_stats.jitter = offset + 3;
167 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
168 }
asapersson35151f32016-05-02 23:44:01 -0700169 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000170 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000171
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000172 // Add statistics with some arbitrary, but unique, numbers.
173 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700174 ssrc_stats.rtcp_stats.packets_lost = offset;
175 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000176 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
177 ssrc_stats.rtcp_stats.jitter = offset + 3;
178 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
179 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000180 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000181 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182}
183
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000184TEST_F(SendStatisticsProxyTest, Suspended) {
185 // Verify that the value is false by default.
186 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
187
188 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200189 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000190 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
191
192 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200193 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000194 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
195}
196
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000197TEST_F(SendStatisticsProxyTest, FrameCounts) {
198 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700199 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000200 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000201 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
202 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000203 FrameCounts frame_counts;
204 frame_counts.key_frames = offset;
205 frame_counts.delta_frames = offset + 1;
206 stats.frame_counts = frame_counts;
207 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000208 }
asapersson35151f32016-05-02 23:44:01 -0700209 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000210 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000211 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
212 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000213 FrameCounts frame_counts;
214 frame_counts.key_frames = offset;
215 frame_counts.delta_frames = offset + 1;
216 stats.frame_counts = frame_counts;
217 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000218 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000219
220 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000221 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000222}
223
224TEST_F(SendStatisticsProxyTest, DataCounters) {
225 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700226 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000227 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
228 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000229 size_t offset = ssrc * sizeof(StreamDataCounters);
230 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000231 counters.transmitted.payload_bytes = offset;
232 counters.transmitted.header_bytes = offset + 1;
233 counters.fec.packets = offset_uint32 + 2;
234 counters.transmitted.padding_bytes = offset + 3;
235 counters.retransmitted.packets = offset_uint32 + 4;
236 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000237 callback->DataCountersUpdated(counters, ssrc);
238 }
asapersson35151f32016-05-02 23:44:01 -0700239 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000240 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
241 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000242 size_t offset = ssrc * sizeof(StreamDataCounters);
243 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000244 counters.transmitted.payload_bytes = offset;
245 counters.transmitted.header_bytes = offset + 1;
246 counters.fec.packets = offset_uint32 + 2;
247 counters.transmitted.padding_bytes = offset + 3;
248 counters.retransmitted.packets = offset_uint32 + 4;
249 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000250 callback->DataCountersUpdated(counters, ssrc);
251 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000252
253 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000254 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000255}
256
257TEST_F(SendStatisticsProxyTest, Bitrate) {
258 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700259 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700260 uint32_t total;
261 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000262 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700263 total = ssrc;
264 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000265 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700266 expected_.substreams[ssrc].total_bitrate_bps = total;
267 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000268 }
asapersson35151f32016-05-02 23:44:01 -0700269 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700270 uint32_t total;
271 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000272 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700273 total = ssrc;
274 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000275 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700276 expected_.substreams[ssrc].total_bitrate_bps = total;
277 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000278 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000279
280 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000281 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000282}
283
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000284TEST_F(SendStatisticsProxyTest, SendSideDelay) {
285 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700286 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000287 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
288 // stream.
289 int avg_delay_ms = ssrc;
290 int max_delay_ms = ssrc + 1;
291 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
292 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
293 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
294 }
asapersson35151f32016-05-02 23:44:01 -0700295 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000296 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
297 // stream.
298 int avg_delay_ms = ssrc;
299 int max_delay_ms = ssrc + 1;
300 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
301 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
302 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
303 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000304 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000305 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000306}
307
Peter Boströme4499152016-02-05 11:13:28 +0100308TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800309 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200310 int encode_usage_percent = 80;
311 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
312 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800313
314 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
315 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200316 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800317}
318
sakal43536c32016-10-24 01:46:43 -0700319TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
320 EncodedImage encoded_image;
321 CodecSpecificInfo codec_info;
322 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
323 for (uint32_t i = 1; i <= 3; ++i) {
324 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
325 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
326 }
327}
328
sakal87da4042016-10-31 06:53:47 -0700329TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
330 EncodedImage encoded_image;
331 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200332 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700333 encoded_image.qp_ = 3;
334 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100335 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700336 encoded_image.qp_ = 127;
337 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100338 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700339}
340
341TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
342 EncodedImage encoded_image;
343 CodecSpecificInfo codec_info;
344 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200345 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700346 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200347 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700348}
349
asapersson09f05612017-05-15 23:40:18 -0700350TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200351 SendStatisticsProxy::AdaptationSteps cpu_counts;
352 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700353 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700354 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200355 cpu_counts.num_framerate_reductions = 1;
356 cpu_counts.num_resolution_reductions = 0;
357 statistics_proxy_->OnAdaptationChanged(
358 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
359 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700360 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700361 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200362 cpu_counts.num_framerate_reductions = 0;
363 cpu_counts.num_resolution_reductions = 1;
364 statistics_proxy_->OnAdaptationChanged(
365 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
366 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700367 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700368 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200369 cpu_counts.num_framerate_reductions = 1;
370 cpu_counts.num_resolution_reductions = absl::nullopt;
371 statistics_proxy_->OnAdaptationChanged(
372 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
373 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700374 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700375 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200376 cpu_counts.num_framerate_reductions = absl::nullopt;
377 cpu_counts.num_resolution_reductions = absl::nullopt;
378 statistics_proxy_->OnAdaptationChanged(
379 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
380 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700381 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
382 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
383}
384
385TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200386 SendStatisticsProxy::AdaptationSteps cpu_counts;
387 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700388 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
389 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200390 quality_counts.num_framerate_reductions = 1;
391 quality_counts.num_resolution_reductions = 0;
392 statistics_proxy_->OnAdaptationChanged(
393 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
394 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700395 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
396 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200397 quality_counts.num_framerate_reductions = 0;
398 quality_counts.num_resolution_reductions = 1;
399 statistics_proxy_->OnAdaptationChanged(
400 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
401 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700402 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
403 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200404 quality_counts.num_framerate_reductions = 1;
405 quality_counts.num_resolution_reductions = absl::nullopt;
406 statistics_proxy_->OnAdaptationChanged(
407 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
408 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700409 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
410 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200411 quality_counts.num_framerate_reductions = absl::nullopt;
412 quality_counts.num_resolution_reductions = absl::nullopt;
413 statistics_proxy_->OnAdaptationChanged(
414 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
415 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700416 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
417 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
418}
419
420TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200421 SendStatisticsProxy::AdaptationSteps cpu_counts;
422 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700423 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
424
Niels Möller213618e2018-07-24 09:29:58 +0200425 cpu_counts.num_resolution_reductions = 1;
426 statistics_proxy_->OnAdaptationChanged(
427 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
428 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700429 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700430 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
431 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
432
Niels Möller213618e2018-07-24 09:29:58 +0200433 cpu_counts.num_resolution_reductions = 2;
434 statistics_proxy_->OnAdaptationChanged(
435 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
436 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700437 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
438 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700439 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700440 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700441}
442
asapersson09f05612017-05-15 23:40:18 -0700443TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200444 SendStatisticsProxy::AdaptationSteps cpu_counts;
445 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700446 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
447
Niels Möller213618e2018-07-24 09:29:58 +0200448 quality_counts.num_framerate_reductions = 1;
449 statistics_proxy_->OnAdaptationChanged(
450 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
451 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700452 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
453 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700454 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
455
Niels Möller213618e2018-07-24 09:29:58 +0200456 quality_counts.num_framerate_reductions = 0;
457 statistics_proxy_->OnAdaptationChanged(
458 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
459 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700460 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700461 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700462 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
463 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700464}
465
asapersson09f05612017-05-15 23:40:18 -0700466TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700467 // First RTP packet sent.
468 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700469 // Min runtime has passed.
470 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
471 statistics_proxy_.reset();
472 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
473 EXPECT_EQ(0,
474 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
475}
476
477TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700478 // First RTP packet sent.
479 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700480 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200481 SendStatisticsProxy::AdaptationSteps cpu_counts;
482 SendStatisticsProxy::AdaptationSteps quality_counts;
483 statistics_proxy_->OnAdaptationChanged(
484 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
485 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700486 // Min runtime has not passed.
487 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
488 statistics_proxy_.reset();
489 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
490 EXPECT_EQ(0,
491 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
492}
493
asapersson09f05612017-05-15 23:40:18 -0700494TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700495 // First RTP packet sent.
496 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700497 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200498 SendStatisticsProxy::AdaptationSteps cpu_counts;
499 SendStatisticsProxy::AdaptationSteps quality_counts;
500 statistics_proxy_->OnAdaptationChanged(
501 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
502 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700503 // Min runtime has passed.
504 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
505 statistics_proxy_.reset();
506 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
507 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700508 EXPECT_EQ(1,
509 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
510 EXPECT_EQ(
511 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
512}
513
514TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700515 // First RTP packet sent.
516 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700517 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200518 SendStatisticsProxy::AdaptationSteps cpu_counts;
519 SendStatisticsProxy::AdaptationSteps quality_counts;
520 statistics_proxy_->OnAdaptationChanged(
521 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
522 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700523 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200524 statistics_proxy_->OnAdaptationChanged(
525 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
526 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700527 fake_clock_.AdvanceTimeMilliseconds(10000);
528 statistics_proxy_.reset();
529 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
530 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
531}
532
Åsa Persson875841d2018-01-08 08:49:53 +0100533TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
534 // First RTP packet sent.
535 UpdateDataCounters(kFirstSsrc);
536 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200537 SendStatisticsProxy::AdaptationSteps cpu_counts;
538 SendStatisticsProxy::AdaptationSteps quality_counts;
539 statistics_proxy_->OnAdaptationChanged(
540 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
541 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100542 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200543 statistics_proxy_->OnAdaptationChanged(
544 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
545 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100546 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
547 fake_clock_.AdvanceTimeMilliseconds(10000);
548 statistics_proxy_.reset();
549 EXPECT_EQ(1,
550 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
551 EXPECT_EQ(
552 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
553}
554
555TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
556 // First RTP packet sent.
557 UpdateDataCounters(kFirstSsrc);
558 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200559 SendStatisticsProxy::AdaptationSteps cpu_counts;
560 SendStatisticsProxy::AdaptationSteps quality_counts;
561 statistics_proxy_->OnAdaptationChanged(
562 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
563 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100564 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200565 quality_counts.num_resolution_reductions = 1;
566 statistics_proxy_->OnAdaptationChanged(
567 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
568 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100569 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200570 quality_counts.num_resolution_reductions = 2;
571 statistics_proxy_->OnAdaptationChanged(
572 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
573 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100574 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200575 quality_counts.num_resolution_reductions = 3;
576 statistics_proxy_->OnAdaptationChanged(
577 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
578 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100579 fake_clock_.AdvanceTimeMilliseconds(10000);
580 statistics_proxy_.reset();
581 EXPECT_EQ(1,
582 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
583 EXPECT_EQ(
584 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
585}
586
587TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
588 // First RTP packet sent.
589 UpdateDataCounters(kFirstSsrc);
590 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200591 SendStatisticsProxy::AdaptationSteps cpu_counts;
592 SendStatisticsProxy::AdaptationSteps quality_counts;
593 statistics_proxy_->OnAdaptationChanged(
594 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
595 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100596 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200597 statistics_proxy_->OnAdaptationChanged(
598 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
599 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100600 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
601 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
602 fake_clock_.AdvanceTimeMilliseconds(10000);
603 statistics_proxy_.reset();
604 EXPECT_EQ(1,
605 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
606 EXPECT_EQ(
607 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
608}
609
610TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
611 // First RTP packet sent.
612 UpdateDataCounters(kFirstSsrc);
613 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200614 SendStatisticsProxy::AdaptationSteps cpu_counts;
615 SendStatisticsProxy::AdaptationSteps quality_counts;
616 statistics_proxy_->OnAdaptationChanged(
617 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
618 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100619 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200620 quality_counts.num_resolution_reductions = 1;
621 statistics_proxy_->OnAdaptationChanged(
622 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
623 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100624 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200625 quality_counts.num_resolution_reductions = 2;
626 statistics_proxy_->OnAdaptationChanged(
627 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
628 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100629 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200630 quality_counts.num_resolution_reductions = 3;
631 statistics_proxy_->OnAdaptationChanged(
632 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
633 quality_counts);
634 quality_counts.num_framerate_reductions = 1;
635 statistics_proxy_->OnAdaptationChanged(
636 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
637 quality_counts);
638 quality_counts.num_framerate_reductions = 0;
639 statistics_proxy_->OnAdaptationChanged(
640 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
641 quality_counts);
642 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
643 statistics_proxy_->OnAdaptationChanged(
644 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
645 quality_counts);
646 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
647 statistics_proxy_->OnAdaptationChanged(
648 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
649 quality_counts);
650 quality_counts.num_resolution_reductions = 0;
651 statistics_proxy_->OnAdaptationChanged(
652 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
653 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100654
655 fake_clock_.AdvanceTimeMilliseconds(10000);
656 statistics_proxy_.reset();
657 EXPECT_EQ(1,
658 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
659 EXPECT_EQ(
660 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
661}
662
asapersson6eca98b2017-04-04 23:40:50 -0700663TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700664 // First RTP packet sent.
665 UpdateDataCounters(kFirstSsrc);
666
asapersson09f05612017-05-15 23:40:18 -0700667 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200668 SendStatisticsProxy::AdaptationSteps cpu_counts;
669 SendStatisticsProxy::AdaptationSteps quality_counts;
670 quality_counts.num_framerate_reductions = absl::nullopt;
671 quality_counts.num_resolution_reductions = absl::nullopt;
672 statistics_proxy_->OnAdaptationChanged(
673 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
674 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700675 fake_clock_.AdvanceTimeMilliseconds(10000);
676
asapersson09f05612017-05-15 23:40:18 -0700677 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700678 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200679 quality_counts.num_framerate_reductions = 0;
680 statistics_proxy_->OnAdaptationChanged(
681 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
682 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700683 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200684 statistics_proxy_->OnAdaptationChanged(
685 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
686 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700687 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200688 statistics_proxy_->OnAdaptationChanged(
689 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
690 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700691 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200692 statistics_proxy_->OnAdaptationChanged(
693 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
694 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700695
asapersson09f05612017-05-15 23:40:18 -0700696 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200697 quality_counts.num_framerate_reductions = absl::nullopt;
698 statistics_proxy_->OnAdaptationChanged(
699 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
700 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700701 fake_clock_.AdvanceTimeMilliseconds(30000);
702
asapersson09f05612017-05-15 23:40:18 -0700703 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700704 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200705 quality_counts.num_resolution_reductions = 0;
706 statistics_proxy_->OnAdaptationChanged(
707 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
708 quality_counts);
709 statistics_proxy_->OnAdaptationChanged(
710 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
711 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700712 fake_clock_.AdvanceTimeMilliseconds(10000);
713
asapersson09f05612017-05-15 23:40:18 -0700714 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200715 quality_counts.num_resolution_reductions = absl::nullopt;
716 statistics_proxy_->OnAdaptationChanged(
717 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
718 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700719 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200720 statistics_proxy_->OnAdaptationChanged(
721 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
722 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700723 fake_clock_.AdvanceTimeMilliseconds(20000);
724
asapersson0944a802017-04-07 00:57:58 -0700725 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700726 statistics_proxy_.reset();
727 EXPECT_EQ(1,
728 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
729 EXPECT_EQ(
730 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
731}
732
asapersson0944a802017-04-07 00:57:58 -0700733TEST_F(SendStatisticsProxyTest,
734 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
735 // First RTP packet sent.
736 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700737
asapersson0944a802017-04-07 00:57:58 -0700738 // Suspend and resume video.
739 statistics_proxy_->OnSuspendChange(true);
740 fake_clock_.AdvanceTimeMilliseconds(5000);
741 statistics_proxy_->OnSuspendChange(false);
742
743 // Min runtime has passed but scaling not enabled.
744 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
745 statistics_proxy_.reset();
746 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
747 EXPECT_EQ(0,
748 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
749}
750
751TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
752 // First RTP packet sent.
753 UpdateDataCounters(kFirstSsrc);
754
asapersson09f05612017-05-15 23:40:18 -0700755 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200756 SendStatisticsProxy::AdaptationSteps cpu_counts;
757 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700758 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200759 statistics_proxy_->OnAdaptationChanged(
760 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
761 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700762 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200763 statistics_proxy_->OnAdaptationChanged(
764 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
765 quality_counts);
766 statistics_proxy_->OnAdaptationChanged(
767 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
768 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700769
770 // Suspend and resume video.
771 statistics_proxy_->OnSuspendChange(true);
772 fake_clock_.AdvanceTimeMilliseconds(30000);
773 statistics_proxy_->OnSuspendChange(false);
774
775 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200776 statistics_proxy_->OnAdaptationChanged(
777 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
778 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700779 fake_clock_.AdvanceTimeMilliseconds(10000);
780
781 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
782 statistics_proxy_.reset();
783 EXPECT_EQ(1,
784 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
785 EXPECT_EQ(
786 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
787}
788
789TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
790 // First RTP packet sent.
791 UpdateDataCounters(kFirstSsrc);
792
793 // Video not suspended.
794 statistics_proxy_->OnSuspendChange(false);
795 fake_clock_.AdvanceTimeMilliseconds(30000);
796
asapersson09f05612017-05-15 23:40:18 -0700797 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200798 SendStatisticsProxy::AdaptationSteps cpu_counts;
799 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700800 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200801 statistics_proxy_->OnAdaptationChanged(
802 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
803 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700804 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200805 statistics_proxy_->OnAdaptationChanged(
806 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
807 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700808
809 // Video not suspended, stats time already started.
810 statistics_proxy_->OnSuspendChange(false);
811 fake_clock_.AdvanceTimeMilliseconds(10000);
812
asapersson09f05612017-05-15 23:40:18 -0700813 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200814 cpu_counts.num_framerate_reductions = absl::nullopt;
815 cpu_counts.num_resolution_reductions = absl::nullopt;
816 statistics_proxy_->OnAdaptationChanged(
817 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
818 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700819 fake_clock_.AdvanceTimeMilliseconds(30000);
820
821 // Suspend and resume video, stats time not started when scaling not enabled.
822 statistics_proxy_->OnSuspendChange(true);
823 fake_clock_.AdvanceTimeMilliseconds(30000);
824 statistics_proxy_->OnSuspendChange(false);
825 fake_clock_.AdvanceTimeMilliseconds(30000);
826
asapersson09f05612017-05-15 23:40:18 -0700827 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700828 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200829 cpu_counts.num_framerate_reductions = 0;
830 cpu_counts.num_resolution_reductions = 0;
831 statistics_proxy_->OnAdaptationChanged(
832 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
833 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700834 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200835 statistics_proxy_->OnAdaptationChanged(
836 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
837 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700838
839 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
840 statistics_proxy_.reset();
841 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
842 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
843}
844
845TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
846 // First RTP packet sent.
847 UpdateDataCounters(kFirstSsrc);
848
849 // Video suspended.
850 statistics_proxy_->OnSuspendChange(true);
851
asapersson09f05612017-05-15 23:40:18 -0700852 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200853 SendStatisticsProxy::AdaptationSteps cpu_counts;
854 SendStatisticsProxy::AdaptationSteps quality_counts;
855 statistics_proxy_->OnAdaptationChanged(
856 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
857 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700858 fake_clock_.AdvanceTimeMilliseconds(10000);
859
860 // Resume video, stats time started.
861 // Adapt changes: 1, elapsed time: 10 sec.
862 statistics_proxy_->OnSuspendChange(false);
863 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200864 statistics_proxy_->OnAdaptationChanged(
865 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
866 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700867
868 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
869 statistics_proxy_.reset();
870 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
871 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
872}
873
874TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700875 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700876 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200877 SendStatisticsProxy::AdaptationSteps cpu_counts;
878 SendStatisticsProxy::AdaptationSteps quality_counts;
879 statistics_proxy_->OnAdaptationChanged(
880 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
881 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700882 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700883 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700884
asapersson0944a802017-04-07 00:57:58 -0700885 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700886 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200887 statistics_proxy_->OnAdaptationChanged(
888 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
889 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700890 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700891
asapersson0944a802017-04-07 00:57:58 -0700892 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700893 statistics_proxy_.reset();
894 EXPECT_EQ(1,
895 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
896 EXPECT_EQ(
897 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
898}
899
900TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700901 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200902 SendStatisticsProxy::AdaptationSteps cpu_counts;
903 SendStatisticsProxy::AdaptationSteps quality_counts;
904 statistics_proxy_->OnAdaptationChanged(
905 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
906 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700907 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +0200908 cpu_counts.num_framerate_reductions = absl::nullopt;
909 cpu_counts.num_resolution_reductions = absl::nullopt;
910 statistics_proxy_->OnAdaptationChanged(
911 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
912 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700913
914 // Send first packet, scaling disabled.
915 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700916 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700917 fake_clock_.AdvanceTimeMilliseconds(60000);
918
asapersson09f05612017-05-15 23:40:18 -0700919 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200920 cpu_counts.num_resolution_reductions = 0;
921 statistics_proxy_->OnAdaptationChanged(
922 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
923 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700924 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700925 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700926
asapersson0944a802017-04-07 00:57:58 -0700927 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700928 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200929 statistics_proxy_->OnAdaptationChanged(
930 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
931 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700932
asapersson0944a802017-04-07 00:57:58 -0700933 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700934 statistics_proxy_.reset();
935 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
936 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
937}
938
939TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700940 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700941 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200942 SendStatisticsProxy::AdaptationSteps cpu_counts;
943 SendStatisticsProxy::AdaptationSteps quality_counts;
944 quality_counts.num_framerate_reductions = absl::nullopt;
945 quality_counts.num_resolution_reductions = absl::nullopt;
946 statistics_proxy_->OnAdaptationChanged(
947 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
948 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700949
asapersson0944a802017-04-07 00:57:58 -0700950 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200951 statistics_proxy_->OnAdaptationChanged(
952 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
953 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700954 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200955 statistics_proxy_->OnAdaptationChanged(
956 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
957 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700958 fake_clock_.AdvanceTimeMilliseconds(9000);
959
960 // Switch content type, real-time stats should be updated.
961 VideoEncoderConfig config;
962 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +0200963 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -0700964 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
965 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
966 EXPECT_EQ(0,
967 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
968
asapersson0944a802017-04-07 00:57:58 -0700969 // First RTP packet sent, scaling enabled.
970 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +0200971 statistics_proxy_->OnAdaptationChanged(
972 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
973 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700974
asapersson0944a802017-04-07 00:57:58 -0700975 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200976 statistics_proxy_->OnAdaptationChanged(
977 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
978 quality_counts);
979 statistics_proxy_->OnAdaptationChanged(
980 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
981 quality_counts);
982 statistics_proxy_->OnAdaptationChanged(
983 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
984 quality_counts);
985 statistics_proxy_->OnAdaptationChanged(
986 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
987 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700988 fake_clock_.AdvanceTimeMilliseconds(120000);
989
990 statistics_proxy_.reset();
991 EXPECT_EQ(1, metrics::NumSamples(
992 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
993 EXPECT_EQ(1, metrics::NumEvents(
994 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
995 EXPECT_EQ(0, metrics::NumSamples(
996 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
997}
998
asapersson59bac1a2016-01-07 23:36:00 -0800999TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001000 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001001 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1002
Pera48ddb72016-09-29 11:48:50 +02001003 // No switch, stats should not be updated.
1004 VideoEncoderConfig config;
1005 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001006 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001007 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001008
1009 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001010 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001011 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -07001012 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001013}
1014
asapersson320e45a2016-11-29 01:40:35 -08001015TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1016 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1017 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001018
asapersson320e45a2016-11-29 01:40:35 -08001019 statistics_proxy_.reset();
1020 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1021 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1022 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1023 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1024}
1025
1026TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001027 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001028 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001029 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1030 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1031 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001032 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001033
1034 // Not enough samples, stats should not be updated.
1035 for (int i = 0; i < kMinSamples - 1; ++i) {
1036 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001037 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001038 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1039 }
Åsa Persson0122e842017-10-16 12:19:23 +02001040 SetUp(); // Reset stats proxy also causes histograms to be reported.
1041 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1042 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1043
1044 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001045 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001046 for (int i = 0; i < kMinSamples; ++i) {
1047 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001048 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001049 encoded_image._encodedWidth = kWidth;
1050 encoded_image._encodedHeight = kHeight;
1051 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1052 encoded_image._encodedWidth = kWidth / 2;
1053 encoded_image._encodedHeight = kHeight / 2;
1054 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1055 }
1056
asapersson320e45a2016-11-29 01:40:35 -08001057 statistics_proxy_.reset();
1058 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1059 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1060 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1061 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1062}
1063
1064TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1065 const int kFps = 20;
1066 const int kMinPeriodicSamples = 6;
1067 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1068 for (int i = 0; i <= frames; ++i) {
1069 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1070 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1071 }
1072 statistics_proxy_.reset();
1073 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1074 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1075}
1076
1077TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1078 EncodedImage encoded_image;
1079 const int kFps = 20;
1080 const int kMinPeriodicSamples = 6;
1081 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001082 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001083 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001084 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001085 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1086 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001087 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1088 }
1089 statistics_proxy_.reset();
1090 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1091 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1092}
1093
1094TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1095 const int kFps = 20;
1096 const int kSuspendTimeMs = 10000;
1097 const int kMinPeriodicSamples = 6;
1098 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1099 for (int i = 0; i < frames; ++i) {
1100 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1101 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1102 }
1103 // Suspend.
1104 statistics_proxy_->OnSuspendChange(true);
1105 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1106
1107 for (int i = 0; i < frames; ++i) {
1108 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1109 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1110 }
1111 // Suspended time interval should not affect the framerate.
1112 statistics_proxy_.reset();
1113 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1114 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1115}
1116
1117TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1118 EncodedImage encoded_image;
1119 const int kFps = 20;
1120 const int kSuspendTimeMs = 10000;
1121 const int kMinPeriodicSamples = 6;
1122 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001123 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001124 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001125 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001126 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1127 }
1128 // Suspend.
1129 statistics_proxy_->OnSuspendChange(true);
1130 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1131
Åsa Persson0122e842017-10-16 12:19:23 +02001132 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001133 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001134 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001135 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1136 }
1137 // Suspended time interval should not affect the framerate.
1138 statistics_proxy_.reset();
1139 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1140 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1141}
1142
asaperssonf4e44af2017-04-19 02:01:06 -07001143TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001144 SendStatisticsProxy::AdaptationSteps cpu_counts;
1145 SendStatisticsProxy::AdaptationSteps quality_counts;
1146 cpu_counts.num_resolution_reductions = absl::nullopt;
1147 statistics_proxy_->OnAdaptationChanged(
1148 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1149 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001150
1151 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1152 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1153
1154 statistics_proxy_.reset();
1155 EXPECT_EQ(0,
1156 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1157}
1158
1159TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001160 SendStatisticsProxy::AdaptationSteps cpu_counts;
1161 SendStatisticsProxy::AdaptationSteps quality_counts;
1162 cpu_counts.num_resolution_reductions = 0;
1163 statistics_proxy_->OnAdaptationChanged(
1164 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1165 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001166
perkj803d97f2016-11-01 11:45:46 -07001167 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1168 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1169
Niels Möller213618e2018-07-24 09:29:58 +02001170 cpu_counts.num_resolution_reductions = 1;
1171 statistics_proxy_->OnAdaptationChanged(
1172 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1173 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001174
1175 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1176 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1177
1178 statistics_proxy_.reset();
1179 EXPECT_EQ(1,
1180 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1181 EXPECT_EQ(
1182 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1183}
1184
asapersson4374a092016-07-27 00:39:09 -07001185TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1186 const int64_t kTimeSec = 3;
1187 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1188 statistics_proxy_.reset();
1189 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1190 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1191 kTimeSec));
1192}
1193
1194TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1195 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1196 statistics_proxy_.reset();
1197 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1198}
1199
asapersson66d4b372016-12-19 06:50:53 -08001200TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1201 // First RTP packet sent.
1202 UpdateDataCounters(kFirstSsrc);
1203
1204 // Min runtime has passed.
1205 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1206 statistics_proxy_.reset();
1207 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1208 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1209}
1210
1211TEST_F(SendStatisticsProxyTest,
1212 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1213 // First RTP packet sent.
1214 UpdateDataCounters(kFirstSsrc);
1215
1216 // Min runtime has not passed.
1217 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1218 statistics_proxy_.reset();
1219 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1220 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1221}
1222
1223TEST_F(SendStatisticsProxyTest,
1224 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1225 // First RTP packet not sent.
1226 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1227 statistics_proxy_.reset();
1228 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1229}
1230
1231TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1232 // First RTP packet sent and min runtime passed.
1233 UpdateDataCounters(kFirstSsrc);
1234
1235 // No change. Video: 10000 ms, paused: 0 ms (0%).
1236 statistics_proxy_->OnSetEncoderTargetRate(50000);
1237 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1238 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1239
1240 statistics_proxy_.reset();
1241 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1242 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1243 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1244 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1245}
1246
1247TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1248 // First RTP packet sent and min runtime passed.
1249 UpdateDataCounters(kFirstSsrc);
1250
1251 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1252 statistics_proxy_->OnSetEncoderTargetRate(50000);
1253 fake_clock_.AdvanceTimeMilliseconds(7000);
1254 statistics_proxy_->OnSetEncoderTargetRate(0);
1255 fake_clock_.AdvanceTimeMilliseconds(3000);
1256 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1257
1258 statistics_proxy_.reset();
1259 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1260 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1261 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1262 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1263}
1264
1265TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1266 // First RTP packet sent.
1267 UpdateDataCounters(kFirstSsrc);
1268
1269 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1270 statistics_proxy_->OnSetEncoderTargetRate(0);
1271 fake_clock_.AdvanceTimeMilliseconds(1000);
1272 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1273 fake_clock_.AdvanceTimeMilliseconds(7000);
1274 statistics_proxy_->OnSetEncoderTargetRate(60000);
1275 fake_clock_.AdvanceTimeMilliseconds(3000);
1276 statistics_proxy_->OnSetEncoderTargetRate(0);
1277 fake_clock_.AdvanceTimeMilliseconds(250);
1278 statistics_proxy_->OnSetEncoderTargetRate(0);
1279 fake_clock_.AdvanceTimeMilliseconds(750);
1280 statistics_proxy_->OnSetEncoderTargetRate(60000);
1281 fake_clock_.AdvanceTimeMilliseconds(5000);
1282 statistics_proxy_->OnSetEncoderTargetRate(50000);
1283 fake_clock_.AdvanceTimeMilliseconds(4000);
1284 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1285
1286 statistics_proxy_.reset();
1287 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1288 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1289 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1290 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1291}
1292
1293TEST_F(SendStatisticsProxyTest,
1294 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1295 // First RTP packet sent.
1296 UpdateDataCounters(kFirstSsrc);
1297 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1298
1299 // Min runtime has not passed.
1300 statistics_proxy_->OnSetEncoderTargetRate(50000);
1301 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1302 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1303
1304 statistics_proxy_.reset();
1305 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1306}
1307
asapersson118ef002016-03-31 00:00:19 -07001308TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001309 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001310 CodecSpecificInfo codec_info;
1311 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001312
perkj803d97f2016-11-01 11:45:46 -07001313 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001314 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001315 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001316 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001317 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001318 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001319 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001320 }
1321 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001322 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1323 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1324 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1325 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001326}
1327
1328TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1329 VideoSendStream::Config config(nullptr);
1330 config.rtp.ssrcs.push_back(kFirstSsrc);
1331 statistics_proxy_.reset(new SendStatisticsProxy(
1332 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1333
asapersson118ef002016-03-31 00:00:19 -07001334 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001335 CodecSpecificInfo codec_info;
1336 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001337
perkj803d97f2016-11-01 11:45:46 -07001338 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001339 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001340 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001341 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001342 }
1343 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001344 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1345 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001346}
1347
asapersson5265fed2016-04-18 02:58:47 -07001348TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001349 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001350 CodecSpecificInfo codec_info;
1351 codec_info.codecType = kVideoCodecVP9;
1352 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001353
perkj803d97f2016-11-01 11:45:46 -07001354 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001355 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001356 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001357 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001358 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001359 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001360 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001361 }
1362 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001363 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1364 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1365 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1366 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001367}
1368
1369TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1370 VideoSendStream::Config config(nullptr);
1371 config.rtp.ssrcs.push_back(kFirstSsrc);
1372 statistics_proxy_.reset(new SendStatisticsProxy(
1373 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1374
asapersson5265fed2016-04-18 02:58:47 -07001375 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001376 CodecSpecificInfo codec_info;
1377 codec_info.codecType = kVideoCodecVP9;
1378 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001379
perkj803d97f2016-11-01 11:45:46 -07001380 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001381 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001382 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001383 }
1384 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001385 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1386 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001387}
1388
asapersson827cab32016-11-02 09:08:47 -07001389TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1390 EncodedImage encoded_image;
1391 CodecSpecificInfo codec_info;
1392 codec_info.codecType = kVideoCodecH264;
1393
1394 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001395 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001396 encoded_image.qp_ = kQpIdx0;
1397 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001398 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001399 encoded_image.qp_ = kQpIdx1;
1400 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001401 }
1402 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001403 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1404 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1405 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1406 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001407}
1408
asapersson4ee70462016-10-31 04:05:12 -07001409TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001410 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1411 // Configure one stream.
1412 VideoEncoderConfig config;
1413 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1414 VideoStream stream1;
1415 stream1.width = kWidth;
1416 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001417 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001418
1419 const int64_t kMaxEncodedFrameWindowMs = 800;
1420 const int kFps = 20;
1421 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1422 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1423 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1424
1425 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001426 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001427 encoded_image._encodedWidth = kWidth;
1428 encoded_image._encodedHeight = kHeight;
1429 for (int i = 0; i < kMinSamples; ++i) {
1430 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001431 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1432 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001433 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001434 }
asapersson4ee70462016-10-31 04:05:12 -07001435
1436 // Histograms are updated when the statistics_proxy_ is deleted.
1437 statistics_proxy_.reset();
1438 EXPECT_EQ(0, metrics::NumSamples(
1439 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1440 EXPECT_EQ(0, metrics::NumSamples(
1441 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1442}
1443
1444TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001445 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1446 // Configure two streams.
1447 VideoEncoderConfig config;
1448 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1449 VideoStream stream1;
1450 stream1.width = kWidth / 2;
1451 stream1.height = kHeight / 2;
1452 VideoStream stream2;
1453 stream2.width = kWidth;
1454 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001455 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001456
1457 const int64_t kMaxEncodedFrameWindowMs = 800;
1458 const int kFps = 20;
1459 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1460 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1461 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1462
1463 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001464 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001465 for (int i = 0; i < kMinSamples; ++i) {
1466 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001467 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1468 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001469 encoded_image._encodedWidth = kWidth;
1470 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001471 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001472 encoded_image._encodedWidth = kWidth / 2;
1473 encoded_image._encodedHeight = kHeight / 2;
1474 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1475 }
asapersson4ee70462016-10-31 04:05:12 -07001476
1477 // Histograms are updated when the statistics_proxy_ is deleted.
1478 statistics_proxy_.reset();
1479 EXPECT_EQ(1, metrics::NumSamples(
1480 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1481 EXPECT_EQ(1, metrics::NumEvents(
1482 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1483 // No resolution disabled.
1484 EXPECT_EQ(0, metrics::NumSamples(
1485 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1486}
1487
1488TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001489 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1490 // Configure two streams.
1491 VideoEncoderConfig config;
1492 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1493 VideoStream stream1;
1494 stream1.width = kWidth / 2;
1495 stream1.height = kHeight / 2;
1496 VideoStream stream2;
1497 stream2.width = kWidth;
1498 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001499 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001500
1501 const int64_t kMaxEncodedFrameWindowMs = 800;
1502 const int kFps = 20;
1503 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1504 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1505 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1506
1507 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001508 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001509 encoded_image._encodedWidth = kWidth / 2;
1510 encoded_image._encodedHeight = kHeight / 2;
1511 for (int i = 0; i < kMinSamples; ++i) {
1512 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001513 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1514 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001515 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001516 }
asapersson4ee70462016-10-31 04:05:12 -07001517
1518 // Histograms are updated when the statistics_proxy_ is deleted.
1519 statistics_proxy_.reset();
1520 EXPECT_EQ(1, metrics::NumSamples(
1521 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1522 EXPECT_EQ(1, metrics::NumEvents(
1523 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001524 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001525 EXPECT_EQ(1, metrics::NumSamples(
1526 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001527 EXPECT_EQ(1, metrics::NumEvents(
1528 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001529}
1530
1531TEST_F(SendStatisticsProxyTest,
1532 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001533 SendStatisticsProxy::AdaptationSteps cpu_counts;
1534 SendStatisticsProxy::AdaptationSteps quality_counts;
1535 quality_counts.num_resolution_reductions = absl::nullopt;
1536 statistics_proxy_->OnAdaptationChanged(
1537 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1538 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001539 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001540 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001541 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001542 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001543
1544 // Histograms are updated when the statistics_proxy_ is deleted.
1545 statistics_proxy_.reset();
1546 EXPECT_EQ(
1547 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1548 EXPECT_EQ(0, metrics::NumSamples(
1549 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1550}
1551
1552TEST_F(SendStatisticsProxyTest,
1553 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02001554 SendStatisticsProxy::AdaptationSteps cpu_counts;
1555 SendStatisticsProxy::AdaptationSteps quality_counts;
1556 quality_counts.num_resolution_reductions = 0;
1557 statistics_proxy_->OnAdaptationChanged(
1558 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1559 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001560 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001561 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001562 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001563 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001564
1565 // Histograms are updated when the statistics_proxy_ is deleted.
1566 statistics_proxy_.reset();
1567 EXPECT_EQ(
1568 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1569 EXPECT_EQ(1, metrics::NumEvents(
1570 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1571 // No resolution downscale.
1572 EXPECT_EQ(0, metrics::NumSamples(
1573 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1574}
1575
1576TEST_F(SendStatisticsProxyTest,
1577 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1578 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02001579 SendStatisticsProxy::AdaptationSteps cpu_counts;
1580 SendStatisticsProxy::AdaptationSteps quality_counts;
1581 quality_counts.num_resolution_reductions = kDownscales;
1582 statistics_proxy_->OnAdaptationChanged(
1583 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1584 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001585 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001586 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07001587 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001588 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001589 // Histograms are updated when the statistics_proxy_ is deleted.
1590 statistics_proxy_.reset();
1591 EXPECT_EQ(
1592 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1593 EXPECT_EQ(1, metrics::NumEvents(
1594 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1595 // Resolution downscales.
1596 EXPECT_EQ(1, metrics::NumSamples(
1597 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1598 EXPECT_EQ(
1599 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1600 kDownscales));
1601}
1602
1603TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1604 // Initially false.
1605 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001606
Åsa Perssonaa329e72017-12-15 15:54:44 +01001607 // Configure two streams.
1608 VideoEncoderConfig config;
1609 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1610 VideoStream stream1;
1611 stream1.width = kWidth / 2;
1612 stream1.height = kHeight / 2;
1613 VideoStream stream2;
1614 stream2.width = kWidth;
1615 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001616 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001617
1618 const int64_t kMaxEncodedFrameWindowMs = 800;
1619 const int kFps = 20;
1620 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1621 kFps * kMaxEncodedFrameWindowMs / 1000;
1622
1623 // One stream encoded.
1624 EncodedImage encoded_image;
1625 encoded_image._encodedWidth = kWidth / 2;
1626 encoded_image._encodedHeight = kHeight / 2;
1627 for (int i = 0; i < kMinSamples; ++i) {
1628 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001629 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1630 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001631 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1632 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1633 }
1634
1635 // First frame removed from EncodedFrameMap, stats updated.
1636 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001637 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
kthelgason0cd27ba2016-12-19 06:32:16 -08001638 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1639 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1640
Åsa Perssonaa329e72017-12-15 15:54:44 +01001641 // Two streams encoded.
1642 for (int i = 0; i < kMinSamples; ++i) {
1643 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001644 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1645 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001646 encoded_image._encodedWidth = kWidth;
1647 encoded_image._encodedHeight = kHeight;
1648 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1649 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1650 encoded_image._encodedWidth = kWidth / 2;
1651 encoded_image._encodedHeight = kHeight / 2;
1652 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1653 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1654 }
1655
1656 // First frame with two streams removed, expect no resolution limit.
1657 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001658 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1659 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001660 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1661 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001662
1663 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02001664 SendStatisticsProxy::AdaptationSteps cpu_counts;
1665 SendStatisticsProxy::AdaptationSteps quality_counts;
1666 quality_counts.num_resolution_reductions = 1;
1667 statistics_proxy_->OnAdaptationChanged(
1668 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1669 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001670 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1671 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1672}
1673
asapersson66d4b372016-12-19 06:50:53 -08001674TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1675 // Initially zero.
1676 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1677
1678 const int kBitrate = 100000;
1679 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1680 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1681
1682 statistics_proxy_->OnSetEncoderTargetRate(0);
1683 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1684}
1685
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001686TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001687 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001688 std::max(
1689 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1690 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1691 config_.rtp.rtx.ssrcs.end())) +
1692 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001693 // From RtcpStatisticsCallback.
1694 RtcpStatistics rtcp_stats;
1695 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001696 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001697
1698 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001699 uint32_t total = 0;
1700 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001701 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001702 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001703
1704 // From FrameCountObserver.
1705 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001706 FrameCounts frame_counts;
1707 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001708 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001709
1710 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1711 EXPECT_TRUE(stats.substreams.empty());
1712}
1713
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001714TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1715 static const int kEncodedWidth = 123;
1716 static const int kEncodedHeight = 81;
1717 EncodedImage encoded_image;
1718 encoded_image._encodedWidth = kEncodedWidth;
1719 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001720 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001721
kjellander02b3d272016-04-20 05:05:54 -07001722 CodecSpecificInfo codec_info;
1723 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001724
kjellander02b3d272016-04-20 05:05:54 -07001725 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001726 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001727 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001728
1729 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001730 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1731 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1732 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1733 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001734
1735 // Forward almost to timeout, this should not have removed stats.
1736 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1737 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001738 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1739 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001740
1741 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1742 // resolution still times out (no global timeout for all stats).
1743 RtcpStatistics rtcp_statistics;
1744 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1745 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1746
1747 // Report stats for second SSRC to make sure it's not outdated along with the
1748 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001749 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001750
1751 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1752 // reported, but substream 1 should.
1753 fake_clock_.AdvanceTimeMilliseconds(1);
1754 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001755 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1756 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1757 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1758 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001759}
1760
Peter Boström20f3f942015-05-15 11:33:39 +02001761TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1762 static const int kEncodedWidth = 123;
1763 static const int kEncodedHeight = 81;
1764 EncodedImage encoded_image;
1765 encoded_image._encodedWidth = kEncodedWidth;
1766 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001767 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02001768
kjellander02b3d272016-04-20 05:05:54 -07001769 CodecSpecificInfo codec_info;
1770 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02001771
kjellander02b3d272016-04-20 05:05:54 -07001772 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001773 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001774 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001775
1776 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1777 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1778 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1779 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1780 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1781 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1782}
1783
1784TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001785 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001786 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1787 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1788 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1789
1790 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1791
1792 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001793 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001794 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001795 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001796 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1797 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1798 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1799}
1800
sprang07fb9be2016-02-24 07:55:00 -08001801TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1802 RtcpPacketTypeCounterObserver* proxy =
1803 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1804 RtcpPacketTypeCounter counters;
1805 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1806 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1807 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1808
1809 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1810
1811 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1812 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1813 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1814 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1815 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1816
1817 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1818 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1819
1820 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001821 VideoEncoderConfig config;
1822 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001823 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001824
asapersson01d70a32016-05-20 06:29:46 -07001825 EXPECT_EQ(1,
1826 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1827 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1828 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1829 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001830 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1831
1832 const int kRate = 60 * 2; // Packets per minute with two streams.
1833
asapersson01d70a32016-05-20 06:29:46 -07001834 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1835 1 * kRate));
1836 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1837 2 * kRate));
1838 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1839 3 * kRate));
1840 EXPECT_EQ(
1841 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1842 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001843
1844 // New start time but same counter values.
1845 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1846 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1847
1848 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1849
1850 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1851 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1852 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1853 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1854 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1855
1856 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1857 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1858
1859 SetUp(); // Reset stats proxy also causes histograms to be reported.
1860
asapersson01d70a32016-05-20 06:29:46 -07001861 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001862 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001863 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001864 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001865 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001866 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1867 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001868 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001869 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1870
asapersson01d70a32016-05-20 06:29:46 -07001871 EXPECT_EQ(1, metrics::NumEvents(
1872 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1873 1 * kRate));
1874 EXPECT_EQ(1, metrics::NumEvents(
1875 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1876 2 * kRate));
1877 EXPECT_EQ(1, metrics::NumEvents(
1878 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1879 3 * kRate));
1880 EXPECT_EQ(1,
1881 metrics::NumEvents(
1882 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1883 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001884}
1885
asaperssona6a699a2016-11-25 03:52:46 -08001886TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1887 statistics_proxy_.reset(
1888 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1889 VideoEncoderConfig::ContentType::kRealtimeVideo));
1890
1891 StreamDataCountersCallback* proxy =
1892 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1893 StreamDataCounters counters;
1894 proxy->DataCountersUpdated(counters, kFirstSsrc);
1895 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1896
1897 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1898 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1899}
1900
1901TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1902 statistics_proxy_.reset(
1903 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1904 VideoEncoderConfig::ContentType::kRealtimeVideo));
1905
1906 StreamDataCountersCallback* proxy =
1907 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001908 StreamDataCounters counters;
1909 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001910
asapersson93e1e232017-02-06 05:18:35 -08001911 const int kMinRequiredPeriodSamples = 8;
1912 const int kPeriodIntervalMs = 2000;
1913 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1914 counters.transmitted.packets += 20;
1915 counters.transmitted.header_bytes += 500;
1916 counters.transmitted.padding_bytes += 1000;
1917 counters.transmitted.payload_bytes += 2000;
1918 counters.retransmitted.packets += 2;
1919 counters.retransmitted.header_bytes += 25;
1920 counters.retransmitted.padding_bytes += 100;
1921 counters.retransmitted.payload_bytes += 250;
1922 counters.fec = counters.retransmitted;
1923 rtx_counters.transmitted = counters.transmitted;
1924 // Advance one interval and update counters.
1925 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1926 proxy->DataCountersUpdated(counters, kFirstSsrc);
1927 proxy->DataCountersUpdated(counters, kSecondSsrc);
1928 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1929 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1930 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1931 }
asaperssona6a699a2016-11-25 03:52:46 -08001932
asaperssona6a699a2016-11-25 03:52:46 -08001933 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001934 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001935 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001936 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1937 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1938 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1939 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1940 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001941 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001942 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1943 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001944 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001945 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1946 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1947 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1948 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1949 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001950 EXPECT_EQ(1,
1951 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001952 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001953 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001954}
1955
Erik Språng22c2b482016-03-01 09:40:42 +01001956TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1957 StreamDataCountersCallback* proxy =
1958 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1959 StreamDataCounters counters;
1960 StreamDataCounters rtx_counters;
1961 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001962
asapersson93e1e232017-02-06 05:18:35 -08001963 const int kMinRequiredPeriodSamples = 8;
1964 const int kPeriodIntervalMs = 2000;
1965 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1966 counters.transmitted.packets += 20;
1967 counters.transmitted.header_bytes += 500;
1968 counters.transmitted.padding_bytes += 1000;
1969 counters.transmitted.payload_bytes += 2000;
1970 counters.retransmitted.packets += 2;
1971 counters.retransmitted.header_bytes += 25;
1972 counters.retransmitted.padding_bytes += 100;
1973 counters.retransmitted.payload_bytes += 250;
1974 counters.fec = counters.retransmitted;
1975 rtx_counters.transmitted = counters.transmitted;
1976 // Advance one interval and update counters.
1977 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1978 proxy->DataCountersUpdated(counters, kFirstSsrc);
1979 proxy->DataCountersUpdated(counters, kSecondSsrc);
1980 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1981 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1982 }
Erik Språng22c2b482016-03-01 09:40:42 +01001983
1984 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001985 VideoEncoderConfig config;
1986 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001987 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01001988
asapersson93e1e232017-02-06 05:18:35 -08001989 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001990 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001991 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1992 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1993 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1994 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1995 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001996 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001997 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1998 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001999 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002000 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2001 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2002 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2003 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2004 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01002005 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002006 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002007 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002008 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002009
asapersson93e1e232017-02-06 05:18:35 -08002010 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002011 // Double counter values, this should result in the same counts as before but
2012 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002013 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2014 counters.transmitted.packets += 20;
2015 counters.transmitted.header_bytes += 500;
2016 counters.transmitted.padding_bytes += 1000;
2017 counters.transmitted.payload_bytes += 2000;
2018 counters.retransmitted.packets += 2;
2019 counters.retransmitted.header_bytes += 25;
2020 counters.retransmitted.padding_bytes += 100;
2021 counters.retransmitted.payload_bytes += 250;
2022 counters.fec = counters.retransmitted;
2023 rtx_counters.transmitted = counters.transmitted;
2024 // Advance one interval and update counters.
2025 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2026 proxy->DataCountersUpdated(counters, kFirstSsrc);
2027 proxy->DataCountersUpdated(counters, kSecondSsrc);
2028 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2029 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2030 }
Erik Språng22c2b482016-03-01 09:40:42 +01002031
asapersson93e1e232017-02-06 05:18:35 -08002032 // Reset stats proxy also causes histograms to be reported.
2033 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002034
asapersson93e1e232017-02-06 05:18:35 -08002035 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07002036 EXPECT_EQ(1,
2037 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002038 EXPECT_EQ(
2039 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2040 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
2041 EXPECT_EQ(
2042 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2043 EXPECT_EQ(1, metrics::NumEvents(
2044 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2045 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07002046 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002047 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002048 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002049 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
2050 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07002051 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002052 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002053 EXPECT_EQ(1, metrics::NumEvents(
2054 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
2055 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2056 EXPECT_EQ(
2057 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2058 EXPECT_EQ(1, metrics::NumEvents(
2059 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2060 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07002061 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01002062 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07002063 EXPECT_EQ(1,
2064 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08002065 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2066}
Erik Språng22c2b482016-03-01 09:40:42 +01002067
asapersson93e1e232017-02-06 05:18:35 -08002068TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2069 StreamDataCountersCallback* proxy =
2070 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2071 StreamDataCounters counters;
2072 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002073
asapersson93e1e232017-02-06 05:18:35 -08002074 const int kMinRequiredPeriodSamples = 8;
2075 const int kPeriodIntervalMs = 2000;
2076 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2077 counters.transmitted.packets += 20;
2078 counters.transmitted.header_bytes += 500;
2079 counters.transmitted.payload_bytes += 2000;
2080 counters.fec = counters.retransmitted;
2081 // Advance one interval and update counters.
2082 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2083 proxy->DataCountersUpdated(counters, kFirstSsrc);
2084 }
2085
2086 // RTX enabled. No data sent over RTX.
2087 statistics_proxy_.reset();
2088 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2089 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2090}
2091
2092TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2093 VideoSendStream::Config config(nullptr);
2094 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2095 statistics_proxy_.reset(new SendStatisticsProxy(
2096 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2097
2098 StreamDataCountersCallback* proxy =
2099 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2100 StreamDataCounters counters;
2101
2102 const int kMinRequiredPeriodSamples = 8;
2103 const int kPeriodIntervalMs = 2000;
2104 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2105 counters.transmitted.packets += 20;
2106 counters.transmitted.header_bytes += 500;
2107 counters.transmitted.payload_bytes += 2000;
2108 counters.fec = counters.retransmitted;
2109 // Advance one interval and update counters.
2110 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2111 proxy->DataCountersUpdated(counters, kFirstSsrc);
2112 }
2113
2114 // RTX not enabled.
2115 statistics_proxy_.reset();
2116 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2117}
2118
2119TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2120 StreamDataCountersCallback* proxy =
2121 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2122 StreamDataCounters counters;
2123 StreamDataCounters rtx_counters;
2124
2125 const int kMinRequiredPeriodSamples = 8;
2126 const int kPeriodIntervalMs = 2000;
2127 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2128 counters.transmitted.packets += 20;
2129 counters.transmitted.header_bytes += 500;
2130 counters.transmitted.payload_bytes += 2000;
2131 // Advance one interval and update counters.
2132 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2133 proxy->DataCountersUpdated(counters, kFirstSsrc);
2134 }
2135
2136 // FEC enabled. No FEC data sent.
2137 statistics_proxy_.reset();
2138 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2139 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2140}
2141
2142TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2143 VideoSendStream::Config config(nullptr);
2144 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2145 statistics_proxy_.reset(new SendStatisticsProxy(
2146 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2147
2148 StreamDataCountersCallback* proxy =
2149 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2150 StreamDataCounters counters;
2151
2152 const int kMinRequiredPeriodSamples = 8;
2153 const int kPeriodIntervalMs = 2000;
2154 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2155 counters.transmitted.packets += 20;
2156 counters.transmitted.header_bytes += 500;
2157 counters.transmitted.payload_bytes += 2000;
2158 counters.fec = counters.retransmitted;
2159 // Advance one interval and update counters.
2160 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2161 proxy->DataCountersUpdated(counters, kFirstSsrc);
2162 }
2163
2164 // FEC not enabled.
2165 statistics_proxy_.reset();
2166 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002167}
2168
asapersson8d75ac72017-09-15 06:41:15 -07002169TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002170 const std::string kName = "encoderName";
2171 statistics_proxy_->OnEncoderImplementationChanged(kName);
2172 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002173}
2174
Sergey Silkinbb081a62018-09-04 18:34:22 +02002175TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2176 static const int kEncodedWidth = 123;
2177 static const int kEncodedHeight = 81;
2178 EncodedImage encoded_image;
2179 encoded_image._encodedWidth = kEncodedWidth;
2180 encoded_image._encodedHeight = kEncodedHeight;
2181 encoded_image.SetSpatialIndex(0);
2182
2183 CodecSpecificInfo codec_info;
2184 codec_info.codecType = kVideoCodecVP9;
2185
2186 // For first picture, it is expected that low layer updates resolution.
2187 codec_info.codecSpecific.VP9.end_of_picture = false;
2188 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2189 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2190 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2191 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2192
2193 // Top layer updates resolution.
2194 encoded_image._encodedWidth = kEncodedWidth * 2;
2195 encoded_image._encodedHeight = kEncodedHeight * 2;
2196 codec_info.codecSpecific.VP9.end_of_picture = true;
2197 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2198 stats = statistics_proxy_->GetStats();
2199 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2200 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2201
2202 // Low layer of next frame doesn't update resolution.
2203 encoded_image._encodedWidth = kEncodedWidth;
2204 encoded_image._encodedHeight = kEncodedHeight;
2205 codec_info.codecSpecific.VP9.end_of_picture = false;
2206 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2207 stats = statistics_proxy_->GetStats();
2208 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2209 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2210}
2211
asapersson8d75ac72017-09-15 06:41:15 -07002212class ForcedFallbackTest : public SendStatisticsProxyTest {
2213 public:
2214 explicit ForcedFallbackTest(const std::string& field_trials)
2215 : SendStatisticsProxyTest(field_trials) {
2216 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002217 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002218 encoded_image_._encodedWidth = kWidth;
2219 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002220 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002221 }
2222
2223 ~ForcedFallbackTest() override {}
2224
2225 protected:
2226 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002227 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2228
asapersson8d75ac72017-09-15 06:41:15 -07002229 // First frame is not updating stats, insert initial frame.
2230 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2231 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2232 }
2233 for (int i = 0; i < num_frames; ++i) {
2234 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2235 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2236 }
2237 // Add frame to include last time interval.
2238 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2239 }
2240
2241 EncodedImage encoded_image_;
2242 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002243 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002244 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2245 const int kFrameIntervalMs = 1000;
2246 const int kMinFrames = 20; // Min run time 20 sec.
2247};
2248
2249class ForcedFallbackDisabled : public ForcedFallbackTest {
2250 public:
2251 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002252 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2253 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002254};
2255
2256class ForcedFallbackEnabled : public ForcedFallbackTest {
2257 public:
2258 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002259 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2260 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002261};
2262
2263TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2264 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2265 statistics_proxy_.reset();
2266 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2267 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2268}
2269
2270TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2271 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002272 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002273 statistics_proxy_.reset();
2274 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2275 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2276 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2277 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2278}
2279
2280TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2281 codec_info_.codecType = kVideoCodecVP9;
2282 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2283 statistics_proxy_.reset();
2284 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2285 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2286}
2287
2288TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2289 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2290 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2291 statistics_proxy_.reset();
2292 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2293 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2294}
2295
2296TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002297 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002298 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2299 statistics_proxy_.reset();
2300 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2301 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2302}
2303
2304TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2305 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2306 statistics_proxy_.reset();
2307 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2308 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2309}
2310
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002311TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2312 InsertEncodedFrames(1, kFrameIntervalMs);
2313 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2314}
2315
2316TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2317 InsertEncodedFrames(1, kFrameIntervalMs);
2318 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2319}
2320
2321TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002322 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002323 InsertEncodedFrames(1, kFrameIntervalMs);
2324 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2325}
2326
2327TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2328 encoded_image_._encodedWidth = kWidth + 1;
2329 InsertEncodedFrames(1, kFrameIntervalMs);
2330 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2331}
2332
2333TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002334 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002335 InsertEncodedFrames(1, kFrameIntervalMs);
2336 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2337}
2338
2339TEST_F(ForcedFallbackDisabled,
2340 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2341 encoded_image_._encodedWidth = kWidth + 1;
2342 statistics_proxy_->OnMinPixelLimitReached();
2343 InsertEncodedFrames(1, kFrameIntervalMs);
2344 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2345}
2346
asapersson8d75ac72017-09-15 06:41:15 -07002347TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2348 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002349 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002350 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002351 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002352 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002353 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002354 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002355
2356 statistics_proxy_.reset();
2357 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2358 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2359 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2360 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2361}
2362
2363TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2364 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2365 const int kMaxFrameDiffMs = 2000;
2366
2367 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2368 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002369 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002370 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002371 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002372 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002373 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002374 InsertEncodedFrames(20, 1000);
2375 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2376 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002377 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002378 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002379 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002380 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002381 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002382 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002383 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002384
2385 statistics_proxy_.reset();
2386 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2387 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2388 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2389 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2390}
2391
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002392TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2393 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002394 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002395 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2396
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002397 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002398 statistics_proxy_.reset();
2399 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2400 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2401}
2402
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002403TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2404 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002405 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002406 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2407
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002408 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002409 statistics_proxy_.reset();
2410 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2411 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2412}
2413
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002414} // namespace webrtc