blob: ee4ef5d6f9fa2b9b98f35d43b91d1a5c7742ce54 [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;
31const int kWidth = 640;
32const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070033const int kQpIdx0 = 21;
34const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010035const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080036const CodecSpecificInfo kDefaultCodecInfo = []() {
37 CodecSpecificInfo codec_info;
38 codec_info.codecType = kVideoCodecVP8;
39 codec_info.codecSpecific.VP8.simulcastIdx = 0;
40 return codec_info;
41}();
asapersson5265fed2016-04-18 02:58:47 -070042} // namespace
sprang07fb9be2016-02-24 07:55:00 -080043
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000044class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000045 public:
asapersson8d75ac72017-09-15 06:41:15 -070046 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
47 explicit SendStatisticsProxyTest(const std::string& field_trials)
48 : override_field_trials_(field_trials),
49 fake_clock_(1234),
50 config_(GetTestConfig()),
51 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070052 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000053 virtual ~SendStatisticsProxyTest() {}
54
55 protected:
56 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070057 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080058 statistics_proxy_.reset(new SendStatisticsProxy(
59 &fake_clock_, GetTestConfig(),
60 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000061 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070062 for (const auto& ssrc : config_.rtp.ssrcs)
63 expected_.substreams[ssrc].is_rtx = false;
64 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
65 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000066 }
67
68 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070069 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080070 config.rtp.ssrcs.push_back(kFirstSsrc);
71 config.rtp.ssrcs.push_back(kSecondSsrc);
72 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
73 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070074 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000075 return config;
76 }
77
asaperssona6a699a2016-11-25 03:52:46 -080078 VideoSendStream::Config GetTestConfigWithFlexFec() {
79 VideoSendStream::Config config(nullptr);
80 config.rtp.ssrcs.push_back(kFirstSsrc);
81 config.rtp.ssrcs.push_back(kSecondSsrc);
82 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
83 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080084 config.rtp.flexfec.payload_type = 50;
85 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080086 return config;
87 }
88
89 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
90 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
91 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
92 stats.substreams.find(ssrc);
93 EXPECT_NE(it, stats.substreams.end());
94 return it->second;
95 }
96
asapersson66d4b372016-12-19 06:50:53 -080097 void UpdateDataCounters(uint32_t ssrc) {
98 StreamDataCountersCallback* proxy =
99 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
100 StreamDataCounters counters;
101 proxy->DataCountersUpdated(counters, ssrc);
102 }
103
sprang@webrtc.org09315702014-02-07 12:06:29 +0000104 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000105 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
106 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000107 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000108 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000109
110 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000111 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000112 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000113 it != one.substreams.end(); ++it) {
114 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
115 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000116 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000117 const VideoSendStream::StreamStats& a = it->second;
118 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000119
asapersson2e5cfcd2016-08-11 08:41:18 -0700120 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000121 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
122 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000123 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000124 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
125 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000126
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000127 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
128 b.rtp_stats.transmitted.payload_bytes);
129 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
130 b.rtp_stats.transmitted.header_bytes);
131 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
132 b.rtp_stats.transmitted.padding_bytes);
133 EXPECT_EQ(a.rtp_stats.transmitted.packets,
134 b.rtp_stats.transmitted.packets);
135 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
136 b.rtp_stats.retransmitted.packets);
137 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000138
139 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700140 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
141 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
142 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000143 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
144 }
145 }
146
asapersson8d75ac72017-09-15 06:41:15 -0700147 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000148 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800149 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000150 VideoSendStream::Config config_;
151 int avg_delay_ms_;
152 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000153 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000154 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
155 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156};
157
158TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
159 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700160 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000161 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000162
163 // Add statistics with some arbitrary, but unique, numbers.
164 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700165 ssrc_stats.rtcp_stats.packets_lost = offset;
166 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000167 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
168 ssrc_stats.rtcp_stats.jitter = offset + 3;
169 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
170 }
asapersson35151f32016-05-02 23:44:01 -0700171 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000172 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000174 // Add statistics with some arbitrary, but unique, numbers.
175 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700176 ssrc_stats.rtcp_stats.packets_lost = offset;
177 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000178 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
179 ssrc_stats.rtcp_stats.jitter = offset + 3;
180 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
181 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000182 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000183 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184}
185
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000186TEST_F(SendStatisticsProxyTest, Suspended) {
187 // Verify that the value is false by default.
188 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
189
190 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200191 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000192 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
193
194 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200195 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000196 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
197}
198
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000199TEST_F(SendStatisticsProxyTest, FrameCounts) {
200 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700201 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000202 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000203 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
204 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000205 FrameCounts frame_counts;
206 frame_counts.key_frames = offset;
207 frame_counts.delta_frames = offset + 1;
208 stats.frame_counts = frame_counts;
209 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000210 }
asapersson35151f32016-05-02 23:44:01 -0700211 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000212 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000213 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
214 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000215 FrameCounts frame_counts;
216 frame_counts.key_frames = offset;
217 frame_counts.delta_frames = offset + 1;
218 stats.frame_counts = frame_counts;
219 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000220 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000221
222 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000223 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224}
225
226TEST_F(SendStatisticsProxyTest, DataCounters) {
227 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700228 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000229 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
230 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000231 size_t offset = ssrc * sizeof(StreamDataCounters);
232 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000233 counters.transmitted.payload_bytes = offset;
234 counters.transmitted.header_bytes = offset + 1;
235 counters.fec.packets = offset_uint32 + 2;
236 counters.transmitted.padding_bytes = offset + 3;
237 counters.retransmitted.packets = offset_uint32 + 4;
238 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000239 callback->DataCountersUpdated(counters, ssrc);
240 }
asapersson35151f32016-05-02 23:44:01 -0700241 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000242 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
243 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000244 size_t offset = ssrc * sizeof(StreamDataCounters);
245 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000246 counters.transmitted.payload_bytes = offset;
247 counters.transmitted.header_bytes = offset + 1;
248 counters.fec.packets = offset_uint32 + 2;
249 counters.transmitted.padding_bytes = offset + 3;
250 counters.retransmitted.packets = offset_uint32 + 4;
251 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000252 callback->DataCountersUpdated(counters, ssrc);
253 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000254
255 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000256 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000257}
258
259TEST_F(SendStatisticsProxyTest, Bitrate) {
260 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700261 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700262 uint32_t total;
263 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000264 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700265 total = ssrc;
266 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000267 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700268 expected_.substreams[ssrc].total_bitrate_bps = total;
269 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000270 }
asapersson35151f32016-05-02 23:44:01 -0700271 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700272 uint32_t total;
273 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000274 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700275 total = ssrc;
276 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000277 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700278 expected_.substreams[ssrc].total_bitrate_bps = total;
279 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000280 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000281
282 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000283 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000284}
285
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000286TEST_F(SendStatisticsProxyTest, SendSideDelay) {
287 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700288 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000289 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
290 // stream.
291 int avg_delay_ms = ssrc;
292 int max_delay_ms = ssrc + 1;
293 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
294 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
295 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
296 }
asapersson35151f32016-05-02 23:44:01 -0700297 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000298 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
299 // stream.
300 int avg_delay_ms = ssrc;
301 int max_delay_ms = ssrc + 1;
302 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
303 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
304 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
305 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000306 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000307 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000308}
309
Peter Boströme4499152016-02-05 11:13:28 +0100310TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800311 const int kEncodeTimeMs = 11;
Peter Boströme4499152016-02-05 11:13:28 +0100312 CpuOveruseMetrics metrics;
313 metrics.encode_usage_percent = 80;
314 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs, metrics);
asapersson1aa420b2015-12-07 03:12:22 -0800315
316 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
317 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Peter Boströme4499152016-02-05 11:13:28 +0100318 EXPECT_EQ(metrics.encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800319}
320
sakal43536c32016-10-24 01:46:43 -0700321TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
322 EncodedImage encoded_image;
323 CodecSpecificInfo codec_info;
324 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
325 for (uint32_t i = 1; i <= 3; ++i) {
326 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
327 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
328 }
329}
330
sakal87da4042016-10-31 06:53:47 -0700331TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
332 EncodedImage encoded_image;
333 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200334 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700335 encoded_image.qp_ = 3;
336 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100337 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700338 encoded_image.qp_ = 127;
339 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100340 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700341}
342
343TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
344 EncodedImage encoded_image;
345 CodecSpecificInfo codec_info;
346 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200347 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700348 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200349 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700350}
351
asapersson09f05612017-05-15 23:40:18 -0700352TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700353 VideoStreamEncoder::AdaptCounts cpu_counts;
354 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700355 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700356 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700357 cpu_counts.fps = 1;
358 cpu_counts.resolution = 0;
359 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
360 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700361 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700362 cpu_counts.fps = 0;
363 cpu_counts.resolution = 1;
364 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
365 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700366 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700367 cpu_counts.fps = 1;
368 cpu_counts.resolution = -1;
369 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
370 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700371 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700372 cpu_counts.fps = -1;
373 cpu_counts.resolution = -1;
374 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
375 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
376 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
377}
378
379TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700380 VideoStreamEncoder::AdaptCounts cpu_counts;
381 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700382 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
383 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
384 quality_counts.fps = 1;
385 quality_counts.resolution = 0;
386 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
387 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
388 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
389 quality_counts.fps = 0;
390 quality_counts.resolution = 1;
391 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
392 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
393 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
394 quality_counts.fps = 1;
395 quality_counts.resolution = -1;
396 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
397 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
398 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
399 quality_counts.fps = -1;
400 quality_counts.resolution = -1;
401 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
402 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
403 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
404}
405
406TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700407 VideoStreamEncoder::AdaptCounts cpu_counts;
408 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700409 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
410
asapersson09f05612017-05-15 23:40:18 -0700411 cpu_counts.resolution = 1;
412 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
413 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700414 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
415 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
416
asapersson09f05612017-05-15 23:40:18 -0700417 cpu_counts.resolution = 2;
418 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
419 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
420 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700421 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700422 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700423}
424
asapersson09f05612017-05-15 23:40:18 -0700425TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700426 VideoStreamEncoder::AdaptCounts cpu_counts;
427 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700428 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
429
asapersson09f05612017-05-15 23:40:18 -0700430 quality_counts.fps = 1;
431 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
432 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
433 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700434 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
435
asapersson09f05612017-05-15 23:40:18 -0700436 quality_counts.fps = 0;
437 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
438 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700439 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700440 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
441 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700442}
443
asapersson09f05612017-05-15 23:40:18 -0700444TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700445 // First RTP packet sent.
446 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700447 // Min runtime has passed.
448 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
449 statistics_proxy_.reset();
450 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
451 EXPECT_EQ(0,
452 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
453}
454
455TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700456 // First RTP packet sent.
457 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700458 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700459 VideoStreamEncoder::AdaptCounts cpu_counts;
460 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700461 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700462 // Min runtime has not passed.
463 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
464 statistics_proxy_.reset();
465 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
466 EXPECT_EQ(0,
467 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
468}
469
asapersson09f05612017-05-15 23:40:18 -0700470TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700471 // First RTP packet sent.
472 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700473 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700474 VideoStreamEncoder::AdaptCounts cpu_counts;
475 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700476 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700477 // Min runtime has passed.
478 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
479 statistics_proxy_.reset();
480 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
481 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700482 EXPECT_EQ(1,
483 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
484 EXPECT_EQ(
485 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
486}
487
488TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700489 // First RTP packet sent.
490 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700491 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700492 VideoStreamEncoder::AdaptCounts cpu_counts;
493 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700494 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700495 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson09f05612017-05-15 23:40:18 -0700496 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700497 fake_clock_.AdvanceTimeMilliseconds(10000);
498 statistics_proxy_.reset();
499 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
500 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
501}
502
Åsa Persson875841d2018-01-08 08:49:53 +0100503TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
504 // First RTP packet sent.
505 UpdateDataCounters(kFirstSsrc);
506 // Enable adaptation.
507 VideoStreamEncoder::AdaptCounts cpu_counts;
508 VideoStreamEncoder::AdaptCounts quality_counts;
509 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
510 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
511 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
512 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
513 fake_clock_.AdvanceTimeMilliseconds(10000);
514 statistics_proxy_.reset();
515 EXPECT_EQ(1,
516 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
517 EXPECT_EQ(
518 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
519}
520
521TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
522 // First RTP packet sent.
523 UpdateDataCounters(kFirstSsrc);
524 // Enable adaptation.
525 VideoStreamEncoder::AdaptCounts cpu_counts;
526 VideoStreamEncoder::AdaptCounts quality_counts;
527 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
528 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
529 quality_counts.resolution = 1;
530 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
531 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
532 quality_counts.resolution = 2;
533 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
534 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
535 quality_counts.resolution = 3;
536 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
537 fake_clock_.AdvanceTimeMilliseconds(10000);
538 statistics_proxy_.reset();
539 EXPECT_EQ(1,
540 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
541 EXPECT_EQ(
542 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
543}
544
545TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
546 // First RTP packet sent.
547 UpdateDataCounters(kFirstSsrc);
548 // Enable adaptation.
549 VideoStreamEncoder::AdaptCounts cpu_counts;
550 VideoStreamEncoder::AdaptCounts quality_counts;
551 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
552 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
553 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
554 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
555 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
556 fake_clock_.AdvanceTimeMilliseconds(10000);
557 statistics_proxy_.reset();
558 EXPECT_EQ(1,
559 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
560 EXPECT_EQ(
561 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
562}
563
564TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
565 // First RTP packet sent.
566 UpdateDataCounters(kFirstSsrc);
567 // Enable adaptation.
568 VideoStreamEncoder::AdaptCounts cpu_counts;
569 VideoStreamEncoder::AdaptCounts quality_counts;
570 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
571 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
572 quality_counts.resolution = 1;
573 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
574 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
575 quality_counts.resolution = 2;
576 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
577 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
578 quality_counts.resolution = 3;
579 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
580 quality_counts.fps = 1;
581 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
582 quality_counts.fps = 0;
583 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
584 quality_counts.resolution = 2; // Initial resolution up.
585 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
586 quality_counts.resolution = 1; // Initial resolution up.
587 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
588 quality_counts.resolution = 0;
589 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
590
591 fake_clock_.AdvanceTimeMilliseconds(10000);
592 statistics_proxy_.reset();
593 EXPECT_EQ(1,
594 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
595 EXPECT_EQ(
596 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
597}
598
asapersson6eca98b2017-04-04 23:40:50 -0700599TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700600 // First RTP packet sent.
601 UpdateDataCounters(kFirstSsrc);
602
asapersson09f05612017-05-15 23:40:18 -0700603 // Disable quality adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700604 VideoStreamEncoder::AdaptCounts cpu_counts;
605 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700606 quality_counts.fps = -1;
607 quality_counts.resolution = -1;
608 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700609 fake_clock_.AdvanceTimeMilliseconds(10000);
610
asapersson09f05612017-05-15 23:40:18 -0700611 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700612 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700613 quality_counts.fps = 0;
614 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700615 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700616 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700617 fake_clock_.AdvanceTimeMilliseconds(9000);
asapersson09f05612017-05-15 23:40:18 -0700618 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700619 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700620 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700621
asapersson09f05612017-05-15 23:40:18 -0700622 // Disable quality adaptation.
623 quality_counts.fps = -1;
624 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700625 fake_clock_.AdvanceTimeMilliseconds(30000);
626
asapersson09f05612017-05-15 23:40:18 -0700627 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700628 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700629 quality_counts.resolution = 0;
630 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
631 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700632 fake_clock_.AdvanceTimeMilliseconds(10000);
633
asapersson09f05612017-05-15 23:40:18 -0700634 // Disable quality adaptation.
635 quality_counts.resolution = -1;
636 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700637 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700638 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700639 fake_clock_.AdvanceTimeMilliseconds(20000);
640
asapersson0944a802017-04-07 00:57:58 -0700641 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700642 statistics_proxy_.reset();
643 EXPECT_EQ(1,
644 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
645 EXPECT_EQ(
646 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
647}
648
asapersson0944a802017-04-07 00:57:58 -0700649TEST_F(SendStatisticsProxyTest,
650 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
651 // First RTP packet sent.
652 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700653
asapersson0944a802017-04-07 00:57:58 -0700654 // Suspend and resume video.
655 statistics_proxy_->OnSuspendChange(true);
656 fake_clock_.AdvanceTimeMilliseconds(5000);
657 statistics_proxy_->OnSuspendChange(false);
658
659 // Min runtime has passed but scaling not enabled.
660 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
661 statistics_proxy_.reset();
662 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
663 EXPECT_EQ(0,
664 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
665}
666
667TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
668 // First RTP packet sent.
669 UpdateDataCounters(kFirstSsrc);
670
asapersson09f05612017-05-15 23:40:18 -0700671 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700672 VideoStreamEncoder::AdaptCounts cpu_counts;
673 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700674 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700675 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700676 fake_clock_.AdvanceTimeMilliseconds(20000);
asapersson09f05612017-05-15 23:40:18 -0700677 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
678 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700679
680 // Suspend and resume video.
681 statistics_proxy_->OnSuspendChange(true);
682 fake_clock_.AdvanceTimeMilliseconds(30000);
683 statistics_proxy_->OnSuspendChange(false);
684
685 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700686 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700687 fake_clock_.AdvanceTimeMilliseconds(10000);
688
689 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
690 statistics_proxy_.reset();
691 EXPECT_EQ(1,
692 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
693 EXPECT_EQ(
694 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
695}
696
697TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
698 // First RTP packet sent.
699 UpdateDataCounters(kFirstSsrc);
700
701 // Video not suspended.
702 statistics_proxy_->OnSuspendChange(false);
703 fake_clock_.AdvanceTimeMilliseconds(30000);
704
asapersson09f05612017-05-15 23:40:18 -0700705 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700706 VideoStreamEncoder::AdaptCounts cpu_counts;
707 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700708 // Adapt changes: 1, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700709 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700710 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700711 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700712
713 // Video not suspended, stats time already started.
714 statistics_proxy_->OnSuspendChange(false);
715 fake_clock_.AdvanceTimeMilliseconds(10000);
716
asapersson09f05612017-05-15 23:40:18 -0700717 // Disable adaptation.
718 cpu_counts.fps = -1;
719 cpu_counts.resolution = -1;
720 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700721 fake_clock_.AdvanceTimeMilliseconds(30000);
722
723 // Suspend and resume video, stats time not started when scaling not enabled.
724 statistics_proxy_->OnSuspendChange(true);
725 fake_clock_.AdvanceTimeMilliseconds(30000);
726 statistics_proxy_->OnSuspendChange(false);
727 fake_clock_.AdvanceTimeMilliseconds(30000);
728
asapersson09f05612017-05-15 23:40:18 -0700729 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700730 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700731 cpu_counts.fps = 0;
732 cpu_counts.resolution = 0;
733 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700734 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700735 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700736
737 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
738 statistics_proxy_.reset();
739 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
740 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
741}
742
743TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
744 // First RTP packet sent.
745 UpdateDataCounters(kFirstSsrc);
746
747 // Video suspended.
748 statistics_proxy_->OnSuspendChange(true);
749
asapersson09f05612017-05-15 23:40:18 -0700750 // Enable adaptation, stats time not started when suspended.
mflodmancc3d4422017-08-03 08:27:51 -0700751 VideoStreamEncoder::AdaptCounts cpu_counts;
752 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700753 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700754 fake_clock_.AdvanceTimeMilliseconds(10000);
755
756 // Resume video, stats time started.
757 // Adapt changes: 1, elapsed time: 10 sec.
758 statistics_proxy_->OnSuspendChange(false);
759 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700760 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700761
762 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
763 statistics_proxy_.reset();
764 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
765 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
766}
767
768TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700769 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700770 // Elapsed time before first packet is sent should be excluded.
mflodmancc3d4422017-08-03 08:27:51 -0700771 VideoStreamEncoder::AdaptCounts cpu_counts;
772 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700773 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700774 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700775 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700776
asapersson0944a802017-04-07 00:57:58 -0700777 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700778 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700779 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700780 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700781
asapersson0944a802017-04-07 00:57:58 -0700782 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700783 statistics_proxy_.reset();
784 EXPECT_EQ(1,
785 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
786 EXPECT_EQ(
787 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
788}
789
790TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700791 // Enable and disable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700792 VideoStreamEncoder::AdaptCounts cpu_counts;
793 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700794 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700795 fake_clock_.AdvanceTimeMilliseconds(60000);
asapersson09f05612017-05-15 23:40:18 -0700796 cpu_counts.fps = -1;
797 cpu_counts.resolution = -1;
798 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700799
800 // Send first packet, scaling disabled.
801 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700802 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700803 fake_clock_.AdvanceTimeMilliseconds(60000);
804
asapersson09f05612017-05-15 23:40:18 -0700805 // Enable adaptation.
806 cpu_counts.resolution = 0;
807 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700808 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700809 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700810
asapersson0944a802017-04-07 00:57:58 -0700811 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700812 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700813 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700814
asapersson0944a802017-04-07 00:57:58 -0700815 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700816 statistics_proxy_.reset();
817 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
818 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
819}
820
821TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700822 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700823 UpdateDataCounters(kFirstSsrc);
mflodmancc3d4422017-08-03 08:27:51 -0700824 VideoStreamEncoder::AdaptCounts cpu_counts;
825 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700826 quality_counts.fps = -1;
827 quality_counts.resolution = -1;
828 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700829
asapersson0944a802017-04-07 00:57:58 -0700830 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
asapersson09f05612017-05-15 23:40:18 -0700831 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700832 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700833 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700834 fake_clock_.AdvanceTimeMilliseconds(9000);
835
836 // Switch content type, real-time stats should be updated.
837 VideoEncoderConfig config;
838 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +0200839 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson6eca98b2017-04-04 23:40:50 -0700840 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
841 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
842 EXPECT_EQ(0,
843 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
844
asapersson0944a802017-04-07 00:57:58 -0700845 // First RTP packet sent, scaling enabled.
846 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700847 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700848
asapersson0944a802017-04-07 00:57:58 -0700849 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
asapersson09f05612017-05-15 23:40:18 -0700850 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
851 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
852 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
853 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700854 fake_clock_.AdvanceTimeMilliseconds(120000);
855
856 statistics_proxy_.reset();
857 EXPECT_EQ(1, metrics::NumSamples(
858 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
859 EXPECT_EQ(1, metrics::NumEvents(
860 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
861 EXPECT_EQ(0, metrics::NumSamples(
862 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
863}
864
asapersson59bac1a2016-01-07 23:36:00 -0800865TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -0700866 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -0800867 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
868
Pera48ddb72016-09-29 11:48:50 +0200869 // No switch, stats should not be updated.
870 VideoEncoderConfig config;
871 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +0200872 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -0700873 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800874
875 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +0200876 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +0200877 statistics_proxy_->OnEncoderReconfigured(config, {});
asapersson01d70a32016-05-20 06:29:46 -0700878 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800879}
880
asapersson320e45a2016-11-29 01:40:35 -0800881TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
882 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
883 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -0700884
asapersson320e45a2016-11-29 01:40:35 -0800885 statistics_proxy_.reset();
886 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
887 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
888 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
889 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
890}
891
892TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +0200893 const int64_t kMaxEncodedFrameWindowMs = 800;
894 const int kFps = 20;
895 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
896 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
897 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -0800898 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +0200899
900 // Not enough samples, stats should not be updated.
901 for (int i = 0; i < kMinSamples - 1; ++i) {
902 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
903 ++encoded_image._timeStamp;
asapersson320e45a2016-11-29 01:40:35 -0800904 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
905 }
Åsa Persson0122e842017-10-16 12:19:23 +0200906 SetUp(); // Reset stats proxy also causes histograms to be reported.
907 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
908 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
909
910 // Enough samples, max resolution per frame should be reported.
911 encoded_image._timeStamp = 0xfffffff0; // Will wrap.
912 for (int i = 0; i < kMinSamples; ++i) {
913 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
914 ++encoded_image._timeStamp;
915 encoded_image._encodedWidth = kWidth;
916 encoded_image._encodedHeight = kHeight;
917 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
918 encoded_image._encodedWidth = kWidth / 2;
919 encoded_image._encodedHeight = kHeight / 2;
920 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
921 }
922
asapersson320e45a2016-11-29 01:40:35 -0800923 statistics_proxy_.reset();
924 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
925 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
926 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
927 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
928}
929
930TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
931 const int kFps = 20;
932 const int kMinPeriodicSamples = 6;
933 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
934 for (int i = 0; i <= frames; ++i) {
935 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
936 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
937 }
938 statistics_proxy_.reset();
939 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
940 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
941}
942
943TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
944 EncodedImage encoded_image;
945 const int kFps = 20;
946 const int kMinPeriodicSamples = 6;
947 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +0200948 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800949 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +0200950 ++encoded_image._timeStamp;
951 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
952 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -0800953 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
954 }
955 statistics_proxy_.reset();
956 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
957 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
958}
959
960TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
961 const int kFps = 20;
962 const int kSuspendTimeMs = 10000;
963 const int kMinPeriodicSamples = 6;
964 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
965 for (int i = 0; i < frames; ++i) {
966 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
967 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
968 }
969 // Suspend.
970 statistics_proxy_->OnSuspendChange(true);
971 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
972
973 for (int i = 0; i < frames; ++i) {
974 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
975 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
976 }
977 // Suspended time interval should not affect the framerate.
978 statistics_proxy_.reset();
979 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
980 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
981}
982
983TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
984 EncodedImage encoded_image;
985 const int kFps = 20;
986 const int kSuspendTimeMs = 10000;
987 const int kMinPeriodicSamples = 6;
988 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +0200989 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800990 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
991 encoded_image._timeStamp = i + 1;
992 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
993 }
994 // Suspend.
995 statistics_proxy_->OnSuspendChange(true);
996 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
997
Åsa Persson0122e842017-10-16 12:19:23 +0200998 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800999 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1000 encoded_image._timeStamp = i + 1;
1001 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1002 }
1003 // Suspended time interval should not affect the framerate.
1004 statistics_proxy_.reset();
1005 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1006 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1007}
1008
asaperssonf4e44af2017-04-19 02:01:06 -07001009TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -07001010 VideoStreamEncoder::AdaptCounts cpu_counts;
1011 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001012 cpu_counts.resolution = -1;
1013 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001014
1015 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1016 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1017
1018 statistics_proxy_.reset();
1019 EXPECT_EQ(0,
1020 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1021}
1022
1023TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
mflodmancc3d4422017-08-03 08:27:51 -07001024 VideoStreamEncoder::AdaptCounts cpu_counts;
1025 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001026 cpu_counts.resolution = 0;
1027 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001028
perkj803d97f2016-11-01 11:45:46 -07001029 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1030 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1031
asapersson09f05612017-05-15 23:40:18 -07001032 cpu_counts.resolution = 1;
1033 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001034
1035 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1036 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1037
1038 statistics_proxy_.reset();
1039 EXPECT_EQ(1,
1040 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1041 EXPECT_EQ(
1042 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1043}
1044
asapersson4374a092016-07-27 00:39:09 -07001045TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1046 const int64_t kTimeSec = 3;
1047 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1048 statistics_proxy_.reset();
1049 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1050 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1051 kTimeSec));
1052}
1053
1054TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1055 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1056 statistics_proxy_.reset();
1057 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1058}
1059
asapersson66d4b372016-12-19 06:50:53 -08001060TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1061 // First RTP packet sent.
1062 UpdateDataCounters(kFirstSsrc);
1063
1064 // Min runtime has passed.
1065 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1066 statistics_proxy_.reset();
1067 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1068 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1069}
1070
1071TEST_F(SendStatisticsProxyTest,
1072 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1073 // First RTP packet sent.
1074 UpdateDataCounters(kFirstSsrc);
1075
1076 // Min runtime has not passed.
1077 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1078 statistics_proxy_.reset();
1079 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1080 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1081}
1082
1083TEST_F(SendStatisticsProxyTest,
1084 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1085 // First RTP packet not sent.
1086 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1087 statistics_proxy_.reset();
1088 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1089}
1090
1091TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1092 // First RTP packet sent and min runtime passed.
1093 UpdateDataCounters(kFirstSsrc);
1094
1095 // No change. Video: 10000 ms, paused: 0 ms (0%).
1096 statistics_proxy_->OnSetEncoderTargetRate(50000);
1097 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1098 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1099
1100 statistics_proxy_.reset();
1101 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1102 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1103 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1104 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1105}
1106
1107TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1108 // First RTP packet sent and min runtime passed.
1109 UpdateDataCounters(kFirstSsrc);
1110
1111 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1112 statistics_proxy_->OnSetEncoderTargetRate(50000);
1113 fake_clock_.AdvanceTimeMilliseconds(7000);
1114 statistics_proxy_->OnSetEncoderTargetRate(0);
1115 fake_clock_.AdvanceTimeMilliseconds(3000);
1116 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1117
1118 statistics_proxy_.reset();
1119 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1120 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1121 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1122 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1123}
1124
1125TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1126 // First RTP packet sent.
1127 UpdateDataCounters(kFirstSsrc);
1128
1129 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1130 statistics_proxy_->OnSetEncoderTargetRate(0);
1131 fake_clock_.AdvanceTimeMilliseconds(1000);
1132 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1133 fake_clock_.AdvanceTimeMilliseconds(7000);
1134 statistics_proxy_->OnSetEncoderTargetRate(60000);
1135 fake_clock_.AdvanceTimeMilliseconds(3000);
1136 statistics_proxy_->OnSetEncoderTargetRate(0);
1137 fake_clock_.AdvanceTimeMilliseconds(250);
1138 statistics_proxy_->OnSetEncoderTargetRate(0);
1139 fake_clock_.AdvanceTimeMilliseconds(750);
1140 statistics_proxy_->OnSetEncoderTargetRate(60000);
1141 fake_clock_.AdvanceTimeMilliseconds(5000);
1142 statistics_proxy_->OnSetEncoderTargetRate(50000);
1143 fake_clock_.AdvanceTimeMilliseconds(4000);
1144 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1145
1146 statistics_proxy_.reset();
1147 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1148 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1149 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1150 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1151}
1152
1153TEST_F(SendStatisticsProxyTest,
1154 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1155 // First RTP packet sent.
1156 UpdateDataCounters(kFirstSsrc);
1157 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1158
1159 // Min runtime has not passed.
1160 statistics_proxy_->OnSetEncoderTargetRate(50000);
1161 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1162 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1163
1164 statistics_proxy_.reset();
1165 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1166}
1167
asapersson118ef002016-03-31 00:00:19 -07001168TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001169 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001170 CodecSpecificInfo codec_info;
1171 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001172
perkj803d97f2016-11-01 11:45:46 -07001173 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001174 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001175 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001176 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1177 codec_info.codecSpecific.VP8.simulcastIdx = 1;
asapersson118ef002016-03-31 00:00:19 -07001178 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001179 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001180 }
1181 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001182 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1183 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1184 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1185 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001186}
1187
1188TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1189 VideoSendStream::Config config(nullptr);
1190 config.rtp.ssrcs.push_back(kFirstSsrc);
1191 statistics_proxy_.reset(new SendStatisticsProxy(
1192 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1193
asapersson118ef002016-03-31 00:00:19 -07001194 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001195 CodecSpecificInfo codec_info;
1196 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001197
perkj803d97f2016-11-01 11:45:46 -07001198 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001199 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001200 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001201 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001202 }
1203 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001204 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1205 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001206}
1207
asapersson5265fed2016-04-18 02:58:47 -07001208TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001209 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001210 CodecSpecificInfo codec_info;
1211 codec_info.codecType = kVideoCodecVP9;
1212 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001213
perkj803d97f2016-11-01 11:45:46 -07001214 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001215 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001216 codec_info.codecSpecific.VP9.spatial_idx = 0;
1217 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001218 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001219 codec_info.codecSpecific.VP9.spatial_idx = 1;
1220 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001221 }
1222 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001223 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1224 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1225 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1226 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001227}
1228
1229TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1230 VideoSendStream::Config config(nullptr);
1231 config.rtp.ssrcs.push_back(kFirstSsrc);
1232 statistics_proxy_.reset(new SendStatisticsProxy(
1233 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1234
asapersson5265fed2016-04-18 02:58:47 -07001235 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001236 CodecSpecificInfo codec_info;
1237 codec_info.codecType = kVideoCodecVP9;
1238 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001239
perkj803d97f2016-11-01 11:45:46 -07001240 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001241 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001242 codec_info.codecSpecific.VP9.spatial_idx = 0;
1243 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001244 }
1245 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001246 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1247 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001248}
1249
asapersson827cab32016-11-02 09:08:47 -07001250TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1251 EncodedImage encoded_image;
1252 CodecSpecificInfo codec_info;
1253 codec_info.codecType = kVideoCodecH264;
1254
1255 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001256 codec_info.codecSpecific.H264.simulcast_idx = 0;
asapersson827cab32016-11-02 09:08:47 -07001257 encoded_image.qp_ = kQpIdx0;
1258 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001259 codec_info.codecSpecific.H264.simulcast_idx = 1;
1260 encoded_image.qp_ = kQpIdx1;
1261 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001262 }
1263 statistics_proxy_.reset();
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001264 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1265 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1266 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1267 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001268}
1269
asapersson4ee70462016-10-31 04:05:12 -07001270TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001271 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1272 // Configure one stream.
1273 VideoEncoderConfig config;
1274 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1275 VideoStream stream1;
1276 stream1.width = kWidth;
1277 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001278 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001279
1280 const int64_t kMaxEncodedFrameWindowMs = 800;
1281 const int kFps = 20;
1282 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1283 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1284 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1285
1286 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001287 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001288 encoded_image._encodedWidth = kWidth;
1289 encoded_image._encodedHeight = kHeight;
1290 for (int i = 0; i < kMinSamples; ++i) {
1291 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1292 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001293 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001294 }
asapersson4ee70462016-10-31 04:05:12 -07001295
1296 // Histograms are updated when the statistics_proxy_ is deleted.
1297 statistics_proxy_.reset();
1298 EXPECT_EQ(0, metrics::NumSamples(
1299 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1300 EXPECT_EQ(0, metrics::NumSamples(
1301 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1302}
1303
1304TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001305 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1306 // Configure two streams.
1307 VideoEncoderConfig config;
1308 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1309 VideoStream stream1;
1310 stream1.width = kWidth / 2;
1311 stream1.height = kHeight / 2;
1312 VideoStream stream2;
1313 stream2.width = kWidth;
1314 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001315 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001316
1317 const int64_t kMaxEncodedFrameWindowMs = 800;
1318 const int kFps = 20;
1319 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1320 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1321 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1322
1323 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001324 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001325 for (int i = 0; i < kMinSamples; ++i) {
1326 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1327 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1328 encoded_image._encodedWidth = kWidth;
1329 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001330 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001331 encoded_image._encodedWidth = kWidth / 2;
1332 encoded_image._encodedHeight = kHeight / 2;
1333 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1334 }
asapersson4ee70462016-10-31 04:05:12 -07001335
1336 // Histograms are updated when the statistics_proxy_ is deleted.
1337 statistics_proxy_.reset();
1338 EXPECT_EQ(1, metrics::NumSamples(
1339 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1340 EXPECT_EQ(1, metrics::NumEvents(
1341 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1342 // No resolution disabled.
1343 EXPECT_EQ(0, metrics::NumSamples(
1344 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1345}
1346
1347TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001348 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1349 // Configure two streams.
1350 VideoEncoderConfig config;
1351 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1352 VideoStream stream1;
1353 stream1.width = kWidth / 2;
1354 stream1.height = kHeight / 2;
1355 VideoStream stream2;
1356 stream2.width = kWidth;
1357 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001358 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001359
1360 const int64_t kMaxEncodedFrameWindowMs = 800;
1361 const int kFps = 20;
1362 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1363 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1364 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1365
1366 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001367 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001368 encoded_image._encodedWidth = kWidth / 2;
1369 encoded_image._encodedHeight = kHeight / 2;
1370 for (int i = 0; i < kMinSamples; ++i) {
1371 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1372 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001373 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001374 }
asapersson4ee70462016-10-31 04:05:12 -07001375
1376 // Histograms are updated when the statistics_proxy_ is deleted.
1377 statistics_proxy_.reset();
1378 EXPECT_EQ(1, metrics::NumSamples(
1379 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1380 EXPECT_EQ(1, metrics::NumEvents(
1381 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001382 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001383 EXPECT_EQ(1, metrics::NumSamples(
1384 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001385 EXPECT_EQ(1, metrics::NumEvents(
1386 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001387}
1388
1389TEST_F(SendStatisticsProxyTest,
1390 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -07001391 VideoStreamEncoder::AdaptCounts cpu_counts;
1392 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001393 quality_counts.resolution = -1;
1394 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001395 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001396 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001397 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001398
1399 // Histograms are updated when the statistics_proxy_ is deleted.
1400 statistics_proxy_.reset();
1401 EXPECT_EQ(
1402 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1403 EXPECT_EQ(0, metrics::NumSamples(
1404 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1405}
1406
1407TEST_F(SendStatisticsProxyTest,
1408 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
mflodmancc3d4422017-08-03 08:27:51 -07001409 VideoStreamEncoder::AdaptCounts cpu_counts;
1410 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001411 quality_counts.resolution = 0;
1412 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001413 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001414 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001415 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001416
1417 // Histograms are updated when the statistics_proxy_ is deleted.
1418 statistics_proxy_.reset();
1419 EXPECT_EQ(
1420 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1421 EXPECT_EQ(1, metrics::NumEvents(
1422 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1423 // No resolution downscale.
1424 EXPECT_EQ(0, metrics::NumSamples(
1425 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1426}
1427
1428TEST_F(SendStatisticsProxyTest,
1429 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1430 const int kDownscales = 2;
mflodmancc3d4422017-08-03 08:27:51 -07001431 VideoStreamEncoder::AdaptCounts cpu_counts;
1432 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001433 quality_counts.resolution = kDownscales;
1434 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001435 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001436 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001437 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001438 // Histograms are updated when the statistics_proxy_ is deleted.
1439 statistics_proxy_.reset();
1440 EXPECT_EQ(
1441 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1442 EXPECT_EQ(1, metrics::NumEvents(
1443 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1444 // Resolution downscales.
1445 EXPECT_EQ(1, metrics::NumSamples(
1446 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1447 EXPECT_EQ(
1448 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1449 kDownscales));
1450}
1451
1452TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1453 // Initially false.
1454 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001455
Åsa Perssonaa329e72017-12-15 15:54:44 +01001456 // Configure two streams.
1457 VideoEncoderConfig config;
1458 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1459 VideoStream stream1;
1460 stream1.width = kWidth / 2;
1461 stream1.height = kHeight / 2;
1462 VideoStream stream2;
1463 stream2.width = kWidth;
1464 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001465 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001466
1467 const int64_t kMaxEncodedFrameWindowMs = 800;
1468 const int kFps = 20;
1469 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1470 kFps * kMaxEncodedFrameWindowMs / 1000;
1471
1472 // One stream encoded.
1473 EncodedImage encoded_image;
1474 encoded_image._encodedWidth = kWidth / 2;
1475 encoded_image._encodedHeight = kHeight / 2;
1476 for (int i = 0; i < kMinSamples; ++i) {
1477 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1478 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1479 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1480 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1481 }
1482
1483 // First frame removed from EncodedFrameMap, stats updated.
1484 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1485 ++encoded_image._timeStamp;
kthelgason0cd27ba2016-12-19 06:32:16 -08001486 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1487 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1488
Åsa Perssonaa329e72017-12-15 15:54:44 +01001489 // Two streams encoded.
1490 for (int i = 0; i < kMinSamples; ++i) {
1491 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1492 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1493 encoded_image._encodedWidth = kWidth;
1494 encoded_image._encodedHeight = kHeight;
1495 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1496 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1497 encoded_image._encodedWidth = kWidth / 2;
1498 encoded_image._encodedHeight = kHeight / 2;
1499 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1500 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1501 }
1502
1503 // First frame with two streams removed, expect no resolution limit.
1504 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1505 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001506 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1507 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001508
1509 // Resolution scaled due to quality.
mflodmancc3d4422017-08-03 08:27:51 -07001510 VideoStreamEncoder::AdaptCounts cpu_counts;
1511 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001512 quality_counts.resolution = 1;
1513 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001514 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1515 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1516}
1517
asapersson66d4b372016-12-19 06:50:53 -08001518TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1519 // Initially zero.
1520 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1521
1522 const int kBitrate = 100000;
1523 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1524 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1525
1526 statistics_proxy_->OnSetEncoderTargetRate(0);
1527 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1528}
1529
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001530TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001531 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001532 std::max(
1533 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1534 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1535 config_.rtp.rtx.ssrcs.end())) +
1536 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001537 // From RtcpStatisticsCallback.
1538 RtcpStatistics rtcp_stats;
1539 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001540 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001541
1542 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001543 uint32_t total = 0;
1544 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001545 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001546 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001547
1548 // From FrameCountObserver.
1549 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001550 FrameCounts frame_counts;
1551 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001552 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001553
1554 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1555 EXPECT_TRUE(stats.substreams.empty());
1556}
1557
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001558TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1559 static const int kEncodedWidth = 123;
1560 static const int kEncodedHeight = 81;
1561 EncodedImage encoded_image;
1562 encoded_image._encodedWidth = kEncodedWidth;
1563 encoded_image._encodedHeight = kEncodedHeight;
1564
kjellander02b3d272016-04-20 05:05:54 -07001565 CodecSpecificInfo codec_info;
1566 codec_info.codecType = kVideoCodecVP8;
1567 codec_info.codecSpecific.VP8.simulcastIdx = 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001568
kjellander02b3d272016-04-20 05:05:54 -07001569 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1570 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1571 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001572
1573 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001574 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1575 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1576 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1577 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001578
1579 // Forward almost to timeout, this should not have removed stats.
1580 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1581 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001582 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1583 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001584
1585 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1586 // resolution still times out (no global timeout for all stats).
1587 RtcpStatistics rtcp_statistics;
1588 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1589 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1590
1591 // Report stats for second SSRC to make sure it's not outdated along with the
1592 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001593 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1594 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001595
1596 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1597 // reported, but substream 1 should.
1598 fake_clock_.AdvanceTimeMilliseconds(1);
1599 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001600 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1601 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1602 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1603 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001604}
1605
Peter Boström20f3f942015-05-15 11:33:39 +02001606TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1607 static const int kEncodedWidth = 123;
1608 static const int kEncodedHeight = 81;
1609 EncodedImage encoded_image;
1610 encoded_image._encodedWidth = kEncodedWidth;
1611 encoded_image._encodedHeight = kEncodedHeight;
1612
kjellander02b3d272016-04-20 05:05:54 -07001613 CodecSpecificInfo codec_info;
1614 codec_info.codecType = kVideoCodecVP8;
1615 codec_info.codecSpecific.VP8.simulcastIdx = 0;
Peter Boström20f3f942015-05-15 11:33:39 +02001616
kjellander02b3d272016-04-20 05:05:54 -07001617 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1618 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1619 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001620
1621 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1622 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1623 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1624 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1625 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1626 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1627}
1628
1629TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001630 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001631 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1632 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1633 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1634
1635 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1636
1637 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001638 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001639 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001640 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001641 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1642 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1643 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1644}
1645
sprang07fb9be2016-02-24 07:55:00 -08001646TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1647 RtcpPacketTypeCounterObserver* proxy =
1648 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1649 RtcpPacketTypeCounter counters;
1650 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1651 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1652 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1653
1654 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1655
1656 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1657 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1658 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1659 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1660 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1661
1662 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1663 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1664
1665 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001666 VideoEncoderConfig config;
1667 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001668 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08001669
asapersson01d70a32016-05-20 06:29:46 -07001670 EXPECT_EQ(1,
1671 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1672 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1673 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1674 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001675 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1676
1677 const int kRate = 60 * 2; // Packets per minute with two streams.
1678
asapersson01d70a32016-05-20 06:29:46 -07001679 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1680 1 * kRate));
1681 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1682 2 * kRate));
1683 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1684 3 * kRate));
1685 EXPECT_EQ(
1686 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1687 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001688
1689 // New start time but same counter values.
1690 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1691 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1692
1693 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1694
1695 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1696 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1697 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1698 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1699 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1700
1701 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1702 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1703
1704 SetUp(); // Reset stats proxy also causes histograms to be reported.
1705
asapersson01d70a32016-05-20 06:29:46 -07001706 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001707 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001708 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001709 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001710 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001711 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1712 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001713 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001714 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1715
asapersson01d70a32016-05-20 06:29:46 -07001716 EXPECT_EQ(1, metrics::NumEvents(
1717 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1718 1 * kRate));
1719 EXPECT_EQ(1, metrics::NumEvents(
1720 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1721 2 * kRate));
1722 EXPECT_EQ(1, metrics::NumEvents(
1723 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1724 3 * kRate));
1725 EXPECT_EQ(1,
1726 metrics::NumEvents(
1727 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1728 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001729}
1730
asaperssona6a699a2016-11-25 03:52:46 -08001731TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1732 statistics_proxy_.reset(
1733 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1734 VideoEncoderConfig::ContentType::kRealtimeVideo));
1735
1736 StreamDataCountersCallback* proxy =
1737 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1738 StreamDataCounters counters;
1739 proxy->DataCountersUpdated(counters, kFirstSsrc);
1740 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1741
1742 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1743 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1744}
1745
1746TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1747 statistics_proxy_.reset(
1748 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1749 VideoEncoderConfig::ContentType::kRealtimeVideo));
1750
1751 StreamDataCountersCallback* proxy =
1752 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001753 StreamDataCounters counters;
1754 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001755
asapersson93e1e232017-02-06 05:18:35 -08001756 const int kMinRequiredPeriodSamples = 8;
1757 const int kPeriodIntervalMs = 2000;
1758 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1759 counters.transmitted.packets += 20;
1760 counters.transmitted.header_bytes += 500;
1761 counters.transmitted.padding_bytes += 1000;
1762 counters.transmitted.payload_bytes += 2000;
1763 counters.retransmitted.packets += 2;
1764 counters.retransmitted.header_bytes += 25;
1765 counters.retransmitted.padding_bytes += 100;
1766 counters.retransmitted.payload_bytes += 250;
1767 counters.fec = counters.retransmitted;
1768 rtx_counters.transmitted = counters.transmitted;
1769 // Advance one interval and update counters.
1770 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1771 proxy->DataCountersUpdated(counters, kFirstSsrc);
1772 proxy->DataCountersUpdated(counters, kSecondSsrc);
1773 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1774 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1775 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1776 }
asaperssona6a699a2016-11-25 03:52:46 -08001777
asaperssona6a699a2016-11-25 03:52:46 -08001778 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001779 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001780 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001781 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1782 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1783 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1784 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1785 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001786 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001787 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1788 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001789 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001790 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1791 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1792 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1793 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1794 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001795 EXPECT_EQ(1,
1796 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001797 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001798 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001799}
1800
Erik Språng22c2b482016-03-01 09:40:42 +01001801TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1802 StreamDataCountersCallback* proxy =
1803 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1804 StreamDataCounters counters;
1805 StreamDataCounters rtx_counters;
1806 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001807
asapersson93e1e232017-02-06 05:18:35 -08001808 const int kMinRequiredPeriodSamples = 8;
1809 const int kPeriodIntervalMs = 2000;
1810 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1811 counters.transmitted.packets += 20;
1812 counters.transmitted.header_bytes += 500;
1813 counters.transmitted.padding_bytes += 1000;
1814 counters.transmitted.payload_bytes += 2000;
1815 counters.retransmitted.packets += 2;
1816 counters.retransmitted.header_bytes += 25;
1817 counters.retransmitted.padding_bytes += 100;
1818 counters.retransmitted.payload_bytes += 250;
1819 counters.fec = counters.retransmitted;
1820 rtx_counters.transmitted = counters.transmitted;
1821 // Advance one interval and update counters.
1822 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1823 proxy->DataCountersUpdated(counters, kFirstSsrc);
1824 proxy->DataCountersUpdated(counters, kSecondSsrc);
1825 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1826 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1827 }
Erik Språng22c2b482016-03-01 09:40:42 +01001828
1829 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001830 VideoEncoderConfig config;
1831 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001832 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01001833
asapersson93e1e232017-02-06 05:18:35 -08001834 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001835 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001836 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1837 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1838 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1839 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1840 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001841 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001842 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1843 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001844 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001845 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1846 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1847 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1848 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1849 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01001850 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07001851 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001852 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001853 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01001854
asapersson93e1e232017-02-06 05:18:35 -08001855 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01001856 // Double counter values, this should result in the same counts as before but
1857 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08001858 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1859 counters.transmitted.packets += 20;
1860 counters.transmitted.header_bytes += 500;
1861 counters.transmitted.padding_bytes += 1000;
1862 counters.transmitted.payload_bytes += 2000;
1863 counters.retransmitted.packets += 2;
1864 counters.retransmitted.header_bytes += 25;
1865 counters.retransmitted.padding_bytes += 100;
1866 counters.retransmitted.payload_bytes += 250;
1867 counters.fec = counters.retransmitted;
1868 rtx_counters.transmitted = counters.transmitted;
1869 // Advance one interval and update counters.
1870 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1871 proxy->DataCountersUpdated(counters, kFirstSsrc);
1872 proxy->DataCountersUpdated(counters, kSecondSsrc);
1873 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1874 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1875 }
Erik Språng22c2b482016-03-01 09:40:42 +01001876
asapersson93e1e232017-02-06 05:18:35 -08001877 // Reset stats proxy also causes histograms to be reported.
1878 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01001879
asapersson93e1e232017-02-06 05:18:35 -08001880 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001881 EXPECT_EQ(1,
1882 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001883 EXPECT_EQ(
1884 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
1885 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1886 EXPECT_EQ(
1887 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
1888 EXPECT_EQ(1, metrics::NumEvents(
1889 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
1890 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001891 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001892 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001893 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001894 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
1895 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001896 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001897 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001898 EXPECT_EQ(1, metrics::NumEvents(
1899 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
1900 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1901 EXPECT_EQ(
1902 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
1903 EXPECT_EQ(1, metrics::NumEvents(
1904 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
1905 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07001906 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001907 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001908 EXPECT_EQ(1,
1909 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001910 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
1911}
Erik Språng22c2b482016-03-01 09:40:42 +01001912
asapersson93e1e232017-02-06 05:18:35 -08001913TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
1914 StreamDataCountersCallback* proxy =
1915 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1916 StreamDataCounters counters;
1917 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01001918
asapersson93e1e232017-02-06 05:18:35 -08001919 const int kMinRequiredPeriodSamples = 8;
1920 const int kPeriodIntervalMs = 2000;
1921 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1922 counters.transmitted.packets += 20;
1923 counters.transmitted.header_bytes += 500;
1924 counters.transmitted.payload_bytes += 2000;
1925 counters.fec = counters.retransmitted;
1926 // Advance one interval and update counters.
1927 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1928 proxy->DataCountersUpdated(counters, kFirstSsrc);
1929 }
1930
1931 // RTX enabled. No data sent over RTX.
1932 statistics_proxy_.reset();
1933 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1934 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
1935}
1936
1937TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
1938 VideoSendStream::Config config(nullptr);
1939 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
1940 statistics_proxy_.reset(new SendStatisticsProxy(
1941 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1942
1943 StreamDataCountersCallback* proxy =
1944 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1945 StreamDataCounters counters;
1946
1947 const int kMinRequiredPeriodSamples = 8;
1948 const int kPeriodIntervalMs = 2000;
1949 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1950 counters.transmitted.packets += 20;
1951 counters.transmitted.header_bytes += 500;
1952 counters.transmitted.payload_bytes += 2000;
1953 counters.fec = counters.retransmitted;
1954 // Advance one interval and update counters.
1955 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1956 proxy->DataCountersUpdated(counters, kFirstSsrc);
1957 }
1958
1959 // RTX not enabled.
1960 statistics_proxy_.reset();
1961 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1962}
1963
1964TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
1965 StreamDataCountersCallback* proxy =
1966 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1967 StreamDataCounters counters;
1968 StreamDataCounters rtx_counters;
1969
1970 const int kMinRequiredPeriodSamples = 8;
1971 const int kPeriodIntervalMs = 2000;
1972 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1973 counters.transmitted.packets += 20;
1974 counters.transmitted.header_bytes += 500;
1975 counters.transmitted.payload_bytes += 2000;
1976 // Advance one interval and update counters.
1977 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1978 proxy->DataCountersUpdated(counters, kFirstSsrc);
1979 }
1980
1981 // FEC enabled. No FEC data sent.
1982 statistics_proxy_.reset();
1983 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1984 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
1985}
1986
1987TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
1988 VideoSendStream::Config config(nullptr);
1989 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
1990 statistics_proxy_.reset(new SendStatisticsProxy(
1991 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1992
1993 StreamDataCountersCallback* proxy =
1994 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1995 StreamDataCounters counters;
1996
1997 const int kMinRequiredPeriodSamples = 8;
1998 const int kPeriodIntervalMs = 2000;
1999 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2000 counters.transmitted.packets += 20;
2001 counters.transmitted.header_bytes += 500;
2002 counters.transmitted.payload_bytes += 2000;
2003 counters.fec = counters.retransmitted;
2004 // Advance one interval and update counters.
2005 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2006 proxy->DataCountersUpdated(counters, kFirstSsrc);
2007 }
2008
2009 // FEC not enabled.
2010 statistics_proxy_.reset();
2011 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002012}
2013
asapersson8d75ac72017-09-15 06:41:15 -07002014TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
2015 const char* kName = "encoderName";
2016 EncodedImage encoded_image;
2017 CodecSpecificInfo codec_info;
2018 codec_info.codec_name = kName;
2019 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2020 EXPECT_STREQ(
2021 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str());
2022}
2023
2024class ForcedFallbackTest : public SendStatisticsProxyTest {
2025 public:
2026 explicit ForcedFallbackTest(const std::string& field_trials)
2027 : SendStatisticsProxyTest(field_trials) {
2028 codec_info_.codecType = kVideoCodecVP8;
2029 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
2030 codec_info_.codecSpecific.VP8.temporalIdx = 0;
2031 codec_info_.codec_name = "fake_codec";
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002032 encoded_image_._encodedWidth = kWidth;
2033 encoded_image_._encodedHeight = kHeight;
asapersson8d75ac72017-09-15 06:41:15 -07002034 }
2035
2036 ~ForcedFallbackTest() override {}
2037
2038 protected:
2039 void InsertEncodedFrames(int num_frames, int interval_ms) {
2040 // First frame is not updating stats, insert initial frame.
2041 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2042 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2043 }
2044 for (int i = 0; i < num_frames; ++i) {
2045 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2046 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2047 }
2048 // Add frame to include last time interval.
2049 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2050 }
2051
2052 EncodedImage encoded_image_;
2053 CodecSpecificInfo codec_info_;
2054 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2055 const int kFrameIntervalMs = 1000;
2056 const int kMinFrames = 20; // Min run time 20 sec.
2057};
2058
2059class ForcedFallbackDisabled : public ForcedFallbackTest {
2060 public:
2061 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002062 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2063 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002064};
2065
2066class ForcedFallbackEnabled : public ForcedFallbackTest {
2067 public:
2068 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002069 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2070 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002071};
2072
2073TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2074 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2075 statistics_proxy_.reset();
2076 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2077 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2078}
2079
2080TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2081 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002082 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002083 statistics_proxy_.reset();
2084 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2085 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2086 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2087 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2088}
2089
2090TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2091 codec_info_.codecType = kVideoCodecVP9;
2092 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2093 statistics_proxy_.reset();
2094 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2095 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2096}
2097
2098TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2099 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2100 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2101 statistics_proxy_.reset();
2102 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2103 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2104}
2105
2106TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
2107 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
2108 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2109 statistics_proxy_.reset();
2110 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2111 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2112}
2113
2114TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2115 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2116 statistics_proxy_.reset();
2117 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2118 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2119}
2120
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002121TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2122 InsertEncodedFrames(1, kFrameIntervalMs);
2123 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2124}
2125
2126TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2127 InsertEncodedFrames(1, kFrameIntervalMs);
2128 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2129}
2130
2131TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
2132 codec_info_.codec_name = "libvpx";
2133 InsertEncodedFrames(1, kFrameIntervalMs);
2134 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2135}
2136
2137TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2138 encoded_image_._encodedWidth = kWidth + 1;
2139 InsertEncodedFrames(1, kFrameIntervalMs);
2140 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2141}
2142
2143TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
2144 codec_info_.codec_name = "libvpx";
2145 InsertEncodedFrames(1, kFrameIntervalMs);
2146 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2147}
2148
2149TEST_F(ForcedFallbackDisabled,
2150 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2151 encoded_image_._encodedWidth = kWidth + 1;
2152 statistics_proxy_->OnMinPixelLimitReached();
2153 InsertEncodedFrames(1, kFrameIntervalMs);
2154 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2155}
2156
asapersson8d75ac72017-09-15 06:41:15 -07002157TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2158 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002159 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002160 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002161 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002162 codec_info_.codec_name = "libvpx";
2163 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002164 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002165
2166 statistics_proxy_.reset();
2167 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2168 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2169 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2170 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2171}
2172
2173TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2174 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2175 const int kMaxFrameDiffMs = 2000;
2176
2177 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2178 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002179 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002180 codec_info_.codec_name = "libvpx";
2181 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002182 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002183 codec_info_.codec_name = "notlibvpx";
2184 InsertEncodedFrames(20, 1000);
2185 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2186 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002187 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002188 codec_info_.codec_name = "notlibvpx2";
2189 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002190 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002191 codec_info_.codec_name = "libvpx";
2192 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002193 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002194
2195 statistics_proxy_.reset();
2196 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2197 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2198 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2199 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2200}
2201
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002202TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2203 encoded_image_._encodedWidth = kWidth + 1;
asapersson8d75ac72017-09-15 06:41:15 -07002204 codec_info_.codec_name = "libvpx";
2205 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2206
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002207 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002208 statistics_proxy_.reset();
2209 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2210 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2211}
2212
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002213TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2214 encoded_image_._encodedWidth = kWidth;
asapersson8d75ac72017-09-15 06:41:15 -07002215 codec_info_.codec_name = "libvpx";
2216 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2217
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002218 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002219 statistics_proxy_.reset();
2220 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2221 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2222}
2223
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002224} // namespace webrtc