blob: 1d2edc6a782ae432a625c0c33a28a1388a4c1c09 [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 Perssonaa329e72017-12-15 15:54:44 +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 Perssonaa329e72017-12-15 15:54:44 +010036const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080037const CodecSpecificInfo kDefaultCodecInfo = []() {
38 CodecSpecificInfo codec_info;
39 codec_info.codecType = kVideoCodecVP8;
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 Perssonaa329e72017-12-15 15:54:44 +0100329 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
Pera48ddb72016-09-29 11:48:50 +0200330 stats = statistics_proxy_->GetStats();
Åsa Perssonaa329e72017-12-15 15:54:44 +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;
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100347 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700348 encoded_image.qp_ = 3;
349 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100350 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700351 encoded_image.qp_ = 127;
352 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100353 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700354}
355
356TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
357 EncodedImage encoded_image;
358 CodecSpecificInfo codec_info;
359 encoded_image.qp_ = -1;
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100360 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700361 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100362 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700363}
364
asapersson09f05612017-05-15 23:40:18 -0700365TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700366 VideoStreamEncoder::AdaptCounts cpu_counts;
367 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700368 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700369 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700370 cpu_counts.fps = 1;
371 cpu_counts.resolution = 0;
372 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
373 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700374 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700375 cpu_counts.fps = 0;
376 cpu_counts.resolution = 1;
377 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
378 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700379 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700380 cpu_counts.fps = 1;
381 cpu_counts.resolution = -1;
382 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
383 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700384 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700385 cpu_counts.fps = -1;
386 cpu_counts.resolution = -1;
387 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
388 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
389 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
390}
391
392TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700393 VideoStreamEncoder::AdaptCounts cpu_counts;
394 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700395 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
396 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
397 quality_counts.fps = 1;
398 quality_counts.resolution = 0;
399 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
400 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
401 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
402 quality_counts.fps = 0;
403 quality_counts.resolution = 1;
404 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
405 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
406 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
407 quality_counts.fps = 1;
408 quality_counts.resolution = -1;
409 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
410 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
411 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
412 quality_counts.fps = -1;
413 quality_counts.resolution = -1;
414 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
415 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
416 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
417}
418
419TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700420 VideoStreamEncoder::AdaptCounts cpu_counts;
421 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700422 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
423
asapersson09f05612017-05-15 23:40:18 -0700424 cpu_counts.resolution = 1;
425 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
426 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700427 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
428 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
429
asapersson09f05612017-05-15 23:40:18 -0700430 cpu_counts.resolution = 2;
431 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
432 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
433 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700434 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700435 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700436}
437
asapersson09f05612017-05-15 23:40:18 -0700438TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700439 VideoStreamEncoder::AdaptCounts cpu_counts;
440 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700441 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
442
asapersson09f05612017-05-15 23:40:18 -0700443 quality_counts.fps = 1;
444 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
445 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
446 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700447 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
448
asapersson09f05612017-05-15 23:40:18 -0700449 quality_counts.fps = 0;
450 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
451 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700452 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700453 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
454 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700455}
456
asapersson09f05612017-05-15 23:40:18 -0700457TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700458 // First RTP packet sent.
459 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700460 // Min runtime has passed.
461 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
462 statistics_proxy_.reset();
463 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
464 EXPECT_EQ(0,
465 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
466}
467
468TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700469 // First RTP packet sent.
470 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700471 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700472 VideoStreamEncoder::AdaptCounts cpu_counts;
473 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700474 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700475 // Min runtime has not passed.
476 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
477 statistics_proxy_.reset();
478 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
479 EXPECT_EQ(0,
480 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
481}
482
asapersson09f05612017-05-15 23:40:18 -0700483TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700484 // First RTP packet sent.
485 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700486 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700487 VideoStreamEncoder::AdaptCounts cpu_counts;
488 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700489 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700490 // Min runtime has passed.
491 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
492 statistics_proxy_.reset();
493 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
494 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700495 EXPECT_EQ(1,
496 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
497 EXPECT_EQ(
498 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
499}
500
501TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700502 // First RTP packet sent.
503 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700504 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700505 VideoStreamEncoder::AdaptCounts cpu_counts;
506 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700507 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700508 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson09f05612017-05-15 23:40:18 -0700509 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700510 fake_clock_.AdvanceTimeMilliseconds(10000);
511 statistics_proxy_.reset();
512 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
513 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
514}
515
516TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700517 // First RTP packet sent.
518 UpdateDataCounters(kFirstSsrc);
519
asapersson09f05612017-05-15 23:40:18 -0700520 // Disable quality adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700521 VideoStreamEncoder::AdaptCounts cpu_counts;
522 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700523 quality_counts.fps = -1;
524 quality_counts.resolution = -1;
525 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700526 fake_clock_.AdvanceTimeMilliseconds(10000);
527
asapersson09f05612017-05-15 23:40:18 -0700528 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700529 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700530 quality_counts.fps = 0;
531 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700532 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700533 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700534 fake_clock_.AdvanceTimeMilliseconds(9000);
asapersson09f05612017-05-15 23:40:18 -0700535 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700536 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700537 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700538
asapersson09f05612017-05-15 23:40:18 -0700539 // Disable quality adaptation.
540 quality_counts.fps = -1;
541 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700542 fake_clock_.AdvanceTimeMilliseconds(30000);
543
asapersson09f05612017-05-15 23:40:18 -0700544 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700545 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700546 quality_counts.resolution = 0;
547 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
548 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700549 fake_clock_.AdvanceTimeMilliseconds(10000);
550
asapersson09f05612017-05-15 23:40:18 -0700551 // Disable quality adaptation.
552 quality_counts.resolution = -1;
553 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700554 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700555 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700556 fake_clock_.AdvanceTimeMilliseconds(20000);
557
asapersson0944a802017-04-07 00:57:58 -0700558 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700559 statistics_proxy_.reset();
560 EXPECT_EQ(1,
561 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
562 EXPECT_EQ(
563 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
564}
565
asapersson0944a802017-04-07 00:57:58 -0700566TEST_F(SendStatisticsProxyTest,
567 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
568 // First RTP packet sent.
569 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700570
asapersson0944a802017-04-07 00:57:58 -0700571 // Suspend and resume video.
572 statistics_proxy_->OnSuspendChange(true);
573 fake_clock_.AdvanceTimeMilliseconds(5000);
574 statistics_proxy_->OnSuspendChange(false);
575
576 // Min runtime has passed but scaling not enabled.
577 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
578 statistics_proxy_.reset();
579 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
580 EXPECT_EQ(0,
581 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
582}
583
584TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
585 // First RTP packet sent.
586 UpdateDataCounters(kFirstSsrc);
587
asapersson09f05612017-05-15 23:40:18 -0700588 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700589 VideoStreamEncoder::AdaptCounts cpu_counts;
590 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700591 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700592 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700593 fake_clock_.AdvanceTimeMilliseconds(20000);
asapersson09f05612017-05-15 23:40:18 -0700594 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
595 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700596
597 // Suspend and resume video.
598 statistics_proxy_->OnSuspendChange(true);
599 fake_clock_.AdvanceTimeMilliseconds(30000);
600 statistics_proxy_->OnSuspendChange(false);
601
602 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700603 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700604 fake_clock_.AdvanceTimeMilliseconds(10000);
605
606 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
607 statistics_proxy_.reset();
608 EXPECT_EQ(1,
609 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
610 EXPECT_EQ(
611 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
612}
613
614TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
615 // First RTP packet sent.
616 UpdateDataCounters(kFirstSsrc);
617
618 // Video not suspended.
619 statistics_proxy_->OnSuspendChange(false);
620 fake_clock_.AdvanceTimeMilliseconds(30000);
621
asapersson09f05612017-05-15 23:40:18 -0700622 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700623 VideoStreamEncoder::AdaptCounts cpu_counts;
624 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700625 // Adapt changes: 1, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700626 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700627 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700628 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700629
630 // Video not suspended, stats time already started.
631 statistics_proxy_->OnSuspendChange(false);
632 fake_clock_.AdvanceTimeMilliseconds(10000);
633
asapersson09f05612017-05-15 23:40:18 -0700634 // Disable adaptation.
635 cpu_counts.fps = -1;
636 cpu_counts.resolution = -1;
637 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700638 fake_clock_.AdvanceTimeMilliseconds(30000);
639
640 // Suspend and resume video, stats time not started when scaling not enabled.
641 statistics_proxy_->OnSuspendChange(true);
642 fake_clock_.AdvanceTimeMilliseconds(30000);
643 statistics_proxy_->OnSuspendChange(false);
644 fake_clock_.AdvanceTimeMilliseconds(30000);
645
asapersson09f05612017-05-15 23:40:18 -0700646 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700647 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700648 cpu_counts.fps = 0;
649 cpu_counts.resolution = 0;
650 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700651 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700652 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700653
654 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
655 statistics_proxy_.reset();
656 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
657 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
658}
659
660TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
661 // First RTP packet sent.
662 UpdateDataCounters(kFirstSsrc);
663
664 // Video suspended.
665 statistics_proxy_->OnSuspendChange(true);
666
asapersson09f05612017-05-15 23:40:18 -0700667 // Enable adaptation, stats time not started when suspended.
mflodmancc3d4422017-08-03 08:27:51 -0700668 VideoStreamEncoder::AdaptCounts cpu_counts;
669 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700670 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700671 fake_clock_.AdvanceTimeMilliseconds(10000);
672
673 // Resume video, stats time started.
674 // Adapt changes: 1, elapsed time: 10 sec.
675 statistics_proxy_->OnSuspendChange(false);
676 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700677 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700678
679 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
680 statistics_proxy_.reset();
681 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
682 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
683}
684
685TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700686 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700687 // Elapsed time before first packet is sent should be excluded.
mflodmancc3d4422017-08-03 08:27:51 -0700688 VideoStreamEncoder::AdaptCounts cpu_counts;
689 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700690 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700691 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700692 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700693
asapersson0944a802017-04-07 00:57:58 -0700694 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700695 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700696 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700697 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700698
asapersson0944a802017-04-07 00:57:58 -0700699 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700700 statistics_proxy_.reset();
701 EXPECT_EQ(1,
702 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
703 EXPECT_EQ(
704 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
705}
706
707TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700708 // Enable and disable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700709 VideoStreamEncoder::AdaptCounts cpu_counts;
710 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700711 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700712 fake_clock_.AdvanceTimeMilliseconds(60000);
asapersson09f05612017-05-15 23:40:18 -0700713 cpu_counts.fps = -1;
714 cpu_counts.resolution = -1;
715 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700716
717 // Send first packet, scaling disabled.
718 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700719 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700720 fake_clock_.AdvanceTimeMilliseconds(60000);
721
asapersson09f05612017-05-15 23:40:18 -0700722 // Enable adaptation.
723 cpu_counts.resolution = 0;
724 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700725 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700726 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700727
asapersson0944a802017-04-07 00:57:58 -0700728 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700729 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700730 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700731
asapersson0944a802017-04-07 00:57:58 -0700732 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700733 statistics_proxy_.reset();
734 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
735 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
736}
737
738TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700739 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700740 UpdateDataCounters(kFirstSsrc);
mflodmancc3d4422017-08-03 08:27:51 -0700741 VideoStreamEncoder::AdaptCounts cpu_counts;
742 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700743 quality_counts.fps = -1;
744 quality_counts.resolution = -1;
745 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700746
asapersson0944a802017-04-07 00:57:58 -0700747 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
asapersson09f05612017-05-15 23:40:18 -0700748 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700749 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700750 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700751 fake_clock_.AdvanceTimeMilliseconds(9000);
752
753 // Switch content type, real-time stats should be updated.
754 VideoEncoderConfig config;
755 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +0100756 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson6eca98b2017-04-04 23:40:50 -0700757 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
758 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
759 EXPECT_EQ(0,
760 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
761
asapersson0944a802017-04-07 00:57:58 -0700762 // First RTP packet sent, scaling enabled.
763 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700764 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700765
asapersson0944a802017-04-07 00:57:58 -0700766 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
asapersson09f05612017-05-15 23:40:18 -0700767 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
768 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
769 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
770 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700771 fake_clock_.AdvanceTimeMilliseconds(120000);
772
773 statistics_proxy_.reset();
774 EXPECT_EQ(1, metrics::NumSamples(
775 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
776 EXPECT_EQ(1, metrics::NumEvents(
777 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
778 EXPECT_EQ(0, metrics::NumSamples(
779 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
780}
781
asapersson59bac1a2016-01-07 23:36:00 -0800782TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -0700783 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -0800784 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
785
Pera48ddb72016-09-29 11:48:50 +0200786 // No switch, stats should not be updated.
787 VideoEncoderConfig config;
788 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Perssonaa329e72017-12-15 15:54:44 +0100789 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson01d70a32016-05-20 06:29:46 -0700790 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800791
792 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +0200793 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +0100794 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson01d70a32016-05-20 06:29:46 -0700795 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800796}
797
asapersson320e45a2016-11-29 01:40:35 -0800798TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
799 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
800 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -0700801
asapersson320e45a2016-11-29 01:40:35 -0800802 statistics_proxy_.reset();
803 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
804 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
805 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
806 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
807}
808
809TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +0200810 const int64_t kMaxEncodedFrameWindowMs = 800;
811 const int kFps = 20;
812 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
813 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
814 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -0800815 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +0200816
817 // Not enough samples, stats should not be updated.
818 for (int i = 0; i < kMinSamples - 1; ++i) {
819 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
820 ++encoded_image._timeStamp;
asapersson320e45a2016-11-29 01:40:35 -0800821 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
822 }
Åsa Persson0122e842017-10-16 12:19:23 +0200823 SetUp(); // Reset stats proxy also causes histograms to be reported.
824 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
825 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
826
827 // Enough samples, max resolution per frame should be reported.
828 encoded_image._timeStamp = 0xfffffff0; // Will wrap.
829 for (int i = 0; i < kMinSamples; ++i) {
830 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
831 ++encoded_image._timeStamp;
832 encoded_image._encodedWidth = kWidth;
833 encoded_image._encodedHeight = kHeight;
834 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
835 encoded_image._encodedWidth = kWidth / 2;
836 encoded_image._encodedHeight = kHeight / 2;
837 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
838 }
839
asapersson320e45a2016-11-29 01:40:35 -0800840 statistics_proxy_.reset();
841 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
842 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
843 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
844 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
845}
846
847TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
848 const int kFps = 20;
849 const int kMinPeriodicSamples = 6;
850 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
851 for (int i = 0; i <= frames; ++i) {
852 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
853 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
854 }
855 statistics_proxy_.reset();
856 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
857 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
858}
859
860TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
861 EncodedImage encoded_image;
862 const int kFps = 20;
863 const int kMinPeriodicSamples = 6;
864 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +0200865 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800866 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +0200867 ++encoded_image._timeStamp;
868 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
869 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -0800870 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
871 }
872 statistics_proxy_.reset();
873 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
874 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
875}
876
877TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
878 const int kFps = 20;
879 const int kSuspendTimeMs = 10000;
880 const int kMinPeriodicSamples = 6;
881 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
882 for (int i = 0; i < frames; ++i) {
883 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
884 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
885 }
886 // Suspend.
887 statistics_proxy_->OnSuspendChange(true);
888 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
889
890 for (int i = 0; i < frames; ++i) {
891 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
892 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
893 }
894 // Suspended time interval should not affect the framerate.
895 statistics_proxy_.reset();
896 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
897 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
898}
899
900TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
901 EncodedImage encoded_image;
902 const int kFps = 20;
903 const int kSuspendTimeMs = 10000;
904 const int kMinPeriodicSamples = 6;
905 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +0200906 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800907 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
908 encoded_image._timeStamp = i + 1;
909 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
910 }
911 // Suspend.
912 statistics_proxy_->OnSuspendChange(true);
913 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
914
Åsa Persson0122e842017-10-16 12:19:23 +0200915 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800916 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
917 encoded_image._timeStamp = i + 1;
918 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
919 }
920 // Suspended time interval should not affect the framerate.
921 statistics_proxy_.reset();
922 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
923 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
924}
925
asaperssonf4e44af2017-04-19 02:01:06 -0700926TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -0700927 VideoStreamEncoder::AdaptCounts cpu_counts;
928 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700929 cpu_counts.resolution = -1;
930 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -0700931
932 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
933 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
934
935 statistics_proxy_.reset();
936 EXPECT_EQ(0,
937 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
938}
939
940TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
mflodmancc3d4422017-08-03 08:27:51 -0700941 VideoStreamEncoder::AdaptCounts cpu_counts;
942 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700943 cpu_counts.resolution = 0;
944 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -0700945
perkj803d97f2016-11-01 11:45:46 -0700946 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
947 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
948
asapersson09f05612017-05-15 23:40:18 -0700949 cpu_counts.resolution = 1;
950 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -0700951
952 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
953 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
954
955 statistics_proxy_.reset();
956 EXPECT_EQ(1,
957 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
958 EXPECT_EQ(
959 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
960}
961
asapersson4374a092016-07-27 00:39:09 -0700962TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
963 const int64_t kTimeSec = 3;
964 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
965 statistics_proxy_.reset();
966 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
967 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
968 kTimeSec));
969}
970
971TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
972 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
973 statistics_proxy_.reset();
974 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
975}
976
asapersson66d4b372016-12-19 06:50:53 -0800977TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
978 // First RTP packet sent.
979 UpdateDataCounters(kFirstSsrc);
980
981 // Min runtime has passed.
982 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
983 statistics_proxy_.reset();
984 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
985 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
986}
987
988TEST_F(SendStatisticsProxyTest,
989 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
990 // First RTP packet sent.
991 UpdateDataCounters(kFirstSsrc);
992
993 // Min runtime has not passed.
994 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
995 statistics_proxy_.reset();
996 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
997 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
998}
999
1000TEST_F(SendStatisticsProxyTest,
1001 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1002 // First RTP packet not sent.
1003 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1004 statistics_proxy_.reset();
1005 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1006}
1007
1008TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1009 // First RTP packet sent and min runtime passed.
1010 UpdateDataCounters(kFirstSsrc);
1011
1012 // No change. Video: 10000 ms, paused: 0 ms (0%).
1013 statistics_proxy_->OnSetEncoderTargetRate(50000);
1014 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1015 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1016
1017 statistics_proxy_.reset();
1018 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1019 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1020 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1021 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1022}
1023
1024TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1025 // First RTP packet sent and min runtime passed.
1026 UpdateDataCounters(kFirstSsrc);
1027
1028 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1029 statistics_proxy_->OnSetEncoderTargetRate(50000);
1030 fake_clock_.AdvanceTimeMilliseconds(7000);
1031 statistics_proxy_->OnSetEncoderTargetRate(0);
1032 fake_clock_.AdvanceTimeMilliseconds(3000);
1033 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1034
1035 statistics_proxy_.reset();
1036 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1037 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1038 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1039 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1040}
1041
1042TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1043 // First RTP packet sent.
1044 UpdateDataCounters(kFirstSsrc);
1045
1046 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1047 statistics_proxy_->OnSetEncoderTargetRate(0);
1048 fake_clock_.AdvanceTimeMilliseconds(1000);
1049 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1050 fake_clock_.AdvanceTimeMilliseconds(7000);
1051 statistics_proxy_->OnSetEncoderTargetRate(60000);
1052 fake_clock_.AdvanceTimeMilliseconds(3000);
1053 statistics_proxy_->OnSetEncoderTargetRate(0);
1054 fake_clock_.AdvanceTimeMilliseconds(250);
1055 statistics_proxy_->OnSetEncoderTargetRate(0);
1056 fake_clock_.AdvanceTimeMilliseconds(750);
1057 statistics_proxy_->OnSetEncoderTargetRate(60000);
1058 fake_clock_.AdvanceTimeMilliseconds(5000);
1059 statistics_proxy_->OnSetEncoderTargetRate(50000);
1060 fake_clock_.AdvanceTimeMilliseconds(4000);
1061 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1062
1063 statistics_proxy_.reset();
1064 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1065 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1066 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1067 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1068}
1069
1070TEST_F(SendStatisticsProxyTest,
1071 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1072 // First RTP packet sent.
1073 UpdateDataCounters(kFirstSsrc);
1074 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1075
1076 // Min runtime has not passed.
1077 statistics_proxy_->OnSetEncoderTargetRate(50000);
1078 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1079 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1080
1081 statistics_proxy_.reset();
1082 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1083}
1084
asapersson118ef002016-03-31 00:00:19 -07001085TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001086 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001087 CodecSpecificInfo codec_info;
1088 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001089
perkj803d97f2016-11-01 11:45:46 -07001090 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001091 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001092 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001093 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1094 codec_info.codecSpecific.VP8.simulcastIdx = 1;
asapersson118ef002016-03-31 00:00:19 -07001095 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001096 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001097 }
1098 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001099 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1100 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1101 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1102 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001103}
1104
1105TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1106 VideoSendStream::Config config(nullptr);
1107 config.rtp.ssrcs.push_back(kFirstSsrc);
1108 statistics_proxy_.reset(new SendStatisticsProxy(
1109 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1110
asapersson118ef002016-03-31 00:00:19 -07001111 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001112 CodecSpecificInfo codec_info;
1113 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001114
perkj803d97f2016-11-01 11:45:46 -07001115 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001116 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001117 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001118 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001119 }
1120 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001121 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1122 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001123}
1124
asapersson5265fed2016-04-18 02:58:47 -07001125TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001126 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001127 CodecSpecificInfo codec_info;
1128 codec_info.codecType = kVideoCodecVP9;
1129 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001130
perkj803d97f2016-11-01 11:45:46 -07001131 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001132 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001133 codec_info.codecSpecific.VP9.spatial_idx = 0;
1134 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001135 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001136 codec_info.codecSpecific.VP9.spatial_idx = 1;
1137 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001138 }
1139 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001140 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1141 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1142 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1143 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001144}
1145
1146TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1147 VideoSendStream::Config config(nullptr);
1148 config.rtp.ssrcs.push_back(kFirstSsrc);
1149 statistics_proxy_.reset(new SendStatisticsProxy(
1150 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1151
asapersson5265fed2016-04-18 02:58:47 -07001152 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001153 CodecSpecificInfo codec_info;
1154 codec_info.codecType = kVideoCodecVP9;
1155 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001156
perkj803d97f2016-11-01 11:45:46 -07001157 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001158 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001159 codec_info.codecSpecific.VP9.spatial_idx = 0;
1160 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001161 }
1162 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001163 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1164 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001165}
1166
asapersson827cab32016-11-02 09:08:47 -07001167TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1168 EncodedImage encoded_image;
1169 CodecSpecificInfo codec_info;
1170 codec_info.codecType = kVideoCodecH264;
1171
1172 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1173 encoded_image.qp_ = kQpIdx0;
1174 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1175 }
1176 statistics_proxy_.reset();
1177 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264"));
1178 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264", kQpIdx0));
1179}
1180
asapersson4ee70462016-10-31 04:05:12 -07001181TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001182 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1183 // Configure one stream.
1184 VideoEncoderConfig config;
1185 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1186 VideoStream stream1;
1187 stream1.width = kWidth;
1188 stream1.height = kHeight;
1189 statistics_proxy_->OnEncoderReconfigured(config, {stream1}, kPreferredBps);
1190
1191 const int64_t kMaxEncodedFrameWindowMs = 800;
1192 const int kFps = 20;
1193 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1194 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1195 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1196
1197 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001198 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001199 encoded_image._encodedWidth = kWidth;
1200 encoded_image._encodedHeight = kHeight;
1201 for (int i = 0; i < kMinSamples; ++i) {
1202 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1203 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001204 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001205 }
asapersson4ee70462016-10-31 04:05:12 -07001206
1207 // Histograms are updated when the statistics_proxy_ is deleted.
1208 statistics_proxy_.reset();
1209 EXPECT_EQ(0, metrics::NumSamples(
1210 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1211 EXPECT_EQ(0, metrics::NumSamples(
1212 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1213}
1214
1215TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001216 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1217 // Configure two streams.
1218 VideoEncoderConfig config;
1219 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1220 VideoStream stream1;
1221 stream1.width = kWidth / 2;
1222 stream1.height = kHeight / 2;
1223 VideoStream stream2;
1224 stream2.width = kWidth;
1225 stream2.height = kHeight;
1226 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1227 kPreferredBps);
1228
1229 const int64_t kMaxEncodedFrameWindowMs = 800;
1230 const int kFps = 20;
1231 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1232 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1233 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1234
1235 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001236 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001237 for (int i = 0; i < kMinSamples; ++i) {
1238 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1239 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1240 encoded_image._encodedWidth = kWidth;
1241 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001242 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001243 encoded_image._encodedWidth = kWidth / 2;
1244 encoded_image._encodedHeight = kHeight / 2;
1245 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1246 }
asapersson4ee70462016-10-31 04:05:12 -07001247
1248 // Histograms are updated when the statistics_proxy_ is deleted.
1249 statistics_proxy_.reset();
1250 EXPECT_EQ(1, metrics::NumSamples(
1251 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1252 EXPECT_EQ(1, metrics::NumEvents(
1253 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1254 // No resolution disabled.
1255 EXPECT_EQ(0, metrics::NumSamples(
1256 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1257}
1258
1259TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001260 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1261 // Configure two streams.
1262 VideoEncoderConfig config;
1263 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1264 VideoStream stream1;
1265 stream1.width = kWidth / 2;
1266 stream1.height = kHeight / 2;
1267 VideoStream stream2;
1268 stream2.width = kWidth;
1269 stream2.height = kHeight;
1270 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1271 kPreferredBps);
1272
1273 const int64_t kMaxEncodedFrameWindowMs = 800;
1274 const int kFps = 20;
1275 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1276 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1277 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1278
1279 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001280 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001281 encoded_image._encodedWidth = kWidth / 2;
1282 encoded_image._encodedHeight = kHeight / 2;
1283 for (int i = 0; i < kMinSamples; ++i) {
1284 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1285 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001286 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001287 }
asapersson4ee70462016-10-31 04:05:12 -07001288
1289 // Histograms are updated when the statistics_proxy_ is deleted.
1290 statistics_proxy_.reset();
1291 EXPECT_EQ(1, metrics::NumSamples(
1292 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1293 EXPECT_EQ(1, metrics::NumEvents(
1294 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001295 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001296 EXPECT_EQ(1, metrics::NumSamples(
1297 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001298 EXPECT_EQ(1, metrics::NumEvents(
1299 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001300}
1301
1302TEST_F(SendStatisticsProxyTest,
1303 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -07001304 VideoStreamEncoder::AdaptCounts cpu_counts;
1305 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001306 quality_counts.resolution = -1;
1307 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001308 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001309 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001310 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001311
1312 // Histograms are updated when the statistics_proxy_ is deleted.
1313 statistics_proxy_.reset();
1314 EXPECT_EQ(
1315 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1316 EXPECT_EQ(0, metrics::NumSamples(
1317 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1318}
1319
1320TEST_F(SendStatisticsProxyTest,
1321 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
mflodmancc3d4422017-08-03 08:27:51 -07001322 VideoStreamEncoder::AdaptCounts cpu_counts;
1323 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001324 quality_counts.resolution = 0;
1325 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001326 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001327 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001328 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001329
1330 // Histograms are updated when the statistics_proxy_ is deleted.
1331 statistics_proxy_.reset();
1332 EXPECT_EQ(
1333 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1334 EXPECT_EQ(1, metrics::NumEvents(
1335 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1336 // No resolution downscale.
1337 EXPECT_EQ(0, metrics::NumSamples(
1338 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1339}
1340
1341TEST_F(SendStatisticsProxyTest,
1342 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1343 const int kDownscales = 2;
mflodmancc3d4422017-08-03 08:27:51 -07001344 VideoStreamEncoder::AdaptCounts cpu_counts;
1345 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001346 quality_counts.resolution = kDownscales;
1347 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001348 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001349 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001350 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001351 // Histograms are updated when the statistics_proxy_ is deleted.
1352 statistics_proxy_.reset();
1353 EXPECT_EQ(
1354 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1355 EXPECT_EQ(1, metrics::NumEvents(
1356 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1357 // Resolution downscales.
1358 EXPECT_EQ(1, metrics::NumSamples(
1359 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1360 EXPECT_EQ(
1361 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1362 kDownscales));
1363}
1364
1365TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1366 // Initially false.
1367 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001368
Åsa Perssonaa329e72017-12-15 15:54:44 +01001369 // Configure two streams.
1370 VideoEncoderConfig config;
1371 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1372 VideoStream stream1;
1373 stream1.width = kWidth / 2;
1374 stream1.height = kHeight / 2;
1375 VideoStream stream2;
1376 stream2.width = kWidth;
1377 stream2.height = kHeight;
1378 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1379 kPreferredBps);
1380
1381 const int64_t kMaxEncodedFrameWindowMs = 800;
1382 const int kFps = 20;
1383 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1384 kFps * kMaxEncodedFrameWindowMs / 1000;
1385
1386 // One stream encoded.
1387 EncodedImage encoded_image;
1388 encoded_image._encodedWidth = kWidth / 2;
1389 encoded_image._encodedHeight = kHeight / 2;
1390 for (int i = 0; i < kMinSamples; ++i) {
1391 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1392 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1393 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1394 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1395 }
1396
1397 // First frame removed from EncodedFrameMap, stats updated.
1398 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1399 ++encoded_image._timeStamp;
kthelgason0cd27ba2016-12-19 06:32:16 -08001400 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1401 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1402
Åsa Perssonaa329e72017-12-15 15:54:44 +01001403 // Two streams encoded.
1404 for (int i = 0; i < kMinSamples; ++i) {
1405 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1406 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1407 encoded_image._encodedWidth = kWidth;
1408 encoded_image._encodedHeight = kHeight;
1409 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1410 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1411 encoded_image._encodedWidth = kWidth / 2;
1412 encoded_image._encodedHeight = kHeight / 2;
1413 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1414 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1415 }
1416
1417 // First frame with two streams removed, expect no resolution limit.
1418 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1419 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001420 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1421 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001422
1423 // Resolution scaled due to quality.
mflodmancc3d4422017-08-03 08:27:51 -07001424 VideoStreamEncoder::AdaptCounts cpu_counts;
1425 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001426 quality_counts.resolution = 1;
1427 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001428 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1429 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1430}
1431
asapersson66d4b372016-12-19 06:50:53 -08001432TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1433 // Initially zero.
1434 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1435
1436 const int kBitrate = 100000;
1437 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1438 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1439
1440 statistics_proxy_->OnSetEncoderTargetRate(0);
1441 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1442}
1443
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001444TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001445 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001446 std::max(
1447 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1448 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1449 config_.rtp.rtx.ssrcs.end())) +
1450 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001451 // From RtcpStatisticsCallback.
1452 RtcpStatistics rtcp_stats;
1453 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001454 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001455
1456 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001457 uint32_t total = 0;
1458 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001459 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001460 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001461
1462 // From FrameCountObserver.
1463 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001464 FrameCounts frame_counts;
1465 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001466 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001467
1468 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1469 EXPECT_TRUE(stats.substreams.empty());
1470}
1471
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001472TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1473 static const int kEncodedWidth = 123;
1474 static const int kEncodedHeight = 81;
1475 EncodedImage encoded_image;
1476 encoded_image._encodedWidth = kEncodedWidth;
1477 encoded_image._encodedHeight = kEncodedHeight;
1478
kjellander02b3d272016-04-20 05:05:54 -07001479 CodecSpecificInfo codec_info;
1480 codec_info.codecType = kVideoCodecVP8;
1481 codec_info.codecSpecific.VP8.simulcastIdx = 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001482
kjellander02b3d272016-04-20 05:05:54 -07001483 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1484 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1485 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001486
1487 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001488 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1489 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1490 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1491 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001492
1493 // Forward almost to timeout, this should not have removed stats.
1494 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1495 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001496 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1497 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001498
1499 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1500 // resolution still times out (no global timeout for all stats).
1501 RtcpStatistics rtcp_statistics;
1502 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1503 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1504
1505 // Report stats for second SSRC to make sure it's not outdated along with the
1506 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001507 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1508 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001509
1510 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1511 // reported, but substream 1 should.
1512 fake_clock_.AdvanceTimeMilliseconds(1);
1513 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001514 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1515 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1516 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1517 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001518}
1519
Peter Boström20f3f942015-05-15 11:33:39 +02001520TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1521 static const int kEncodedWidth = 123;
1522 static const int kEncodedHeight = 81;
1523 EncodedImage encoded_image;
1524 encoded_image._encodedWidth = kEncodedWidth;
1525 encoded_image._encodedHeight = kEncodedHeight;
1526
kjellander02b3d272016-04-20 05:05:54 -07001527 CodecSpecificInfo codec_info;
1528 codec_info.codecType = kVideoCodecVP8;
1529 codec_info.codecSpecific.VP8.simulcastIdx = 0;
Peter Boström20f3f942015-05-15 11:33:39 +02001530
kjellander02b3d272016-04-20 05:05:54 -07001531 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1532 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1533 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001534
1535 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1536 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1537 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1538 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1539 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1540 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1541}
1542
1543TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001544 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001545 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1546 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1547 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1548
1549 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1550
1551 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001552 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001553 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001554 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001555 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1556 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1557 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1558}
1559
sprang07fb9be2016-02-24 07:55:00 -08001560TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1561 RtcpPacketTypeCounterObserver* proxy =
1562 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1563 RtcpPacketTypeCounter counters;
1564 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1565 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1566 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1567
1568 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1569
1570 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1571 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1572 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1573 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1574 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1575
1576 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1577 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1578
1579 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001580 VideoEncoderConfig config;
1581 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001582 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
sprang07fb9be2016-02-24 07:55:00 -08001583
asapersson01d70a32016-05-20 06:29:46 -07001584 EXPECT_EQ(1,
1585 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1586 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1587 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1588 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001589 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1590
1591 const int kRate = 60 * 2; // Packets per minute with two streams.
1592
asapersson01d70a32016-05-20 06:29:46 -07001593 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1594 1 * kRate));
1595 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1596 2 * kRate));
1597 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1598 3 * kRate));
1599 EXPECT_EQ(
1600 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1601 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001602
1603 // New start time but same counter values.
1604 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1605 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1606
1607 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1608
1609 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1610 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1611 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1612 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1613 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1614
1615 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1616 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1617
1618 SetUp(); // Reset stats proxy also causes histograms to be reported.
1619
asapersson01d70a32016-05-20 06:29:46 -07001620 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001621 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001622 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001623 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001624 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001625 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1626 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001627 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001628 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1629
asapersson01d70a32016-05-20 06:29:46 -07001630 EXPECT_EQ(1, metrics::NumEvents(
1631 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1632 1 * kRate));
1633 EXPECT_EQ(1, metrics::NumEvents(
1634 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1635 2 * kRate));
1636 EXPECT_EQ(1, metrics::NumEvents(
1637 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1638 3 * kRate));
1639 EXPECT_EQ(1,
1640 metrics::NumEvents(
1641 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1642 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001643}
1644
asaperssona6a699a2016-11-25 03:52:46 -08001645TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1646 statistics_proxy_.reset(
1647 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1648 VideoEncoderConfig::ContentType::kRealtimeVideo));
1649
1650 StreamDataCountersCallback* proxy =
1651 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1652 StreamDataCounters counters;
1653 proxy->DataCountersUpdated(counters, kFirstSsrc);
1654 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1655
1656 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1657 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1658}
1659
1660TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1661 statistics_proxy_.reset(
1662 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1663 VideoEncoderConfig::ContentType::kRealtimeVideo));
1664
1665 StreamDataCountersCallback* proxy =
1666 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001667 StreamDataCounters counters;
1668 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001669
asapersson93e1e232017-02-06 05:18:35 -08001670 const int kMinRequiredPeriodSamples = 8;
1671 const int kPeriodIntervalMs = 2000;
1672 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1673 counters.transmitted.packets += 20;
1674 counters.transmitted.header_bytes += 500;
1675 counters.transmitted.padding_bytes += 1000;
1676 counters.transmitted.payload_bytes += 2000;
1677 counters.retransmitted.packets += 2;
1678 counters.retransmitted.header_bytes += 25;
1679 counters.retransmitted.padding_bytes += 100;
1680 counters.retransmitted.payload_bytes += 250;
1681 counters.fec = counters.retransmitted;
1682 rtx_counters.transmitted = counters.transmitted;
1683 // Advance one interval and update counters.
1684 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1685 proxy->DataCountersUpdated(counters, kFirstSsrc);
1686 proxy->DataCountersUpdated(counters, kSecondSsrc);
1687 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1688 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1689 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1690 }
asaperssona6a699a2016-11-25 03:52:46 -08001691
asaperssona6a699a2016-11-25 03:52:46 -08001692 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001693 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001694 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001695 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1696 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1697 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1698 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1699 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001700 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001701 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1702 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001703 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001704 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1705 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1706 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1707 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1708 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001709 EXPECT_EQ(1,
1710 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001711 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001712 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001713}
1714
Erik Språng22c2b482016-03-01 09:40:42 +01001715TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1716 StreamDataCountersCallback* proxy =
1717 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1718 StreamDataCounters counters;
1719 StreamDataCounters rtx_counters;
1720 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001721
asapersson93e1e232017-02-06 05:18:35 -08001722 const int kMinRequiredPeriodSamples = 8;
1723 const int kPeriodIntervalMs = 2000;
1724 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1725 counters.transmitted.packets += 20;
1726 counters.transmitted.header_bytes += 500;
1727 counters.transmitted.padding_bytes += 1000;
1728 counters.transmitted.payload_bytes += 2000;
1729 counters.retransmitted.packets += 2;
1730 counters.retransmitted.header_bytes += 25;
1731 counters.retransmitted.padding_bytes += 100;
1732 counters.retransmitted.payload_bytes += 250;
1733 counters.fec = counters.retransmitted;
1734 rtx_counters.transmitted = counters.transmitted;
1735 // Advance one interval and update counters.
1736 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1737 proxy->DataCountersUpdated(counters, kFirstSsrc);
1738 proxy->DataCountersUpdated(counters, kSecondSsrc);
1739 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1740 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1741 }
Erik Språng22c2b482016-03-01 09:40:42 +01001742
1743 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001744 VideoEncoderConfig config;
1745 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001746 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
Erik Språng22c2b482016-03-01 09:40:42 +01001747
asapersson93e1e232017-02-06 05:18:35 -08001748 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001749 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001750 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1751 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1752 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1753 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1754 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001755 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001756 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1757 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001758 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001759 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1760 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1761 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1762 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1763 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01001764 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07001765 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001766 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001767 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01001768
asapersson93e1e232017-02-06 05:18:35 -08001769 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01001770 // Double counter values, this should result in the same counts as before but
1771 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08001772 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1773 counters.transmitted.packets += 20;
1774 counters.transmitted.header_bytes += 500;
1775 counters.transmitted.padding_bytes += 1000;
1776 counters.transmitted.payload_bytes += 2000;
1777 counters.retransmitted.packets += 2;
1778 counters.retransmitted.header_bytes += 25;
1779 counters.retransmitted.padding_bytes += 100;
1780 counters.retransmitted.payload_bytes += 250;
1781 counters.fec = counters.retransmitted;
1782 rtx_counters.transmitted = counters.transmitted;
1783 // Advance one interval and update counters.
1784 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1785 proxy->DataCountersUpdated(counters, kFirstSsrc);
1786 proxy->DataCountersUpdated(counters, kSecondSsrc);
1787 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1788 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1789 }
Erik Språng22c2b482016-03-01 09:40:42 +01001790
asapersson93e1e232017-02-06 05:18:35 -08001791 // Reset stats proxy also causes histograms to be reported.
1792 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01001793
asapersson93e1e232017-02-06 05:18:35 -08001794 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001795 EXPECT_EQ(1,
1796 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001797 EXPECT_EQ(
1798 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
1799 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1800 EXPECT_EQ(
1801 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
1802 EXPECT_EQ(1, metrics::NumEvents(
1803 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
1804 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001805 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001806 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001807 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001808 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
1809 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001810 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001811 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001812 EXPECT_EQ(1, metrics::NumEvents(
1813 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
1814 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1815 EXPECT_EQ(
1816 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
1817 EXPECT_EQ(1, metrics::NumEvents(
1818 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
1819 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07001820 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001821 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001822 EXPECT_EQ(1,
1823 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001824 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
1825}
Erik Språng22c2b482016-03-01 09:40:42 +01001826
asapersson93e1e232017-02-06 05:18:35 -08001827TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
1828 StreamDataCountersCallback* proxy =
1829 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1830 StreamDataCounters counters;
1831 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01001832
asapersson93e1e232017-02-06 05:18:35 -08001833 const int kMinRequiredPeriodSamples = 8;
1834 const int kPeriodIntervalMs = 2000;
1835 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1836 counters.transmitted.packets += 20;
1837 counters.transmitted.header_bytes += 500;
1838 counters.transmitted.payload_bytes += 2000;
1839 counters.fec = counters.retransmitted;
1840 // Advance one interval and update counters.
1841 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1842 proxy->DataCountersUpdated(counters, kFirstSsrc);
1843 }
1844
1845 // RTX enabled. No data sent over RTX.
1846 statistics_proxy_.reset();
1847 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1848 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
1849}
1850
1851TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
1852 VideoSendStream::Config config(nullptr);
1853 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
1854 statistics_proxy_.reset(new SendStatisticsProxy(
1855 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1856
1857 StreamDataCountersCallback* proxy =
1858 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1859 StreamDataCounters counters;
1860
1861 const int kMinRequiredPeriodSamples = 8;
1862 const int kPeriodIntervalMs = 2000;
1863 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1864 counters.transmitted.packets += 20;
1865 counters.transmitted.header_bytes += 500;
1866 counters.transmitted.payload_bytes += 2000;
1867 counters.fec = counters.retransmitted;
1868 // Advance one interval and update counters.
1869 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1870 proxy->DataCountersUpdated(counters, kFirstSsrc);
1871 }
1872
1873 // RTX not enabled.
1874 statistics_proxy_.reset();
1875 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1876}
1877
1878TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
1879 StreamDataCountersCallback* proxy =
1880 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1881 StreamDataCounters counters;
1882 StreamDataCounters rtx_counters;
1883
1884 const int kMinRequiredPeriodSamples = 8;
1885 const int kPeriodIntervalMs = 2000;
1886 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1887 counters.transmitted.packets += 20;
1888 counters.transmitted.header_bytes += 500;
1889 counters.transmitted.payload_bytes += 2000;
1890 // Advance one interval and update counters.
1891 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1892 proxy->DataCountersUpdated(counters, kFirstSsrc);
1893 }
1894
1895 // FEC enabled. No FEC data sent.
1896 statistics_proxy_.reset();
1897 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1898 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
1899}
1900
1901TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
1902 VideoSendStream::Config config(nullptr);
1903 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
1904 statistics_proxy_.reset(new SendStatisticsProxy(
1905 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1906
1907 StreamDataCountersCallback* proxy =
1908 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1909 StreamDataCounters counters;
1910
1911 const int kMinRequiredPeriodSamples = 8;
1912 const int kPeriodIntervalMs = 2000;
1913 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1914 counters.transmitted.packets += 20;
1915 counters.transmitted.header_bytes += 500;
1916 counters.transmitted.payload_bytes += 2000;
1917 counters.fec = counters.retransmitted;
1918 // Advance one interval and update counters.
1919 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1920 proxy->DataCountersUpdated(counters, kFirstSsrc);
1921 }
1922
1923 // FEC not enabled.
1924 statistics_proxy_.reset();
1925 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001926}
1927
asapersson8d75ac72017-09-15 06:41:15 -07001928TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
1929 const char* kName = "encoderName";
1930 EncodedImage encoded_image;
1931 CodecSpecificInfo codec_info;
1932 codec_info.codec_name = kName;
1933 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1934 EXPECT_STREQ(
1935 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str());
1936}
1937
1938class ForcedFallbackTest : public SendStatisticsProxyTest {
1939 public:
1940 explicit ForcedFallbackTest(const std::string& field_trials)
1941 : SendStatisticsProxyTest(field_trials) {
1942 codec_info_.codecType = kVideoCodecVP8;
1943 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
1944 codec_info_.codecSpecific.VP8.temporalIdx = 0;
1945 codec_info_.codec_name = "fake_codec";
Åsa Persson45bbc8a2017-11-13 10:16:47 +01001946 encoded_image_._encodedWidth = kWidth;
1947 encoded_image_._encodedHeight = kHeight;
asapersson8d75ac72017-09-15 06:41:15 -07001948 }
1949
1950 ~ForcedFallbackTest() override {}
1951
1952 protected:
1953 void InsertEncodedFrames(int num_frames, int interval_ms) {
1954 // First frame is not updating stats, insert initial frame.
1955 if (statistics_proxy_->GetStats().frames_encoded == 0) {
1956 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1957 }
1958 for (int i = 0; i < num_frames; ++i) {
1959 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1960 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
1961 }
1962 // Add frame to include last time interval.
1963 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1964 }
1965
1966 EncodedImage encoded_image_;
1967 CodecSpecificInfo codec_info_;
1968 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
1969 const int kFrameIntervalMs = 1000;
1970 const int kMinFrames = 20; // Min run time 20 sec.
1971};
1972
1973class ForcedFallbackDisabled : public ForcedFallbackTest {
1974 public:
1975 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01001976 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
1977 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07001978};
1979
1980class ForcedFallbackEnabled : public ForcedFallbackTest {
1981 public:
1982 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01001983 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
1984 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07001985};
1986
1987TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
1988 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
1989 statistics_proxy_.reset();
1990 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1991 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1992}
1993
1994TEST_F(ForcedFallbackEnabled, StatsUpdated) {
1995 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01001996 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07001997 statistics_proxy_.reset();
1998 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1999 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2000 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2001 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2002}
2003
2004TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2005 codec_info_.codecType = kVideoCodecVP9;
2006 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2007 statistics_proxy_.reset();
2008 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2009 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2010}
2011
2012TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2013 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2014 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2015 statistics_proxy_.reset();
2016 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2017 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2018}
2019
2020TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
2021 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
2022 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2023 statistics_proxy_.reset();
2024 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2025 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2026}
2027
2028TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2029 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2030 statistics_proxy_.reset();
2031 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2032 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2033}
2034
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002035TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2036 InsertEncodedFrames(1, kFrameIntervalMs);
2037 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2038}
2039
2040TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2041 InsertEncodedFrames(1, kFrameIntervalMs);
2042 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2043}
2044
2045TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
2046 codec_info_.codec_name = "libvpx";
2047 InsertEncodedFrames(1, kFrameIntervalMs);
2048 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2049}
2050
2051TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2052 encoded_image_._encodedWidth = kWidth + 1;
2053 InsertEncodedFrames(1, kFrameIntervalMs);
2054 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2055}
2056
2057TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
2058 codec_info_.codec_name = "libvpx";
2059 InsertEncodedFrames(1, kFrameIntervalMs);
2060 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2061}
2062
2063TEST_F(ForcedFallbackDisabled,
2064 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2065 encoded_image_._encodedWidth = kWidth + 1;
2066 statistics_proxy_->OnMinPixelLimitReached();
2067 InsertEncodedFrames(1, kFrameIntervalMs);
2068 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2069}
2070
asapersson8d75ac72017-09-15 06:41:15 -07002071TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2072 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002073 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002074 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002075 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002076 codec_info_.codec_name = "libvpx";
2077 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002078 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002079
2080 statistics_proxy_.reset();
2081 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2082 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2083 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2084 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2085}
2086
2087TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2088 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2089 const int kMaxFrameDiffMs = 2000;
2090
2091 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2092 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002093 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002094 codec_info_.codec_name = "libvpx";
2095 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002096 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002097 codec_info_.codec_name = "notlibvpx";
2098 InsertEncodedFrames(20, 1000);
2099 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2100 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002101 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002102 codec_info_.codec_name = "notlibvpx2";
2103 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002104 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002105 codec_info_.codec_name = "libvpx";
2106 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002107 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002108
2109 statistics_proxy_.reset();
2110 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2111 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2112 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2113 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2114}
2115
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002116TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2117 encoded_image_._encodedWidth = kWidth + 1;
asapersson8d75ac72017-09-15 06:41:15 -07002118 codec_info_.codec_name = "libvpx";
2119 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2120
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002121 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002122 statistics_proxy_.reset();
2123 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2124 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2125}
2126
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002127TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2128 encoded_image_._encodedWidth = kWidth;
asapersson8d75ac72017-09-15 06:41:15 -07002129 codec_info_.codec_name = "libvpx";
2130 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2131
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002132 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002133 statistics_proxy_.reset();
2134 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2135 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2136}
2137
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002138} // namespace webrtc