blob: 98ad5668a5eee88d179658ca910f3e17dd956fb4 [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"
19#include "system_wrappers/include/metrics_default.h"
asapersson8d75ac72017-09-15 06:41:15 -070020#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000022
23namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070024namespace {
25const uint32_t kFirstSsrc = 17;
26const uint32_t kSecondSsrc = 42;
27const uint32_t kFirstRtxSsrc = 18;
28const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080029const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080030const int kFpsPeriodicIntervalMs = 2000;
Åsa Persson59283e42017-12-12 14:14:42 +010031const int kPreferredBps = 50000;
asapersson320e45a2016-11-29 01:40:35 -080032const int kWidth = 640;
33const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070034const int kQpIdx0 = 21;
35const int kQpIdx1 = 39;
Åsa Persson59283e42017-12-12 14:14:42 +010036const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080037const CodecSpecificInfo kDefaultCodecInfo = []() {
38 CodecSpecificInfo codec_info;
39 codec_info.codecType = kVideoCodecVP8;
40 codec_info.codecSpecific.VP8.simulcastIdx = 0;
41 return codec_info;
42}();
asapersson5265fed2016-04-18 02:58:47 -070043} // namespace
sprang07fb9be2016-02-24 07:55:00 -080044
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000045class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000046 public:
asapersson8d75ac72017-09-15 06:41:15 -070047 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
48 explicit SendStatisticsProxyTest(const std::string& field_trials)
49 : override_field_trials_(field_trials),
50 fake_clock_(1234),
51 config_(GetTestConfig()),
52 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070053 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000054 virtual ~SendStatisticsProxyTest() {}
55
56 protected:
57 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070058 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080059 statistics_proxy_.reset(new SendStatisticsProxy(
60 &fake_clock_, GetTestConfig(),
61 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000062 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070063 for (const auto& ssrc : config_.rtp.ssrcs)
64 expected_.substreams[ssrc].is_rtx = false;
65 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
66 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000067 }
68
69 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070070 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080071 config.rtp.ssrcs.push_back(kFirstSsrc);
72 config.rtp.ssrcs.push_back(kSecondSsrc);
73 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
74 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070075 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000076 return config;
77 }
78
asaperssona6a699a2016-11-25 03:52:46 -080079 VideoSendStream::Config GetTestConfigWithFlexFec() {
80 VideoSendStream::Config config(nullptr);
81 config.rtp.ssrcs.push_back(kFirstSsrc);
82 config.rtp.ssrcs.push_back(kSecondSsrc);
83 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
84 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080085 config.rtp.flexfec.payload_type = 50;
86 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080087 return config;
88 }
89
90 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
91 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
92 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
93 stats.substreams.find(ssrc);
94 EXPECT_NE(it, stats.substreams.end());
95 return it->second;
96 }
97
asapersson66d4b372016-12-19 06:50:53 -080098 void UpdateDataCounters(uint32_t ssrc) {
99 StreamDataCountersCallback* proxy =
100 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
101 StreamDataCounters counters;
102 proxy->DataCountersUpdated(counters, ssrc);
103 }
104
sprang@webrtc.org09315702014-02-07 12:06:29 +0000105 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000106 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
107 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000108 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
Pera48ddb72016-09-29 11:48:50 +0200109 EXPECT_EQ(one.preferred_media_bitrate_bps,
110 other.preferred_media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000111 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000112
113 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000114 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000115 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000116 it != one.substreams.end(); ++it) {
117 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
118 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000119 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000120 const VideoSendStream::StreamStats& a = it->second;
121 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000122
asapersson2e5cfcd2016-08-11 08:41:18 -0700123 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000124 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
125 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000126 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000127 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
128 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000129
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000130 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
131 b.rtp_stats.transmitted.payload_bytes);
132 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
133 b.rtp_stats.transmitted.header_bytes);
134 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
135 b.rtp_stats.transmitted.padding_bytes);
136 EXPECT_EQ(a.rtp_stats.transmitted.packets,
137 b.rtp_stats.transmitted.packets);
138 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
139 b.rtp_stats.retransmitted.packets);
140 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000141
142 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700143 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
144 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
145 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000146 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
147 }
148 }
149
asapersson8d75ac72017-09-15 06:41:15 -0700150 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000151 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800152 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000153 VideoSendStream::Config config_;
154 int avg_delay_ms_;
155 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000157 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
158 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000159};
160
161TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
162 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700163 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000164 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000165
166 // Add statistics with some arbitrary, but unique, numbers.
167 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700168 ssrc_stats.rtcp_stats.packets_lost = offset;
169 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000170 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
171 ssrc_stats.rtcp_stats.jitter = offset + 3;
172 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
173 }
asapersson35151f32016-05-02 23:44:01 -0700174 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000175 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000176
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000177 // Add statistics with some arbitrary, but unique, numbers.
178 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700179 ssrc_stats.rtcp_stats.packets_lost = offset;
180 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000181 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
182 ssrc_stats.rtcp_stats.jitter = offset + 3;
183 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
184 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000185 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000186 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000187}
188
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000189TEST_F(SendStatisticsProxyTest, Suspended) {
190 // Verify that the value is false by default.
191 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
192
193 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200194 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000195 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
196
197 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200198 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000199 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
200}
201
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000202TEST_F(SendStatisticsProxyTest, FrameCounts) {
203 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700204 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000205 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000206 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
207 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000208 FrameCounts frame_counts;
209 frame_counts.key_frames = offset;
210 frame_counts.delta_frames = offset + 1;
211 stats.frame_counts = frame_counts;
212 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000213 }
asapersson35151f32016-05-02 23:44:01 -0700214 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000215 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000216 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
217 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000218 FrameCounts frame_counts;
219 frame_counts.key_frames = offset;
220 frame_counts.delta_frames = offset + 1;
221 stats.frame_counts = frame_counts;
222 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000223 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224
225 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000226 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000227}
228
229TEST_F(SendStatisticsProxyTest, DataCounters) {
230 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700231 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000232 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
233 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000234 size_t offset = ssrc * sizeof(StreamDataCounters);
235 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000236 counters.transmitted.payload_bytes = offset;
237 counters.transmitted.header_bytes = offset + 1;
238 counters.fec.packets = offset_uint32 + 2;
239 counters.transmitted.padding_bytes = offset + 3;
240 counters.retransmitted.packets = offset_uint32 + 4;
241 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000242 callback->DataCountersUpdated(counters, ssrc);
243 }
asapersson35151f32016-05-02 23:44:01 -0700244 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000245 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
246 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000247 size_t offset = ssrc * sizeof(StreamDataCounters);
248 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000249 counters.transmitted.payload_bytes = offset;
250 counters.transmitted.header_bytes = offset + 1;
251 counters.fec.packets = offset_uint32 + 2;
252 counters.transmitted.padding_bytes = offset + 3;
253 counters.retransmitted.packets = offset_uint32 + 4;
254 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000255 callback->DataCountersUpdated(counters, ssrc);
256 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000257
258 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000259 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000260}
261
262TEST_F(SendStatisticsProxyTest, Bitrate) {
263 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700264 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700265 uint32_t total;
266 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000267 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700268 total = ssrc;
269 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000270 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700271 expected_.substreams[ssrc].total_bitrate_bps = total;
272 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000273 }
asapersson35151f32016-05-02 23:44:01 -0700274 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700275 uint32_t total;
276 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000277 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700278 total = ssrc;
279 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000280 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700281 expected_.substreams[ssrc].total_bitrate_bps = total;
282 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000283 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000284
285 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000286 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000287}
288
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000289TEST_F(SendStatisticsProxyTest, SendSideDelay) {
290 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700291 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000292 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
293 // stream.
294 int avg_delay_ms = ssrc;
295 int max_delay_ms = ssrc + 1;
296 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
297 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
298 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
299 }
asapersson35151f32016-05-02 23:44:01 -0700300 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000301 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
302 // stream.
303 int avg_delay_ms = ssrc;
304 int max_delay_ms = ssrc + 1;
305 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
306 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
307 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
308 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000309 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000310 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000311}
312
Peter Boströme4499152016-02-05 11:13:28 +0100313TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800314 const int kEncodeTimeMs = 11;
Peter Boströme4499152016-02-05 11:13:28 +0100315 CpuOveruseMetrics metrics;
316 metrics.encode_usage_percent = 80;
317 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs, metrics);
asapersson1aa420b2015-12-07 03:12:22 -0800318
319 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
320 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Peter Boströme4499152016-02-05 11:13:28 +0100321 EXPECT_EQ(metrics.encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800322}
323
Pera48ddb72016-09-29 11:48:50 +0200324TEST_F(SendStatisticsProxyTest, OnEncoderReconfiguredChangePreferredBitrate) {
325 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
326 EXPECT_EQ(0, stats.preferred_media_bitrate_bps);
Pera48ddb72016-09-29 11:48:50 +0200327
328 VideoEncoderConfig config;
Åsa Persson59283e42017-12-12 14:14:42 +0100329 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
Pera48ddb72016-09-29 11:48:50 +0200330 stats = statistics_proxy_->GetStats();
Åsa Persson59283e42017-12-12 14:14:42 +0100331 EXPECT_EQ(kPreferredBps, stats.preferred_media_bitrate_bps);
Pera48ddb72016-09-29 11:48:50 +0200332}
333
sakal43536c32016-10-24 01:46:43 -0700334TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
335 EncodedImage encoded_image;
336 CodecSpecificInfo codec_info;
337 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
338 for (uint32_t i = 1; i <= 3; ++i) {
339 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
340 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
341 }
342}
343
sakal87da4042016-10-31 06:53:47 -0700344TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
345 EncodedImage encoded_image;
346 CodecSpecificInfo codec_info;
347 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
348 encoded_image.qp_ = 3;
349 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
350 EXPECT_EQ(rtc::Optional<uint64_t>(3u), statistics_proxy_->GetStats().qp_sum);
351 encoded_image.qp_ = 127;
352 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
353 EXPECT_EQ(rtc::Optional<uint64_t>(130u),
354 statistics_proxy_->GetStats().qp_sum);
355}
356
357TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
358 EncodedImage encoded_image;
359 CodecSpecificInfo codec_info;
360 encoded_image.qp_ = -1;
361 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
362 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
363 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
364}
365
asapersson09f05612017-05-15 23:40:18 -0700366TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700367 VideoStreamEncoder::AdaptCounts cpu_counts;
368 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700369 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700370 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700371 cpu_counts.fps = 1;
372 cpu_counts.resolution = 0;
373 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
374 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700375 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700376 cpu_counts.fps = 0;
377 cpu_counts.resolution = 1;
378 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
379 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700380 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700381 cpu_counts.fps = 1;
382 cpu_counts.resolution = -1;
383 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
384 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700385 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700386 cpu_counts.fps = -1;
387 cpu_counts.resolution = -1;
388 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
389 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
390 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
391}
392
393TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700394 VideoStreamEncoder::AdaptCounts cpu_counts;
395 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700396 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
397 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
398 quality_counts.fps = 1;
399 quality_counts.resolution = 0;
400 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
401 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
402 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
403 quality_counts.fps = 0;
404 quality_counts.resolution = 1;
405 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
406 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
407 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
408 quality_counts.fps = 1;
409 quality_counts.resolution = -1;
410 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
411 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
412 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
413 quality_counts.fps = -1;
414 quality_counts.resolution = -1;
415 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
416 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
417 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
418}
419
420TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700421 VideoStreamEncoder::AdaptCounts cpu_counts;
422 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700423 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
424
asapersson09f05612017-05-15 23:40:18 -0700425 cpu_counts.resolution = 1;
426 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
427 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700428 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
429 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
430
asapersson09f05612017-05-15 23:40:18 -0700431 cpu_counts.resolution = 2;
432 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
433 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
434 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700435 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700436 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700437}
438
asapersson09f05612017-05-15 23:40:18 -0700439TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700440 VideoStreamEncoder::AdaptCounts cpu_counts;
441 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700442 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
443
asapersson09f05612017-05-15 23:40:18 -0700444 quality_counts.fps = 1;
445 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
446 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
447 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700448 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
449
asapersson09f05612017-05-15 23:40:18 -0700450 quality_counts.fps = 0;
451 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
452 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700453 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700454 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
455 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700456}
457
asapersson09f05612017-05-15 23:40:18 -0700458TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700459 // First RTP packet sent.
460 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700461 // Min runtime has passed.
462 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
463 statistics_proxy_.reset();
464 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
465 EXPECT_EQ(0,
466 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
467}
468
469TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700470 // First RTP packet sent.
471 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700472 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700473 VideoStreamEncoder::AdaptCounts cpu_counts;
474 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700475 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700476 // Min runtime has not passed.
477 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
478 statistics_proxy_.reset();
479 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
480 EXPECT_EQ(0,
481 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
482}
483
asapersson09f05612017-05-15 23:40:18 -0700484TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700485 // First RTP packet sent.
486 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700487 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700488 VideoStreamEncoder::AdaptCounts cpu_counts;
489 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700490 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700491 // Min runtime has passed.
492 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
493 statistics_proxy_.reset();
494 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
495 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700496 EXPECT_EQ(1,
497 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
498 EXPECT_EQ(
499 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
500}
501
502TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700503 // First RTP packet sent.
504 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700505 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700506 VideoStreamEncoder::AdaptCounts cpu_counts;
507 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700508 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700509 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson09f05612017-05-15 23:40:18 -0700510 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700511 fake_clock_.AdvanceTimeMilliseconds(10000);
512 statistics_proxy_.reset();
513 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
514 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
515}
516
517TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700518 // First RTP packet sent.
519 UpdateDataCounters(kFirstSsrc);
520
asapersson09f05612017-05-15 23:40:18 -0700521 // Disable quality adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700522 VideoStreamEncoder::AdaptCounts cpu_counts;
523 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700524 quality_counts.fps = -1;
525 quality_counts.resolution = -1;
526 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700527 fake_clock_.AdvanceTimeMilliseconds(10000);
528
asapersson09f05612017-05-15 23:40:18 -0700529 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700530 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700531 quality_counts.fps = 0;
532 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700533 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700534 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700535 fake_clock_.AdvanceTimeMilliseconds(9000);
asapersson09f05612017-05-15 23:40:18 -0700536 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700537 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700538 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700539
asapersson09f05612017-05-15 23:40:18 -0700540 // Disable quality adaptation.
541 quality_counts.fps = -1;
542 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700543 fake_clock_.AdvanceTimeMilliseconds(30000);
544
asapersson09f05612017-05-15 23:40:18 -0700545 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700546 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700547 quality_counts.resolution = 0;
548 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
549 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700550 fake_clock_.AdvanceTimeMilliseconds(10000);
551
asapersson09f05612017-05-15 23:40:18 -0700552 // Disable quality adaptation.
553 quality_counts.resolution = -1;
554 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700555 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700556 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700557 fake_clock_.AdvanceTimeMilliseconds(20000);
558
asapersson0944a802017-04-07 00:57:58 -0700559 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700560 statistics_proxy_.reset();
561 EXPECT_EQ(1,
562 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
563 EXPECT_EQ(
564 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
565}
566
asapersson0944a802017-04-07 00:57:58 -0700567TEST_F(SendStatisticsProxyTest,
568 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
569 // First RTP packet sent.
570 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700571
asapersson0944a802017-04-07 00:57:58 -0700572 // Suspend and resume video.
573 statistics_proxy_->OnSuspendChange(true);
574 fake_clock_.AdvanceTimeMilliseconds(5000);
575 statistics_proxy_->OnSuspendChange(false);
576
577 // Min runtime has passed but scaling not enabled.
578 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
579 statistics_proxy_.reset();
580 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
581 EXPECT_EQ(0,
582 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
583}
584
585TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
586 // First RTP packet sent.
587 UpdateDataCounters(kFirstSsrc);
588
asapersson09f05612017-05-15 23:40:18 -0700589 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700590 VideoStreamEncoder::AdaptCounts cpu_counts;
591 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700592 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700593 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700594 fake_clock_.AdvanceTimeMilliseconds(20000);
asapersson09f05612017-05-15 23:40:18 -0700595 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
596 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700597
598 // Suspend and resume video.
599 statistics_proxy_->OnSuspendChange(true);
600 fake_clock_.AdvanceTimeMilliseconds(30000);
601 statistics_proxy_->OnSuspendChange(false);
602
603 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700604 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700605 fake_clock_.AdvanceTimeMilliseconds(10000);
606
607 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
608 statistics_proxy_.reset();
609 EXPECT_EQ(1,
610 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
611 EXPECT_EQ(
612 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
613}
614
615TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
616 // First RTP packet sent.
617 UpdateDataCounters(kFirstSsrc);
618
619 // Video not suspended.
620 statistics_proxy_->OnSuspendChange(false);
621 fake_clock_.AdvanceTimeMilliseconds(30000);
622
asapersson09f05612017-05-15 23:40:18 -0700623 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700624 VideoStreamEncoder::AdaptCounts cpu_counts;
625 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700626 // Adapt changes: 1, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700627 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700628 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700629 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700630
631 // Video not suspended, stats time already started.
632 statistics_proxy_->OnSuspendChange(false);
633 fake_clock_.AdvanceTimeMilliseconds(10000);
634
asapersson09f05612017-05-15 23:40:18 -0700635 // Disable adaptation.
636 cpu_counts.fps = -1;
637 cpu_counts.resolution = -1;
638 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700639 fake_clock_.AdvanceTimeMilliseconds(30000);
640
641 // Suspend and resume video, stats time not started when scaling not enabled.
642 statistics_proxy_->OnSuspendChange(true);
643 fake_clock_.AdvanceTimeMilliseconds(30000);
644 statistics_proxy_->OnSuspendChange(false);
645 fake_clock_.AdvanceTimeMilliseconds(30000);
646
asapersson09f05612017-05-15 23:40:18 -0700647 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700648 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700649 cpu_counts.fps = 0;
650 cpu_counts.resolution = 0;
651 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700652 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700653 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700654
655 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
656 statistics_proxy_.reset();
657 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
658 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
659}
660
661TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
662 // First RTP packet sent.
663 UpdateDataCounters(kFirstSsrc);
664
665 // Video suspended.
666 statistics_proxy_->OnSuspendChange(true);
667
asapersson09f05612017-05-15 23:40:18 -0700668 // Enable adaptation, stats time not started when suspended.
mflodmancc3d4422017-08-03 08:27:51 -0700669 VideoStreamEncoder::AdaptCounts cpu_counts;
670 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700671 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700672 fake_clock_.AdvanceTimeMilliseconds(10000);
673
674 // Resume video, stats time started.
675 // Adapt changes: 1, elapsed time: 10 sec.
676 statistics_proxy_->OnSuspendChange(false);
677 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700678 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700679
680 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
681 statistics_proxy_.reset();
682 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
683 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
684}
685
686TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700687 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700688 // Elapsed time before first packet is sent should be excluded.
mflodmancc3d4422017-08-03 08:27:51 -0700689 VideoStreamEncoder::AdaptCounts cpu_counts;
690 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700691 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700692 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700693 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700694
asapersson0944a802017-04-07 00:57:58 -0700695 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700696 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700697 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700698 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700699
asapersson0944a802017-04-07 00:57:58 -0700700 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700701 statistics_proxy_.reset();
702 EXPECT_EQ(1,
703 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
704 EXPECT_EQ(
705 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
706}
707
708TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700709 // Enable and disable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700710 VideoStreamEncoder::AdaptCounts cpu_counts;
711 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700712 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700713 fake_clock_.AdvanceTimeMilliseconds(60000);
asapersson09f05612017-05-15 23:40:18 -0700714 cpu_counts.fps = -1;
715 cpu_counts.resolution = -1;
716 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700717
718 // Send first packet, scaling disabled.
719 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700720 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700721 fake_clock_.AdvanceTimeMilliseconds(60000);
722
asapersson09f05612017-05-15 23:40:18 -0700723 // Enable adaptation.
724 cpu_counts.resolution = 0;
725 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700726 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700727 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700728
asapersson0944a802017-04-07 00:57:58 -0700729 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700730 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700731 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700732
asapersson0944a802017-04-07 00:57:58 -0700733 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700734 statistics_proxy_.reset();
735 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
736 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
737}
738
739TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700740 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700741 UpdateDataCounters(kFirstSsrc);
mflodmancc3d4422017-08-03 08:27:51 -0700742 VideoStreamEncoder::AdaptCounts cpu_counts;
743 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700744 quality_counts.fps = -1;
745 quality_counts.resolution = -1;
746 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700747
asapersson0944a802017-04-07 00:57:58 -0700748 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
asapersson09f05612017-05-15 23:40:18 -0700749 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700750 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700751 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700752 fake_clock_.AdvanceTimeMilliseconds(9000);
753
754 // Switch content type, real-time stats should be updated.
755 VideoEncoderConfig config;
756 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Persson59283e42017-12-12 14:14:42 +0100757 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson6eca98b2017-04-04 23:40:50 -0700758 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
759 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
760 EXPECT_EQ(0,
761 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
762
asapersson0944a802017-04-07 00:57:58 -0700763 // First RTP packet sent, scaling enabled.
764 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700765 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700766
asapersson0944a802017-04-07 00:57:58 -0700767 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
asapersson09f05612017-05-15 23:40:18 -0700768 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
769 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
770 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
771 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700772 fake_clock_.AdvanceTimeMilliseconds(120000);
773
774 statistics_proxy_.reset();
775 EXPECT_EQ(1, metrics::NumSamples(
776 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
777 EXPECT_EQ(1, metrics::NumEvents(
778 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
779 EXPECT_EQ(0, metrics::NumSamples(
780 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
781}
782
asapersson59bac1a2016-01-07 23:36:00 -0800783TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -0700784 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -0800785 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
786
Pera48ddb72016-09-29 11:48:50 +0200787 // No switch, stats should not be updated.
788 VideoEncoderConfig config;
789 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson59283e42017-12-12 14:14:42 +0100790 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson01d70a32016-05-20 06:29:46 -0700791 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800792
793 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +0200794 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Persson59283e42017-12-12 14:14:42 +0100795 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson01d70a32016-05-20 06:29:46 -0700796 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800797}
798
asapersson320e45a2016-11-29 01:40:35 -0800799TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
800 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
801 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -0700802
asapersson320e45a2016-11-29 01:40:35 -0800803 statistics_proxy_.reset();
804 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
805 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
806 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
807 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
808}
809
810TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +0200811 const int64_t kMaxEncodedFrameWindowMs = 800;
812 const int kFps = 20;
813 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
814 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
815 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -0800816 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +0200817
818 // Not enough samples, stats should not be updated.
819 for (int i = 0; i < kMinSamples - 1; ++i) {
820 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
821 ++encoded_image._timeStamp;
asapersson320e45a2016-11-29 01:40:35 -0800822 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
823 }
Åsa Persson0122e842017-10-16 12:19:23 +0200824 SetUp(); // Reset stats proxy also causes histograms to be reported.
825 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
826 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
827
828 // Enough samples, max resolution per frame should be reported.
829 encoded_image._timeStamp = 0xfffffff0; // Will wrap.
830 for (int i = 0; i < kMinSamples; ++i) {
831 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
832 ++encoded_image._timeStamp;
833 encoded_image._encodedWidth = kWidth;
834 encoded_image._encodedHeight = kHeight;
835 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
836 encoded_image._encodedWidth = kWidth / 2;
837 encoded_image._encodedHeight = kHeight / 2;
838 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
839 }
840
asapersson320e45a2016-11-29 01:40:35 -0800841 statistics_proxy_.reset();
842 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
843 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
844 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
845 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
846}
847
848TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
849 const int kFps = 20;
850 const int kMinPeriodicSamples = 6;
851 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
852 for (int i = 0; i <= frames; ++i) {
853 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
854 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
855 }
856 statistics_proxy_.reset();
857 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
858 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
859}
860
861TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
862 EncodedImage encoded_image;
863 const int kFps = 20;
864 const int kMinPeriodicSamples = 6;
865 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +0200866 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800867 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +0200868 ++encoded_image._timeStamp;
869 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
870 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -0800871 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
872 }
873 statistics_proxy_.reset();
874 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
875 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
876}
877
878TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
879 const int kFps = 20;
880 const int kSuspendTimeMs = 10000;
881 const int kMinPeriodicSamples = 6;
882 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
883 for (int i = 0; i < frames; ++i) {
884 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
885 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
886 }
887 // Suspend.
888 statistics_proxy_->OnSuspendChange(true);
889 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
890
891 for (int i = 0; i < frames; ++i) {
892 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
893 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
894 }
895 // Suspended time interval should not affect the framerate.
896 statistics_proxy_.reset();
897 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
898 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
899}
900
901TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
902 EncodedImage encoded_image;
903 const int kFps = 20;
904 const int kSuspendTimeMs = 10000;
905 const int kMinPeriodicSamples = 6;
906 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +0200907 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800908 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
909 encoded_image._timeStamp = i + 1;
910 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
911 }
912 // Suspend.
913 statistics_proxy_->OnSuspendChange(true);
914 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
915
Åsa Persson0122e842017-10-16 12:19:23 +0200916 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800917 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
918 encoded_image._timeStamp = i + 1;
919 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
920 }
921 // Suspended time interval should not affect the framerate.
922 statistics_proxy_.reset();
923 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
924 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
925}
926
asaperssonf4e44af2017-04-19 02:01:06 -0700927TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -0700928 VideoStreamEncoder::AdaptCounts cpu_counts;
929 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700930 cpu_counts.resolution = -1;
931 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -0700932
933 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
934 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
935
936 statistics_proxy_.reset();
937 EXPECT_EQ(0,
938 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
939}
940
941TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
mflodmancc3d4422017-08-03 08:27:51 -0700942 VideoStreamEncoder::AdaptCounts cpu_counts;
943 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700944 cpu_counts.resolution = 0;
945 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -0700946
perkj803d97f2016-11-01 11:45:46 -0700947 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
948 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
949
asapersson09f05612017-05-15 23:40:18 -0700950 cpu_counts.resolution = 1;
951 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -0700952
953 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
954 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
955
956 statistics_proxy_.reset();
957 EXPECT_EQ(1,
958 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
959 EXPECT_EQ(
960 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
961}
962
asapersson4374a092016-07-27 00:39:09 -0700963TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
964 const int64_t kTimeSec = 3;
965 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
966 statistics_proxy_.reset();
967 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
968 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
969 kTimeSec));
970}
971
972TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
973 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
974 statistics_proxy_.reset();
975 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
976}
977
asapersson66d4b372016-12-19 06:50:53 -0800978TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
979 // First RTP packet sent.
980 UpdateDataCounters(kFirstSsrc);
981
982 // Min runtime has passed.
983 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
984 statistics_proxy_.reset();
985 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
986 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
987}
988
989TEST_F(SendStatisticsProxyTest,
990 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
991 // First RTP packet sent.
992 UpdateDataCounters(kFirstSsrc);
993
994 // Min runtime has not passed.
995 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
996 statistics_proxy_.reset();
997 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
998 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
999}
1000
1001TEST_F(SendStatisticsProxyTest,
1002 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1003 // First RTP packet not sent.
1004 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1005 statistics_proxy_.reset();
1006 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1007}
1008
1009TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1010 // First RTP packet sent and min runtime passed.
1011 UpdateDataCounters(kFirstSsrc);
1012
1013 // No change. Video: 10000 ms, paused: 0 ms (0%).
1014 statistics_proxy_->OnSetEncoderTargetRate(50000);
1015 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1016 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1017
1018 statistics_proxy_.reset();
1019 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1020 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1021 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1022 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1023}
1024
1025TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1026 // First RTP packet sent and min runtime passed.
1027 UpdateDataCounters(kFirstSsrc);
1028
1029 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1030 statistics_proxy_->OnSetEncoderTargetRate(50000);
1031 fake_clock_.AdvanceTimeMilliseconds(7000);
1032 statistics_proxy_->OnSetEncoderTargetRate(0);
1033 fake_clock_.AdvanceTimeMilliseconds(3000);
1034 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1035
1036 statistics_proxy_.reset();
1037 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1038 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1039 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1040 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1041}
1042
1043TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1044 // First RTP packet sent.
1045 UpdateDataCounters(kFirstSsrc);
1046
1047 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1048 statistics_proxy_->OnSetEncoderTargetRate(0);
1049 fake_clock_.AdvanceTimeMilliseconds(1000);
1050 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1051 fake_clock_.AdvanceTimeMilliseconds(7000);
1052 statistics_proxy_->OnSetEncoderTargetRate(60000);
1053 fake_clock_.AdvanceTimeMilliseconds(3000);
1054 statistics_proxy_->OnSetEncoderTargetRate(0);
1055 fake_clock_.AdvanceTimeMilliseconds(250);
1056 statistics_proxy_->OnSetEncoderTargetRate(0);
1057 fake_clock_.AdvanceTimeMilliseconds(750);
1058 statistics_proxy_->OnSetEncoderTargetRate(60000);
1059 fake_clock_.AdvanceTimeMilliseconds(5000);
1060 statistics_proxy_->OnSetEncoderTargetRate(50000);
1061 fake_clock_.AdvanceTimeMilliseconds(4000);
1062 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1063
1064 statistics_proxy_.reset();
1065 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1066 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1067 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1068 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1069}
1070
1071TEST_F(SendStatisticsProxyTest,
1072 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1073 // First RTP packet sent.
1074 UpdateDataCounters(kFirstSsrc);
1075 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1076
1077 // Min runtime has not passed.
1078 statistics_proxy_->OnSetEncoderTargetRate(50000);
1079 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1080 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1081
1082 statistics_proxy_.reset();
1083 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1084}
1085
asapersson118ef002016-03-31 00:00:19 -07001086TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001087 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001088 CodecSpecificInfo codec_info;
1089 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001090
perkj803d97f2016-11-01 11:45:46 -07001091 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001092 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001093 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001094 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1095 codec_info.codecSpecific.VP8.simulcastIdx = 1;
asapersson118ef002016-03-31 00:00:19 -07001096 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001097 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001098 }
1099 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001100 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1101 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1102 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1103 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001104}
1105
1106TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1107 VideoSendStream::Config config(nullptr);
1108 config.rtp.ssrcs.push_back(kFirstSsrc);
1109 statistics_proxy_.reset(new SendStatisticsProxy(
1110 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1111
asapersson118ef002016-03-31 00:00:19 -07001112 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001113 CodecSpecificInfo codec_info;
1114 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001115
perkj803d97f2016-11-01 11:45:46 -07001116 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001117 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001118 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001119 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001120 }
1121 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001122 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1123 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001124}
1125
asapersson5265fed2016-04-18 02:58:47 -07001126TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001127 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001128 CodecSpecificInfo codec_info;
1129 codec_info.codecType = kVideoCodecVP9;
1130 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001131
perkj803d97f2016-11-01 11:45:46 -07001132 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001133 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001134 codec_info.codecSpecific.VP9.spatial_idx = 0;
1135 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001136 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001137 codec_info.codecSpecific.VP9.spatial_idx = 1;
1138 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001139 }
1140 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001141 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1142 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1143 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1144 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001145}
1146
1147TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1148 VideoSendStream::Config config(nullptr);
1149 config.rtp.ssrcs.push_back(kFirstSsrc);
1150 statistics_proxy_.reset(new SendStatisticsProxy(
1151 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1152
asapersson5265fed2016-04-18 02:58:47 -07001153 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001154 CodecSpecificInfo codec_info;
1155 codec_info.codecType = kVideoCodecVP9;
1156 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001157
perkj803d97f2016-11-01 11:45:46 -07001158 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001159 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001160 codec_info.codecSpecific.VP9.spatial_idx = 0;
1161 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001162 }
1163 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001164 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1165 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001166}
1167
asapersson827cab32016-11-02 09:08:47 -07001168TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1169 EncodedImage encoded_image;
1170 CodecSpecificInfo codec_info;
1171 codec_info.codecType = kVideoCodecH264;
1172
1173 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1174 encoded_image.qp_ = kQpIdx0;
1175 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1176 }
1177 statistics_proxy_.reset();
1178 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264"));
1179 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264", kQpIdx0));
1180}
1181
asapersson4ee70462016-10-31 04:05:12 -07001182TEST_F(SendStatisticsProxyTest,
Åsa Persson59283e42017-12-12 14:14:42 +01001183 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1184 // Configure one stream.
1185 VideoEncoderConfig config;
1186 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1187 VideoStream stream1;
1188 stream1.width = kWidth;
1189 stream1.height = kHeight;
1190 statistics_proxy_->OnEncoderReconfigured(config, {stream1}, kPreferredBps);
1191
1192 const int64_t kMaxEncodedFrameWindowMs = 800;
1193 const int kFps = 20;
1194 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1195 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1196 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1197
1198 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001199 EncodedImage encoded_image;
Åsa Persson59283e42017-12-12 14:14:42 +01001200 encoded_image._encodedWidth = kWidth;
1201 encoded_image._encodedHeight = kHeight;
1202 for (int i = 0; i < kMinSamples; ++i) {
1203 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1204 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001205 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson59283e42017-12-12 14:14:42 +01001206 }
asapersson4ee70462016-10-31 04:05:12 -07001207
1208 // Histograms are updated when the statistics_proxy_ is deleted.
1209 statistics_proxy_.reset();
1210 EXPECT_EQ(0, metrics::NumSamples(
1211 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1212 EXPECT_EQ(0, metrics::NumSamples(
1213 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1214}
1215
1216TEST_F(SendStatisticsProxyTest,
Åsa Persson59283e42017-12-12 14:14:42 +01001217 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1218 // Configure two streams.
1219 VideoEncoderConfig config;
1220 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1221 VideoStream stream1;
1222 stream1.width = kWidth / 2;
1223 stream1.height = kHeight / 2;
1224 VideoStream stream2;
1225 stream2.width = kWidth;
1226 stream2.height = kHeight;
1227 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1228 kPreferredBps);
1229
1230 const int64_t kMaxEncodedFrameWindowMs = 800;
1231 const int kFps = 20;
1232 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1233 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1234 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1235
1236 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001237 EncodedImage encoded_image;
Åsa Persson59283e42017-12-12 14:14:42 +01001238 for (int i = 0; i < kMinSamples; ++i) {
1239 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1240 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1241 encoded_image._encodedWidth = kWidth;
1242 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001243 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson59283e42017-12-12 14:14:42 +01001244 encoded_image._encodedWidth = kWidth / 2;
1245 encoded_image._encodedHeight = kHeight / 2;
1246 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1247 }
asapersson4ee70462016-10-31 04:05:12 -07001248
1249 // Histograms are updated when the statistics_proxy_ is deleted.
1250 statistics_proxy_.reset();
1251 EXPECT_EQ(1, metrics::NumSamples(
1252 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1253 EXPECT_EQ(1, metrics::NumEvents(
1254 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1255 // No resolution disabled.
1256 EXPECT_EQ(0, metrics::NumSamples(
1257 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1258}
1259
1260TEST_F(SendStatisticsProxyTest,
Åsa Persson59283e42017-12-12 14:14:42 +01001261 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1262 // Configure two streams.
1263 VideoEncoderConfig config;
1264 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1265 VideoStream stream1;
1266 stream1.width = kWidth / 2;
1267 stream1.height = kHeight / 2;
1268 VideoStream stream2;
1269 stream2.width = kWidth;
1270 stream2.height = kHeight;
1271 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1272 kPreferredBps);
1273
1274 const int64_t kMaxEncodedFrameWindowMs = 800;
1275 const int kFps = 20;
1276 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1277 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1278 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1279
1280 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001281 EncodedImage encoded_image;
Åsa Persson59283e42017-12-12 14:14:42 +01001282 encoded_image._encodedWidth = kWidth / 2;
1283 encoded_image._encodedHeight = kHeight / 2;
1284 for (int i = 0; i < kMinSamples; ++i) {
1285 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1286 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001287 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Persson59283e42017-12-12 14:14:42 +01001288 }
asapersson4ee70462016-10-31 04:05:12 -07001289
1290 // Histograms are updated when the statistics_proxy_ is deleted.
1291 statistics_proxy_.reset();
1292 EXPECT_EQ(1, metrics::NumSamples(
1293 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1294 EXPECT_EQ(1, metrics::NumEvents(
1295 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Persson59283e42017-12-12 14:14:42 +01001296 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001297 EXPECT_EQ(1, metrics::NumSamples(
1298 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Persson59283e42017-12-12 14:14:42 +01001299 EXPECT_EQ(1, metrics::NumEvents(
1300 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001301}
1302
1303TEST_F(SendStatisticsProxyTest,
1304 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -07001305 VideoStreamEncoder::AdaptCounts cpu_counts;
1306 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001307 quality_counts.resolution = -1;
1308 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001309 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001310 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001311 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001312
1313 // Histograms are updated when the statistics_proxy_ is deleted.
1314 statistics_proxy_.reset();
1315 EXPECT_EQ(
1316 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1317 EXPECT_EQ(0, metrics::NumSamples(
1318 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1319}
1320
1321TEST_F(SendStatisticsProxyTest,
1322 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
mflodmancc3d4422017-08-03 08:27:51 -07001323 VideoStreamEncoder::AdaptCounts cpu_counts;
1324 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001325 quality_counts.resolution = 0;
1326 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001327 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001328 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001329 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001330
1331 // Histograms are updated when the statistics_proxy_ is deleted.
1332 statistics_proxy_.reset();
1333 EXPECT_EQ(
1334 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1335 EXPECT_EQ(1, metrics::NumEvents(
1336 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1337 // No resolution downscale.
1338 EXPECT_EQ(0, metrics::NumSamples(
1339 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1340}
1341
1342TEST_F(SendStatisticsProxyTest,
1343 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1344 const int kDownscales = 2;
mflodmancc3d4422017-08-03 08:27:51 -07001345 VideoStreamEncoder::AdaptCounts cpu_counts;
1346 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001347 quality_counts.resolution = kDownscales;
1348 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001349 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001350 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001351 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001352 // Histograms are updated when the statistics_proxy_ is deleted.
1353 statistics_proxy_.reset();
1354 EXPECT_EQ(
1355 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1356 EXPECT_EQ(1, metrics::NumEvents(
1357 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1358 // Resolution downscales.
1359 EXPECT_EQ(1, metrics::NumSamples(
1360 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1361 EXPECT_EQ(
1362 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1363 kDownscales));
1364}
1365
1366TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1367 // Initially false.
1368 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001369
Åsa Persson59283e42017-12-12 14:14:42 +01001370 // Configure two streams.
1371 VideoEncoderConfig config;
1372 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1373 VideoStream stream1;
1374 stream1.width = kWidth / 2;
1375 stream1.height = kHeight / 2;
1376 VideoStream stream2;
1377 stream2.width = kWidth;
1378 stream2.height = kHeight;
1379 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1380 kPreferredBps);
1381
1382 const int64_t kMaxEncodedFrameWindowMs = 800;
1383 const int kFps = 20;
1384 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1385 kFps * kMaxEncodedFrameWindowMs / 1000;
1386
1387 // One stream encoded.
1388 EncodedImage encoded_image;
1389 encoded_image._encodedWidth = kWidth / 2;
1390 encoded_image._encodedHeight = kHeight / 2;
1391 for (int i = 0; i < kMinSamples; ++i) {
1392 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1393 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1394 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1395 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1396 }
1397
1398 // First frame removed from EncodedFrameMap, stats updated.
1399 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1400 ++encoded_image._timeStamp;
kthelgason0cd27ba2016-12-19 06:32:16 -08001401 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1402 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1403
Åsa Persson59283e42017-12-12 14:14:42 +01001404 // Two streams encoded.
1405 for (int i = 0; i < kMinSamples; ++i) {
1406 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1407 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1408 encoded_image._encodedWidth = kWidth;
1409 encoded_image._encodedHeight = kHeight;
1410 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1411 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1412 encoded_image._encodedWidth = kWidth / 2;
1413 encoded_image._encodedHeight = kHeight / 2;
1414 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1415 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1416 }
1417
1418 // First frame with two streams removed, expect no resolution limit.
1419 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1420 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001421 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1422 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001423
1424 // Resolution scaled due to quality.
mflodmancc3d4422017-08-03 08:27:51 -07001425 VideoStreamEncoder::AdaptCounts cpu_counts;
1426 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001427 quality_counts.resolution = 1;
1428 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001429 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1430 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1431}
1432
asapersson66d4b372016-12-19 06:50:53 -08001433TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1434 // Initially zero.
1435 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1436
1437 const int kBitrate = 100000;
1438 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1439 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1440
1441 statistics_proxy_->OnSetEncoderTargetRate(0);
1442 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1443}
1444
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001445TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001446 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001447 std::max(
1448 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1449 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1450 config_.rtp.rtx.ssrcs.end())) +
1451 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001452 // From RtcpStatisticsCallback.
1453 RtcpStatistics rtcp_stats;
1454 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001455 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001456
1457 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001458 uint32_t total = 0;
1459 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001460 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001461 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001462
1463 // From FrameCountObserver.
1464 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001465 FrameCounts frame_counts;
1466 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001467 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001468
1469 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1470 EXPECT_TRUE(stats.substreams.empty());
1471}
1472
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001473TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1474 static const int kEncodedWidth = 123;
1475 static const int kEncodedHeight = 81;
1476 EncodedImage encoded_image;
1477 encoded_image._encodedWidth = kEncodedWidth;
1478 encoded_image._encodedHeight = kEncodedHeight;
1479
kjellander02b3d272016-04-20 05:05:54 -07001480 CodecSpecificInfo codec_info;
1481 codec_info.codecType = kVideoCodecVP8;
1482 codec_info.codecSpecific.VP8.simulcastIdx = 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001483
kjellander02b3d272016-04-20 05:05:54 -07001484 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1485 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1486 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001487
1488 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001489 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1490 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1491 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1492 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001493
1494 // Forward almost to timeout, this should not have removed stats.
1495 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1496 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001497 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1498 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001499
1500 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1501 // resolution still times out (no global timeout for all stats).
1502 RtcpStatistics rtcp_statistics;
1503 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1504 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1505
1506 // Report stats for second SSRC to make sure it's not outdated along with the
1507 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001508 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1509 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001510
1511 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1512 // reported, but substream 1 should.
1513 fake_clock_.AdvanceTimeMilliseconds(1);
1514 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001515 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1516 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1517 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1518 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001519}
1520
Peter Boström20f3f942015-05-15 11:33:39 +02001521TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1522 static const int kEncodedWidth = 123;
1523 static const int kEncodedHeight = 81;
1524 EncodedImage encoded_image;
1525 encoded_image._encodedWidth = kEncodedWidth;
1526 encoded_image._encodedHeight = kEncodedHeight;
1527
kjellander02b3d272016-04-20 05:05:54 -07001528 CodecSpecificInfo codec_info;
1529 codec_info.codecType = kVideoCodecVP8;
1530 codec_info.codecSpecific.VP8.simulcastIdx = 0;
Peter Boström20f3f942015-05-15 11:33:39 +02001531
kjellander02b3d272016-04-20 05:05:54 -07001532 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1533 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1534 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001535
1536 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1537 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1538 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1539 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1540 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1541 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1542}
1543
1544TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001545 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001546 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1547 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1548 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1549
1550 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1551
1552 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001553 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001554 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001555 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001556 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1557 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1558 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1559}
1560
sprang07fb9be2016-02-24 07:55:00 -08001561TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1562 RtcpPacketTypeCounterObserver* proxy =
1563 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1564 RtcpPacketTypeCounter counters;
1565 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1566 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1567 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1568
1569 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1570
1571 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1572 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1573 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1574 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1575 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1576
1577 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1578 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1579
1580 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001581 VideoEncoderConfig config;
1582 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Persson59283e42017-12-12 14:14:42 +01001583 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
sprang07fb9be2016-02-24 07:55:00 -08001584
asapersson01d70a32016-05-20 06:29:46 -07001585 EXPECT_EQ(1,
1586 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1587 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1588 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1589 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001590 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1591
1592 const int kRate = 60 * 2; // Packets per minute with two streams.
1593
asapersson01d70a32016-05-20 06:29:46 -07001594 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1595 1 * kRate));
1596 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1597 2 * kRate));
1598 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1599 3 * kRate));
1600 EXPECT_EQ(
1601 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1602 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001603
1604 // New start time but same counter values.
1605 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1606 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1607
1608 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1609
1610 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1611 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1612 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1613 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1614 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1615
1616 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1617 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1618
1619 SetUp(); // Reset stats proxy also causes histograms to be reported.
1620
asapersson01d70a32016-05-20 06:29:46 -07001621 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001622 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001623 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001624 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001625 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001626 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1627 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001628 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001629 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1630
asapersson01d70a32016-05-20 06:29:46 -07001631 EXPECT_EQ(1, metrics::NumEvents(
1632 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1633 1 * kRate));
1634 EXPECT_EQ(1, metrics::NumEvents(
1635 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1636 2 * kRate));
1637 EXPECT_EQ(1, metrics::NumEvents(
1638 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1639 3 * kRate));
1640 EXPECT_EQ(1,
1641 metrics::NumEvents(
1642 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1643 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001644}
1645
asaperssona6a699a2016-11-25 03:52:46 -08001646TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1647 statistics_proxy_.reset(
1648 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1649 VideoEncoderConfig::ContentType::kRealtimeVideo));
1650
1651 StreamDataCountersCallback* proxy =
1652 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1653 StreamDataCounters counters;
1654 proxy->DataCountersUpdated(counters, kFirstSsrc);
1655 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1656
1657 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1658 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1659}
1660
1661TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1662 statistics_proxy_.reset(
1663 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1664 VideoEncoderConfig::ContentType::kRealtimeVideo));
1665
1666 StreamDataCountersCallback* proxy =
1667 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001668 StreamDataCounters counters;
1669 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001670
asapersson93e1e232017-02-06 05:18:35 -08001671 const int kMinRequiredPeriodSamples = 8;
1672 const int kPeriodIntervalMs = 2000;
1673 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1674 counters.transmitted.packets += 20;
1675 counters.transmitted.header_bytes += 500;
1676 counters.transmitted.padding_bytes += 1000;
1677 counters.transmitted.payload_bytes += 2000;
1678 counters.retransmitted.packets += 2;
1679 counters.retransmitted.header_bytes += 25;
1680 counters.retransmitted.padding_bytes += 100;
1681 counters.retransmitted.payload_bytes += 250;
1682 counters.fec = counters.retransmitted;
1683 rtx_counters.transmitted = counters.transmitted;
1684 // Advance one interval and update counters.
1685 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1686 proxy->DataCountersUpdated(counters, kFirstSsrc);
1687 proxy->DataCountersUpdated(counters, kSecondSsrc);
1688 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1689 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1690 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1691 }
asaperssona6a699a2016-11-25 03:52:46 -08001692
asaperssona6a699a2016-11-25 03:52:46 -08001693 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001694 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001695 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001696 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1697 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1698 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1699 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1700 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001701 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001702 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1703 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001704 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001705 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1706 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1707 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1708 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1709 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001710 EXPECT_EQ(1,
1711 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001712 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001713 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001714}
1715
Erik Språng22c2b482016-03-01 09:40:42 +01001716TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1717 StreamDataCountersCallback* proxy =
1718 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1719 StreamDataCounters counters;
1720 StreamDataCounters rtx_counters;
1721 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001722
asapersson93e1e232017-02-06 05:18:35 -08001723 const int kMinRequiredPeriodSamples = 8;
1724 const int kPeriodIntervalMs = 2000;
1725 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1726 counters.transmitted.packets += 20;
1727 counters.transmitted.header_bytes += 500;
1728 counters.transmitted.padding_bytes += 1000;
1729 counters.transmitted.payload_bytes += 2000;
1730 counters.retransmitted.packets += 2;
1731 counters.retransmitted.header_bytes += 25;
1732 counters.retransmitted.padding_bytes += 100;
1733 counters.retransmitted.payload_bytes += 250;
1734 counters.fec = counters.retransmitted;
1735 rtx_counters.transmitted = counters.transmitted;
1736 // Advance one interval and update counters.
1737 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1738 proxy->DataCountersUpdated(counters, kFirstSsrc);
1739 proxy->DataCountersUpdated(counters, kSecondSsrc);
1740 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1741 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1742 }
Erik Språng22c2b482016-03-01 09:40:42 +01001743
1744 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001745 VideoEncoderConfig config;
1746 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Persson59283e42017-12-12 14:14:42 +01001747 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
Erik Språng22c2b482016-03-01 09:40:42 +01001748
asapersson93e1e232017-02-06 05:18:35 -08001749 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001750 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001751 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1752 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1753 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1754 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1755 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001756 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001757 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1758 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001759 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001760 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1761 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1762 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1763 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1764 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01001765 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07001766 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001767 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001768 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01001769
asapersson93e1e232017-02-06 05:18:35 -08001770 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01001771 // Double counter values, this should result in the same counts as before but
1772 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08001773 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1774 counters.transmitted.packets += 20;
1775 counters.transmitted.header_bytes += 500;
1776 counters.transmitted.padding_bytes += 1000;
1777 counters.transmitted.payload_bytes += 2000;
1778 counters.retransmitted.packets += 2;
1779 counters.retransmitted.header_bytes += 25;
1780 counters.retransmitted.padding_bytes += 100;
1781 counters.retransmitted.payload_bytes += 250;
1782 counters.fec = counters.retransmitted;
1783 rtx_counters.transmitted = counters.transmitted;
1784 // Advance one interval and update counters.
1785 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1786 proxy->DataCountersUpdated(counters, kFirstSsrc);
1787 proxy->DataCountersUpdated(counters, kSecondSsrc);
1788 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1789 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1790 }
Erik Språng22c2b482016-03-01 09:40:42 +01001791
asapersson93e1e232017-02-06 05:18:35 -08001792 // Reset stats proxy also causes histograms to be reported.
1793 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01001794
asapersson93e1e232017-02-06 05:18:35 -08001795 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001796 EXPECT_EQ(1,
1797 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001798 EXPECT_EQ(
1799 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
1800 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1801 EXPECT_EQ(
1802 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
1803 EXPECT_EQ(1, metrics::NumEvents(
1804 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
1805 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001806 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001807 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001808 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001809 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
1810 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001811 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001812 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001813 EXPECT_EQ(1, metrics::NumEvents(
1814 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
1815 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1816 EXPECT_EQ(
1817 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
1818 EXPECT_EQ(1, metrics::NumEvents(
1819 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
1820 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07001821 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001822 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001823 EXPECT_EQ(1,
1824 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001825 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
1826}
Erik Språng22c2b482016-03-01 09:40:42 +01001827
asapersson93e1e232017-02-06 05:18:35 -08001828TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
1829 StreamDataCountersCallback* proxy =
1830 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1831 StreamDataCounters counters;
1832 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01001833
asapersson93e1e232017-02-06 05:18:35 -08001834 const int kMinRequiredPeriodSamples = 8;
1835 const int kPeriodIntervalMs = 2000;
1836 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1837 counters.transmitted.packets += 20;
1838 counters.transmitted.header_bytes += 500;
1839 counters.transmitted.payload_bytes += 2000;
1840 counters.fec = counters.retransmitted;
1841 // Advance one interval and update counters.
1842 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1843 proxy->DataCountersUpdated(counters, kFirstSsrc);
1844 }
1845
1846 // RTX enabled. No data sent over RTX.
1847 statistics_proxy_.reset();
1848 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1849 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
1850}
1851
1852TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
1853 VideoSendStream::Config config(nullptr);
1854 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
1855 statistics_proxy_.reset(new SendStatisticsProxy(
1856 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1857
1858 StreamDataCountersCallback* proxy =
1859 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1860 StreamDataCounters counters;
1861
1862 const int kMinRequiredPeriodSamples = 8;
1863 const int kPeriodIntervalMs = 2000;
1864 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1865 counters.transmitted.packets += 20;
1866 counters.transmitted.header_bytes += 500;
1867 counters.transmitted.payload_bytes += 2000;
1868 counters.fec = counters.retransmitted;
1869 // Advance one interval and update counters.
1870 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1871 proxy->DataCountersUpdated(counters, kFirstSsrc);
1872 }
1873
1874 // RTX not enabled.
1875 statistics_proxy_.reset();
1876 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1877}
1878
1879TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
1880 StreamDataCountersCallback* proxy =
1881 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1882 StreamDataCounters counters;
1883 StreamDataCounters rtx_counters;
1884
1885 const int kMinRequiredPeriodSamples = 8;
1886 const int kPeriodIntervalMs = 2000;
1887 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1888 counters.transmitted.packets += 20;
1889 counters.transmitted.header_bytes += 500;
1890 counters.transmitted.payload_bytes += 2000;
1891 // Advance one interval and update counters.
1892 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1893 proxy->DataCountersUpdated(counters, kFirstSsrc);
1894 }
1895
1896 // FEC enabled. No FEC data sent.
1897 statistics_proxy_.reset();
1898 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1899 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
1900}
1901
1902TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
1903 VideoSendStream::Config config(nullptr);
1904 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
1905 statistics_proxy_.reset(new SendStatisticsProxy(
1906 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1907
1908 StreamDataCountersCallback* proxy =
1909 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1910 StreamDataCounters counters;
1911
1912 const int kMinRequiredPeriodSamples = 8;
1913 const int kPeriodIntervalMs = 2000;
1914 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1915 counters.transmitted.packets += 20;
1916 counters.transmitted.header_bytes += 500;
1917 counters.transmitted.payload_bytes += 2000;
1918 counters.fec = counters.retransmitted;
1919 // Advance one interval and update counters.
1920 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1921 proxy->DataCountersUpdated(counters, kFirstSsrc);
1922 }
1923
1924 // FEC not enabled.
1925 statistics_proxy_.reset();
1926 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001927}
1928
asapersson8d75ac72017-09-15 06:41:15 -07001929TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
1930 const char* kName = "encoderName";
1931 EncodedImage encoded_image;
1932 CodecSpecificInfo codec_info;
1933 codec_info.codec_name = kName;
1934 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1935 EXPECT_STREQ(
1936 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str());
1937}
1938
1939class ForcedFallbackTest : public SendStatisticsProxyTest {
1940 public:
1941 explicit ForcedFallbackTest(const std::string& field_trials)
1942 : SendStatisticsProxyTest(field_trials) {
1943 codec_info_.codecType = kVideoCodecVP8;
1944 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
1945 codec_info_.codecSpecific.VP8.temporalIdx = 0;
1946 codec_info_.codec_name = "fake_codec";
Åsa Persson45bbc8a2017-11-13 10:16:47 +01001947 encoded_image_._encodedWidth = kWidth;
1948 encoded_image_._encodedHeight = kHeight;
asapersson8d75ac72017-09-15 06:41:15 -07001949 }
1950
1951 ~ForcedFallbackTest() override {}
1952
1953 protected:
1954 void InsertEncodedFrames(int num_frames, int interval_ms) {
1955 // First frame is not updating stats, insert initial frame.
1956 if (statistics_proxy_->GetStats().frames_encoded == 0) {
1957 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1958 }
1959 for (int i = 0; i < num_frames; ++i) {
1960 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1961 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
1962 }
1963 // Add frame to include last time interval.
1964 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1965 }
1966
1967 EncodedImage encoded_image_;
1968 CodecSpecificInfo codec_info_;
1969 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
1970 const int kFrameIntervalMs = 1000;
1971 const int kMinFrames = 20; // Min run time 20 sec.
1972};
1973
1974class ForcedFallbackDisabled : public ForcedFallbackTest {
1975 public:
1976 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01001977 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
1978 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07001979};
1980
1981class ForcedFallbackEnabled : public ForcedFallbackTest {
1982 public:
1983 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01001984 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
1985 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07001986};
1987
1988TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
1989 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
1990 statistics_proxy_.reset();
1991 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1992 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1993}
1994
1995TEST_F(ForcedFallbackEnabled, StatsUpdated) {
1996 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01001997 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07001998 statistics_proxy_.reset();
1999 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2000 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2001 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2002 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2003}
2004
2005TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2006 codec_info_.codecType = kVideoCodecVP9;
2007 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2008 statistics_proxy_.reset();
2009 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2010 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2011}
2012
2013TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2014 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2015 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2016 statistics_proxy_.reset();
2017 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2018 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2019}
2020
2021TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
2022 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
2023 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2024 statistics_proxy_.reset();
2025 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2026 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2027}
2028
2029TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2030 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2031 statistics_proxy_.reset();
2032 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2033 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2034}
2035
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002036TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2037 InsertEncodedFrames(1, kFrameIntervalMs);
2038 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2039}
2040
2041TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2042 InsertEncodedFrames(1, kFrameIntervalMs);
2043 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2044}
2045
2046TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
2047 codec_info_.codec_name = "libvpx";
2048 InsertEncodedFrames(1, kFrameIntervalMs);
2049 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2050}
2051
2052TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2053 encoded_image_._encodedWidth = kWidth + 1;
2054 InsertEncodedFrames(1, kFrameIntervalMs);
2055 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2056}
2057
2058TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
2059 codec_info_.codec_name = "libvpx";
2060 InsertEncodedFrames(1, kFrameIntervalMs);
2061 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2062}
2063
2064TEST_F(ForcedFallbackDisabled,
2065 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2066 encoded_image_._encodedWidth = kWidth + 1;
2067 statistics_proxy_->OnMinPixelLimitReached();
2068 InsertEncodedFrames(1, kFrameIntervalMs);
2069 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2070}
2071
asapersson8d75ac72017-09-15 06:41:15 -07002072TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2073 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002074 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002075 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002076 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002077 codec_info_.codec_name = "libvpx";
2078 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002079 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002080
2081 statistics_proxy_.reset();
2082 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2083 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2084 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2085 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2086}
2087
2088TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2089 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2090 const int kMaxFrameDiffMs = 2000;
2091
2092 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2093 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002094 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002095 codec_info_.codec_name = "libvpx";
2096 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002097 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002098 codec_info_.codec_name = "notlibvpx";
2099 InsertEncodedFrames(20, 1000);
2100 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2101 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002102 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002103 codec_info_.codec_name = "notlibvpx2";
2104 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002105 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002106 codec_info_.codec_name = "libvpx";
2107 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002108 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002109
2110 statistics_proxy_.reset();
2111 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2112 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2113 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2114 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2115}
2116
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002117TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2118 encoded_image_._encodedWidth = kWidth + 1;
asapersson8d75ac72017-09-15 06:41:15 -07002119 codec_info_.codec_name = "libvpx";
2120 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2121
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002122 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002123 statistics_proxy_.reset();
2124 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2125 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2126}
2127
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002128TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2129 encoded_image_._encodedWidth = kWidth;
asapersson8d75ac72017-09-15 06:41:15 -07002130 codec_info_.codec_name = "libvpx";
2131 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2132
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002133 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002134 statistics_proxy_.reset();
2135 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2136 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2137}
2138
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002139} // namespace webrtc