blob: 01cbfe8dda44af3715165a87f6ef9ecc3f2ebe7b [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
13#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080014#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000015#include <string>
16#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "system_wrappers/include/metrics.h"
19#include "system_wrappers/include/metrics_default.h"
asapersson8d75ac72017-09-15 06:41:15 -070020#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000022
23namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070024namespace {
25const uint32_t kFirstSsrc = 17;
26const uint32_t kSecondSsrc = 42;
27const uint32_t kFirstRtxSsrc = 18;
28const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080029const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080030const int kFpsPeriodicIntervalMs = 2000;
Åsa Perssonaa329e72017-12-15 15:54:44 +010031const int kPreferredBps = 50000;
asapersson320e45a2016-11-29 01:40:35 -080032const int kWidth = 640;
33const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070034const int kQpIdx0 = 21;
35const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010036const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080037const CodecSpecificInfo kDefaultCodecInfo = []() {
38 CodecSpecificInfo codec_info;
39 codec_info.codecType = kVideoCodecVP8;
40 codec_info.codecSpecific.VP8.simulcastIdx = 0;
41 return codec_info;
42}();
asapersson5265fed2016-04-18 02:58:47 -070043} // namespace
sprang07fb9be2016-02-24 07:55:00 -080044
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000045class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000046 public:
asapersson8d75ac72017-09-15 06:41:15 -070047 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
48 explicit SendStatisticsProxyTest(const std::string& field_trials)
49 : override_field_trials_(field_trials),
50 fake_clock_(1234),
51 config_(GetTestConfig()),
52 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070053 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000054 virtual ~SendStatisticsProxyTest() {}
55
56 protected:
57 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070058 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080059 statistics_proxy_.reset(new SendStatisticsProxy(
60 &fake_clock_, GetTestConfig(),
61 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000062 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070063 for (const auto& ssrc : config_.rtp.ssrcs)
64 expected_.substreams[ssrc].is_rtx = false;
65 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
66 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000067 }
68
69 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070070 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080071 config.rtp.ssrcs.push_back(kFirstSsrc);
72 config.rtp.ssrcs.push_back(kSecondSsrc);
73 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
74 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070075 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000076 return config;
77 }
78
asaperssona6a699a2016-11-25 03:52:46 -080079 VideoSendStream::Config GetTestConfigWithFlexFec() {
80 VideoSendStream::Config config(nullptr);
81 config.rtp.ssrcs.push_back(kFirstSsrc);
82 config.rtp.ssrcs.push_back(kSecondSsrc);
83 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
84 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080085 config.rtp.flexfec.payload_type = 50;
86 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080087 return config;
88 }
89
90 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
91 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
92 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
93 stats.substreams.find(ssrc);
94 EXPECT_NE(it, stats.substreams.end());
95 return it->second;
96 }
97
asapersson66d4b372016-12-19 06:50:53 -080098 void UpdateDataCounters(uint32_t ssrc) {
99 StreamDataCountersCallback* proxy =
100 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
101 StreamDataCounters counters;
102 proxy->DataCountersUpdated(counters, ssrc);
103 }
104
sprang@webrtc.org09315702014-02-07 12:06:29 +0000105 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000106 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
107 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000108 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
Pera48ddb72016-09-29 11:48:50 +0200109 EXPECT_EQ(one.preferred_media_bitrate_bps,
110 other.preferred_media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000111 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000112
113 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000114 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000115 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000116 it != one.substreams.end(); ++it) {
117 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
118 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000119 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000120 const VideoSendStream::StreamStats& a = it->second;
121 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000122
asapersson2e5cfcd2016-08-11 08:41:18 -0700123 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000124 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
125 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000126 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000127 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
128 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000129
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000130 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
131 b.rtp_stats.transmitted.payload_bytes);
132 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
133 b.rtp_stats.transmitted.header_bytes);
134 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
135 b.rtp_stats.transmitted.padding_bytes);
136 EXPECT_EQ(a.rtp_stats.transmitted.packets,
137 b.rtp_stats.transmitted.packets);
138 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
139 b.rtp_stats.retransmitted.packets);
140 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000141
142 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700143 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
144 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
145 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000146 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
147 }
148 }
149
asapersson8d75ac72017-09-15 06:41:15 -0700150 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000151 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800152 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000153 VideoSendStream::Config config_;
154 int avg_delay_ms_;
155 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000156 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000157 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
158 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000159};
160
161TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
162 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700163 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000164 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000165
166 // Add statistics with some arbitrary, but unique, numbers.
167 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700168 ssrc_stats.rtcp_stats.packets_lost = offset;
169 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000170 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
171 ssrc_stats.rtcp_stats.jitter = offset + 3;
172 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
173 }
asapersson35151f32016-05-02 23:44:01 -0700174 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000175 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000176
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000177 // Add statistics with some arbitrary, but unique, numbers.
178 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700179 ssrc_stats.rtcp_stats.packets_lost = offset;
180 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000181 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
182 ssrc_stats.rtcp_stats.jitter = offset + 3;
183 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
184 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000185 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000186 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000187}
188
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000189TEST_F(SendStatisticsProxyTest, Suspended) {
190 // Verify that the value is false by default.
191 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
192
193 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200194 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000195 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
196
197 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200198 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000199 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
200}
201
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000202TEST_F(SendStatisticsProxyTest, FrameCounts) {
203 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700204 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000205 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000206 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
207 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000208 FrameCounts frame_counts;
209 frame_counts.key_frames = offset;
210 frame_counts.delta_frames = offset + 1;
211 stats.frame_counts = frame_counts;
212 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000213 }
asapersson35151f32016-05-02 23:44:01 -0700214 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000215 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000216 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
217 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000218 FrameCounts frame_counts;
219 frame_counts.key_frames = offset;
220 frame_counts.delta_frames = offset + 1;
221 stats.frame_counts = frame_counts;
222 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000223 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000224
225 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000226 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000227}
228
229TEST_F(SendStatisticsProxyTest, DataCounters) {
230 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700231 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000232 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
233 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000234 size_t offset = ssrc * sizeof(StreamDataCounters);
235 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000236 counters.transmitted.payload_bytes = offset;
237 counters.transmitted.header_bytes = offset + 1;
238 counters.fec.packets = offset_uint32 + 2;
239 counters.transmitted.padding_bytes = offset + 3;
240 counters.retransmitted.packets = offset_uint32 + 4;
241 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000242 callback->DataCountersUpdated(counters, ssrc);
243 }
asapersson35151f32016-05-02 23:44:01 -0700244 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000245 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
246 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000247 size_t offset = ssrc * sizeof(StreamDataCounters);
248 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000249 counters.transmitted.payload_bytes = offset;
250 counters.transmitted.header_bytes = offset + 1;
251 counters.fec.packets = offset_uint32 + 2;
252 counters.transmitted.padding_bytes = offset + 3;
253 counters.retransmitted.packets = offset_uint32 + 4;
254 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000255 callback->DataCountersUpdated(counters, ssrc);
256 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000257
258 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000259 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000260}
261
262TEST_F(SendStatisticsProxyTest, Bitrate) {
263 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700264 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700265 uint32_t total;
266 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000267 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700268 total = ssrc;
269 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000270 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700271 expected_.substreams[ssrc].total_bitrate_bps = total;
272 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000273 }
asapersson35151f32016-05-02 23:44:01 -0700274 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700275 uint32_t total;
276 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000277 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700278 total = ssrc;
279 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000280 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700281 expected_.substreams[ssrc].total_bitrate_bps = total;
282 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000283 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000284
285 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000286 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000287}
288
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000289TEST_F(SendStatisticsProxyTest, SendSideDelay) {
290 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700291 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000292 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
293 // stream.
294 int avg_delay_ms = ssrc;
295 int max_delay_ms = ssrc + 1;
296 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
297 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
298 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
299 }
asapersson35151f32016-05-02 23:44:01 -0700300 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000301 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
302 // stream.
303 int avg_delay_ms = ssrc;
304 int max_delay_ms = ssrc + 1;
305 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
306 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
307 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
308 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000309 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000310 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000311}
312
Peter Boströme4499152016-02-05 11:13:28 +0100313TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800314 const int kEncodeTimeMs = 11;
Peter Boströme4499152016-02-05 11:13:28 +0100315 CpuOveruseMetrics metrics;
316 metrics.encode_usage_percent = 80;
317 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs, metrics);
asapersson1aa420b2015-12-07 03:12:22 -0800318
319 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
320 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Peter Boströme4499152016-02-05 11:13:28 +0100321 EXPECT_EQ(metrics.encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800322}
323
Pera48ddb72016-09-29 11:48:50 +0200324TEST_F(SendStatisticsProxyTest, OnEncoderReconfiguredChangePreferredBitrate) {
325 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
326 EXPECT_EQ(0, stats.preferred_media_bitrate_bps);
Pera48ddb72016-09-29 11:48:50 +0200327
328 VideoEncoderConfig config;
Åsa Perssonaa329e72017-12-15 15:54:44 +0100329 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
Pera48ddb72016-09-29 11:48:50 +0200330 stats = statistics_proxy_->GetStats();
Åsa Perssonaa329e72017-12-15 15:54:44 +0100331 EXPECT_EQ(kPreferredBps, stats.preferred_media_bitrate_bps);
Pera48ddb72016-09-29 11:48:50 +0200332}
333
sakal43536c32016-10-24 01:46:43 -0700334TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
335 EncodedImage encoded_image;
336 CodecSpecificInfo codec_info;
337 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
338 for (uint32_t i = 1; i <= 3; ++i) {
339 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
340 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
341 }
342}
343
sakal87da4042016-10-31 06:53:47 -0700344TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
345 EncodedImage encoded_image;
346 CodecSpecificInfo codec_info;
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100347 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700348 encoded_image.qp_ = 3;
349 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100350 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700351 encoded_image.qp_ = 127;
352 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100353 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700354}
355
356TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
357 EncodedImage encoded_image;
358 CodecSpecificInfo codec_info;
359 encoded_image.qp_ = -1;
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100360 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700361 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100362 EXPECT_EQ(rtc::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700363}
364
asapersson09f05612017-05-15 23:40:18 -0700365TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700366 VideoStreamEncoder::AdaptCounts cpu_counts;
367 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700368 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700369 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700370 cpu_counts.fps = 1;
371 cpu_counts.resolution = 0;
372 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
373 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700374 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700375 cpu_counts.fps = 0;
376 cpu_counts.resolution = 1;
377 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
378 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700379 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700380 cpu_counts.fps = 1;
381 cpu_counts.resolution = -1;
382 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
383 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700384 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700385 cpu_counts.fps = -1;
386 cpu_counts.resolution = -1;
387 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
388 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
389 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
390}
391
392TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700393 VideoStreamEncoder::AdaptCounts cpu_counts;
394 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700395 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
396 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
397 quality_counts.fps = 1;
398 quality_counts.resolution = 0;
399 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
400 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
401 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
402 quality_counts.fps = 0;
403 quality_counts.resolution = 1;
404 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
405 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
406 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
407 quality_counts.fps = 1;
408 quality_counts.resolution = -1;
409 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
410 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
411 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
412 quality_counts.fps = -1;
413 quality_counts.resolution = -1;
414 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
415 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
416 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
417}
418
419TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700420 VideoStreamEncoder::AdaptCounts cpu_counts;
421 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700422 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
423
asapersson09f05612017-05-15 23:40:18 -0700424 cpu_counts.resolution = 1;
425 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
426 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700427 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
428 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
429
asapersson09f05612017-05-15 23:40:18 -0700430 cpu_counts.resolution = 2;
431 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
432 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
433 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700434 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700435 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700436}
437
asapersson09f05612017-05-15 23:40:18 -0700438TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700439 VideoStreamEncoder::AdaptCounts cpu_counts;
440 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700441 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
442
asapersson09f05612017-05-15 23:40:18 -0700443 quality_counts.fps = 1;
444 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
445 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
446 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700447 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
448
asapersson09f05612017-05-15 23:40:18 -0700449 quality_counts.fps = 0;
450 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
451 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700452 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700453 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
454 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700455}
456
asapersson09f05612017-05-15 23:40:18 -0700457TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700458 // First RTP packet sent.
459 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700460 // Min runtime has passed.
461 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
462 statistics_proxy_.reset();
463 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
464 EXPECT_EQ(0,
465 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
466}
467
468TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700469 // First RTP packet sent.
470 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700471 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700472 VideoStreamEncoder::AdaptCounts cpu_counts;
473 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700474 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700475 // Min runtime has not passed.
476 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
477 statistics_proxy_.reset();
478 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
479 EXPECT_EQ(0,
480 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
481}
482
asapersson09f05612017-05-15 23:40:18 -0700483TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700484 // First RTP packet sent.
485 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700486 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700487 VideoStreamEncoder::AdaptCounts cpu_counts;
488 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700489 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700490 // Min runtime has passed.
491 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
492 statistics_proxy_.reset();
493 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
494 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700495 EXPECT_EQ(1,
496 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
497 EXPECT_EQ(
498 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
499}
500
501TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700502 // First RTP packet sent.
503 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700504 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700505 VideoStreamEncoder::AdaptCounts cpu_counts;
506 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700507 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700508 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson09f05612017-05-15 23:40:18 -0700509 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700510 fake_clock_.AdvanceTimeMilliseconds(10000);
511 statistics_proxy_.reset();
512 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
513 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
514}
515
Åsa Persson875841d2018-01-08 08:49:53 +0100516TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
517 // First RTP packet sent.
518 UpdateDataCounters(kFirstSsrc);
519 // Enable adaptation.
520 VideoStreamEncoder::AdaptCounts cpu_counts;
521 VideoStreamEncoder::AdaptCounts quality_counts;
522 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
523 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
524 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
525 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
526 fake_clock_.AdvanceTimeMilliseconds(10000);
527 statistics_proxy_.reset();
528 EXPECT_EQ(1,
529 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
530 EXPECT_EQ(
531 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
532}
533
534TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
535 // First RTP packet sent.
536 UpdateDataCounters(kFirstSsrc);
537 // Enable adaptation.
538 VideoStreamEncoder::AdaptCounts cpu_counts;
539 VideoStreamEncoder::AdaptCounts quality_counts;
540 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
541 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
542 quality_counts.resolution = 1;
543 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
544 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
545 quality_counts.resolution = 2;
546 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
547 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
548 quality_counts.resolution = 3;
549 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
550 fake_clock_.AdvanceTimeMilliseconds(10000);
551 statistics_proxy_.reset();
552 EXPECT_EQ(1,
553 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
554 EXPECT_EQ(
555 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
556}
557
558TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
559 // First RTP packet sent.
560 UpdateDataCounters(kFirstSsrc);
561 // Enable adaptation.
562 VideoStreamEncoder::AdaptCounts cpu_counts;
563 VideoStreamEncoder::AdaptCounts quality_counts;
564 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
565 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
566 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
567 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
568 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
569 fake_clock_.AdvanceTimeMilliseconds(10000);
570 statistics_proxy_.reset();
571 EXPECT_EQ(1,
572 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
573 EXPECT_EQ(
574 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
575}
576
577TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
578 // First RTP packet sent.
579 UpdateDataCounters(kFirstSsrc);
580 // Enable adaptation.
581 VideoStreamEncoder::AdaptCounts cpu_counts;
582 VideoStreamEncoder::AdaptCounts quality_counts;
583 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
584 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
585 quality_counts.resolution = 1;
586 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
587 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
588 quality_counts.resolution = 2;
589 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
590 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
591 quality_counts.resolution = 3;
592 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
593 quality_counts.fps = 1;
594 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
595 quality_counts.fps = 0;
596 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
597 quality_counts.resolution = 2; // Initial resolution up.
598 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
599 quality_counts.resolution = 1; // Initial resolution up.
600 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
601 quality_counts.resolution = 0;
602 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
603
604 fake_clock_.AdvanceTimeMilliseconds(10000);
605 statistics_proxy_.reset();
606 EXPECT_EQ(1,
607 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
608 EXPECT_EQ(
609 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
610}
611
asapersson6eca98b2017-04-04 23:40:50 -0700612TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700613 // First RTP packet sent.
614 UpdateDataCounters(kFirstSsrc);
615
asapersson09f05612017-05-15 23:40:18 -0700616 // Disable quality adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700617 VideoStreamEncoder::AdaptCounts cpu_counts;
618 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700619 quality_counts.fps = -1;
620 quality_counts.resolution = -1;
621 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700622 fake_clock_.AdvanceTimeMilliseconds(10000);
623
asapersson09f05612017-05-15 23:40:18 -0700624 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700625 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700626 quality_counts.fps = 0;
627 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700628 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700629 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700630 fake_clock_.AdvanceTimeMilliseconds(9000);
asapersson09f05612017-05-15 23:40:18 -0700631 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700632 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700633 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700634
asapersson09f05612017-05-15 23:40:18 -0700635 // Disable quality adaptation.
636 quality_counts.fps = -1;
637 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700638 fake_clock_.AdvanceTimeMilliseconds(30000);
639
asapersson09f05612017-05-15 23:40:18 -0700640 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700641 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700642 quality_counts.resolution = 0;
643 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
644 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700645 fake_clock_.AdvanceTimeMilliseconds(10000);
646
asapersson09f05612017-05-15 23:40:18 -0700647 // Disable quality adaptation.
648 quality_counts.resolution = -1;
649 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700650 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700651 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700652 fake_clock_.AdvanceTimeMilliseconds(20000);
653
asapersson0944a802017-04-07 00:57:58 -0700654 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700655 statistics_proxy_.reset();
656 EXPECT_EQ(1,
657 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
658 EXPECT_EQ(
659 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
660}
661
asapersson0944a802017-04-07 00:57:58 -0700662TEST_F(SendStatisticsProxyTest,
663 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
664 // First RTP packet sent.
665 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700666
asapersson0944a802017-04-07 00:57:58 -0700667 // Suspend and resume video.
668 statistics_proxy_->OnSuspendChange(true);
669 fake_clock_.AdvanceTimeMilliseconds(5000);
670 statistics_proxy_->OnSuspendChange(false);
671
672 // Min runtime has passed but scaling not enabled.
673 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
674 statistics_proxy_.reset();
675 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
676 EXPECT_EQ(0,
677 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
678}
679
680TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
681 // First RTP packet sent.
682 UpdateDataCounters(kFirstSsrc);
683
asapersson09f05612017-05-15 23:40:18 -0700684 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700685 VideoStreamEncoder::AdaptCounts cpu_counts;
686 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700687 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700688 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700689 fake_clock_.AdvanceTimeMilliseconds(20000);
asapersson09f05612017-05-15 23:40:18 -0700690 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
691 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700692
693 // Suspend and resume video.
694 statistics_proxy_->OnSuspendChange(true);
695 fake_clock_.AdvanceTimeMilliseconds(30000);
696 statistics_proxy_->OnSuspendChange(false);
697
698 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700699 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700700 fake_clock_.AdvanceTimeMilliseconds(10000);
701
702 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
703 statistics_proxy_.reset();
704 EXPECT_EQ(1,
705 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
706 EXPECT_EQ(
707 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
708}
709
710TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
711 // First RTP packet sent.
712 UpdateDataCounters(kFirstSsrc);
713
714 // Video not suspended.
715 statistics_proxy_->OnSuspendChange(false);
716 fake_clock_.AdvanceTimeMilliseconds(30000);
717
asapersson09f05612017-05-15 23:40:18 -0700718 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700719 VideoStreamEncoder::AdaptCounts cpu_counts;
720 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700721 // Adapt changes: 1, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700722 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700723 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700724 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700725
726 // Video not suspended, stats time already started.
727 statistics_proxy_->OnSuspendChange(false);
728 fake_clock_.AdvanceTimeMilliseconds(10000);
729
asapersson09f05612017-05-15 23:40:18 -0700730 // Disable adaptation.
731 cpu_counts.fps = -1;
732 cpu_counts.resolution = -1;
733 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700734 fake_clock_.AdvanceTimeMilliseconds(30000);
735
736 // Suspend and resume video, stats time not started when scaling not enabled.
737 statistics_proxy_->OnSuspendChange(true);
738 fake_clock_.AdvanceTimeMilliseconds(30000);
739 statistics_proxy_->OnSuspendChange(false);
740 fake_clock_.AdvanceTimeMilliseconds(30000);
741
asapersson09f05612017-05-15 23:40:18 -0700742 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700743 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700744 cpu_counts.fps = 0;
745 cpu_counts.resolution = 0;
746 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700747 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700748 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700749
750 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
751 statistics_proxy_.reset();
752 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
753 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
754}
755
756TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
757 // First RTP packet sent.
758 UpdateDataCounters(kFirstSsrc);
759
760 // Video suspended.
761 statistics_proxy_->OnSuspendChange(true);
762
asapersson09f05612017-05-15 23:40:18 -0700763 // Enable adaptation, stats time not started when suspended.
mflodmancc3d4422017-08-03 08:27:51 -0700764 VideoStreamEncoder::AdaptCounts cpu_counts;
765 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700766 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700767 fake_clock_.AdvanceTimeMilliseconds(10000);
768
769 // Resume video, stats time started.
770 // Adapt changes: 1, elapsed time: 10 sec.
771 statistics_proxy_->OnSuspendChange(false);
772 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700773 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700774
775 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
776 statistics_proxy_.reset();
777 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
778 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
779}
780
781TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700782 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700783 // Elapsed time before first packet is sent should be excluded.
mflodmancc3d4422017-08-03 08:27:51 -0700784 VideoStreamEncoder::AdaptCounts cpu_counts;
785 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700786 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700787 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700788 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700789
asapersson0944a802017-04-07 00:57:58 -0700790 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700791 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700792 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700793 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700794
asapersson0944a802017-04-07 00:57:58 -0700795 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700796 statistics_proxy_.reset();
797 EXPECT_EQ(1,
798 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
799 EXPECT_EQ(
800 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
801}
802
803TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700804 // Enable and disable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700805 VideoStreamEncoder::AdaptCounts cpu_counts;
806 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700807 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700808 fake_clock_.AdvanceTimeMilliseconds(60000);
asapersson09f05612017-05-15 23:40:18 -0700809 cpu_counts.fps = -1;
810 cpu_counts.resolution = -1;
811 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700812
813 // Send first packet, scaling disabled.
814 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700815 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700816 fake_clock_.AdvanceTimeMilliseconds(60000);
817
asapersson09f05612017-05-15 23:40:18 -0700818 // Enable adaptation.
819 cpu_counts.resolution = 0;
820 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700821 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700822 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700823
asapersson0944a802017-04-07 00:57:58 -0700824 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700825 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700826 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700827
asapersson0944a802017-04-07 00:57:58 -0700828 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700829 statistics_proxy_.reset();
830 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
831 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
832}
833
834TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700835 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700836 UpdateDataCounters(kFirstSsrc);
mflodmancc3d4422017-08-03 08:27:51 -0700837 VideoStreamEncoder::AdaptCounts cpu_counts;
838 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700839 quality_counts.fps = -1;
840 quality_counts.resolution = -1;
841 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700842
asapersson0944a802017-04-07 00:57:58 -0700843 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
asapersson09f05612017-05-15 23:40:18 -0700844 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700845 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700846 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700847 fake_clock_.AdvanceTimeMilliseconds(9000);
848
849 // Switch content type, real-time stats should be updated.
850 VideoEncoderConfig config;
851 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +0100852 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson6eca98b2017-04-04 23:40:50 -0700853 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
854 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
855 EXPECT_EQ(0,
856 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
857
asapersson0944a802017-04-07 00:57:58 -0700858 // First RTP packet sent, scaling enabled.
859 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700860 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700861
asapersson0944a802017-04-07 00:57:58 -0700862 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
asapersson09f05612017-05-15 23:40:18 -0700863 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
864 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
865 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
866 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700867 fake_clock_.AdvanceTimeMilliseconds(120000);
868
869 statistics_proxy_.reset();
870 EXPECT_EQ(1, metrics::NumSamples(
871 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
872 EXPECT_EQ(1, metrics::NumEvents(
873 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
874 EXPECT_EQ(0, metrics::NumSamples(
875 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
876}
877
asapersson59bac1a2016-01-07 23:36:00 -0800878TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -0700879 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -0800880 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
881
Pera48ddb72016-09-29 11:48:50 +0200882 // No switch, stats should not be updated.
883 VideoEncoderConfig config;
884 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Perssonaa329e72017-12-15 15:54:44 +0100885 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson01d70a32016-05-20 06:29:46 -0700886 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800887
888 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +0200889 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +0100890 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
asapersson01d70a32016-05-20 06:29:46 -0700891 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800892}
893
asapersson320e45a2016-11-29 01:40:35 -0800894TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
895 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
896 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -0700897
asapersson320e45a2016-11-29 01:40:35 -0800898 statistics_proxy_.reset();
899 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
900 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
901 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
902 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
903}
904
905TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +0200906 const int64_t kMaxEncodedFrameWindowMs = 800;
907 const int kFps = 20;
908 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
909 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
910 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -0800911 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +0200912
913 // Not enough samples, stats should not be updated.
914 for (int i = 0; i < kMinSamples - 1; ++i) {
915 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
916 ++encoded_image._timeStamp;
asapersson320e45a2016-11-29 01:40:35 -0800917 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
918 }
Åsa Persson0122e842017-10-16 12:19:23 +0200919 SetUp(); // Reset stats proxy also causes histograms to be reported.
920 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
921 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
922
923 // Enough samples, max resolution per frame should be reported.
924 encoded_image._timeStamp = 0xfffffff0; // Will wrap.
925 for (int i = 0; i < kMinSamples; ++i) {
926 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
927 ++encoded_image._timeStamp;
928 encoded_image._encodedWidth = kWidth;
929 encoded_image._encodedHeight = kHeight;
930 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
931 encoded_image._encodedWidth = kWidth / 2;
932 encoded_image._encodedHeight = kHeight / 2;
933 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
934 }
935
asapersson320e45a2016-11-29 01:40:35 -0800936 statistics_proxy_.reset();
937 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
938 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
939 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
940 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
941}
942
943TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
944 const int kFps = 20;
945 const int kMinPeriodicSamples = 6;
946 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
947 for (int i = 0; i <= frames; ++i) {
948 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
949 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
950 }
951 statistics_proxy_.reset();
952 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
953 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
954}
955
956TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
957 EncodedImage encoded_image;
958 const int kFps = 20;
959 const int kMinPeriodicSamples = 6;
960 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +0200961 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -0800962 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +0200963 ++encoded_image._timeStamp;
964 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
965 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -0800966 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
967 }
968 statistics_proxy_.reset();
969 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
970 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
971}
972
973TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
974 const int kFps = 20;
975 const int kSuspendTimeMs = 10000;
976 const int kMinPeriodicSamples = 6;
977 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
978 for (int i = 0; i < frames; ++i) {
979 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
980 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
981 }
982 // Suspend.
983 statistics_proxy_->OnSuspendChange(true);
984 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
985
986 for (int i = 0; i < frames; ++i) {
987 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
988 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
989 }
990 // Suspended time interval should not affect the framerate.
991 statistics_proxy_.reset();
992 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
993 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
994}
995
996TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
997 EncodedImage encoded_image;
998 const int kFps = 20;
999 const int kSuspendTimeMs = 10000;
1000 const int kMinPeriodicSamples = 6;
1001 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001002 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001003 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1004 encoded_image._timeStamp = i + 1;
1005 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1006 }
1007 // Suspend.
1008 statistics_proxy_->OnSuspendChange(true);
1009 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1010
Åsa Persson0122e842017-10-16 12:19:23 +02001011 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001012 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1013 encoded_image._timeStamp = i + 1;
1014 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1015 }
1016 // Suspended time interval should not affect the framerate.
1017 statistics_proxy_.reset();
1018 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1019 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1020}
1021
asaperssonf4e44af2017-04-19 02:01:06 -07001022TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -07001023 VideoStreamEncoder::AdaptCounts cpu_counts;
1024 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001025 cpu_counts.resolution = -1;
1026 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001027
1028 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1029 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1030
1031 statistics_proxy_.reset();
1032 EXPECT_EQ(0,
1033 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1034}
1035
1036TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
mflodmancc3d4422017-08-03 08:27:51 -07001037 VideoStreamEncoder::AdaptCounts cpu_counts;
1038 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001039 cpu_counts.resolution = 0;
1040 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001041
perkj803d97f2016-11-01 11:45:46 -07001042 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1043 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1044
asapersson09f05612017-05-15 23:40:18 -07001045 cpu_counts.resolution = 1;
1046 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001047
1048 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1049 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1050
1051 statistics_proxy_.reset();
1052 EXPECT_EQ(1,
1053 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1054 EXPECT_EQ(
1055 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1056}
1057
asapersson4374a092016-07-27 00:39:09 -07001058TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1059 const int64_t kTimeSec = 3;
1060 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1061 statistics_proxy_.reset();
1062 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1063 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
1064 kTimeSec));
1065}
1066
1067TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1068 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1069 statistics_proxy_.reset();
1070 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1071}
1072
asapersson66d4b372016-12-19 06:50:53 -08001073TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1074 // First RTP packet sent.
1075 UpdateDataCounters(kFirstSsrc);
1076
1077 // Min runtime has passed.
1078 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1079 statistics_proxy_.reset();
1080 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1081 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1082}
1083
1084TEST_F(SendStatisticsProxyTest,
1085 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1086 // First RTP packet sent.
1087 UpdateDataCounters(kFirstSsrc);
1088
1089 // Min runtime has not passed.
1090 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1091 statistics_proxy_.reset();
1092 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1093 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1094}
1095
1096TEST_F(SendStatisticsProxyTest,
1097 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1098 // First RTP packet not sent.
1099 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1100 statistics_proxy_.reset();
1101 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1102}
1103
1104TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1105 // First RTP packet sent and min runtime passed.
1106 UpdateDataCounters(kFirstSsrc);
1107
1108 // No change. Video: 10000 ms, paused: 0 ms (0%).
1109 statistics_proxy_->OnSetEncoderTargetRate(50000);
1110 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1111 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1112
1113 statistics_proxy_.reset();
1114 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1115 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1116 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1117 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1118}
1119
1120TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1121 // First RTP packet sent and min runtime passed.
1122 UpdateDataCounters(kFirstSsrc);
1123
1124 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1125 statistics_proxy_->OnSetEncoderTargetRate(50000);
1126 fake_clock_.AdvanceTimeMilliseconds(7000);
1127 statistics_proxy_->OnSetEncoderTargetRate(0);
1128 fake_clock_.AdvanceTimeMilliseconds(3000);
1129 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1130
1131 statistics_proxy_.reset();
1132 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1133 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1134 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1135 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1136}
1137
1138TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1139 // First RTP packet sent.
1140 UpdateDataCounters(kFirstSsrc);
1141
1142 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1143 statistics_proxy_->OnSetEncoderTargetRate(0);
1144 fake_clock_.AdvanceTimeMilliseconds(1000);
1145 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1146 fake_clock_.AdvanceTimeMilliseconds(7000);
1147 statistics_proxy_->OnSetEncoderTargetRate(60000);
1148 fake_clock_.AdvanceTimeMilliseconds(3000);
1149 statistics_proxy_->OnSetEncoderTargetRate(0);
1150 fake_clock_.AdvanceTimeMilliseconds(250);
1151 statistics_proxy_->OnSetEncoderTargetRate(0);
1152 fake_clock_.AdvanceTimeMilliseconds(750);
1153 statistics_proxy_->OnSetEncoderTargetRate(60000);
1154 fake_clock_.AdvanceTimeMilliseconds(5000);
1155 statistics_proxy_->OnSetEncoderTargetRate(50000);
1156 fake_clock_.AdvanceTimeMilliseconds(4000);
1157 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1158
1159 statistics_proxy_.reset();
1160 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1161 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1162 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1163 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1164}
1165
1166TEST_F(SendStatisticsProxyTest,
1167 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1168 // First RTP packet sent.
1169 UpdateDataCounters(kFirstSsrc);
1170 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1171
1172 // Min runtime has not passed.
1173 statistics_proxy_->OnSetEncoderTargetRate(50000);
1174 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1175 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1176
1177 statistics_proxy_.reset();
1178 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1179}
1180
asapersson118ef002016-03-31 00:00:19 -07001181TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001182 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001183 CodecSpecificInfo codec_info;
1184 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001185
perkj803d97f2016-11-01 11:45:46 -07001186 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001187 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001188 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001189 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1190 codec_info.codecSpecific.VP8.simulcastIdx = 1;
asapersson118ef002016-03-31 00:00:19 -07001191 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001192 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001193 }
1194 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001195 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1196 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1197 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1198 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001199}
1200
1201TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1202 VideoSendStream::Config config(nullptr);
1203 config.rtp.ssrcs.push_back(kFirstSsrc);
1204 statistics_proxy_.reset(new SendStatisticsProxy(
1205 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1206
asapersson118ef002016-03-31 00:00:19 -07001207 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001208 CodecSpecificInfo codec_info;
1209 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001210
perkj803d97f2016-11-01 11:45:46 -07001211 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001212 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001213 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001214 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001215 }
1216 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001217 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1218 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001219}
1220
asapersson5265fed2016-04-18 02:58:47 -07001221TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001222 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001223 CodecSpecificInfo codec_info;
1224 codec_info.codecType = kVideoCodecVP9;
1225 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001226
perkj803d97f2016-11-01 11:45:46 -07001227 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001228 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001229 codec_info.codecSpecific.VP9.spatial_idx = 0;
1230 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001231 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001232 codec_info.codecSpecific.VP9.spatial_idx = 1;
1233 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001234 }
1235 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001236 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1237 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1238 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1239 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001240}
1241
1242TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1243 VideoSendStream::Config config(nullptr);
1244 config.rtp.ssrcs.push_back(kFirstSsrc);
1245 statistics_proxy_.reset(new SendStatisticsProxy(
1246 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1247
asapersson5265fed2016-04-18 02:58:47 -07001248 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001249 CodecSpecificInfo codec_info;
1250 codec_info.codecType = kVideoCodecVP9;
1251 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001252
perkj803d97f2016-11-01 11:45:46 -07001253 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001254 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001255 codec_info.codecSpecific.VP9.spatial_idx = 0;
1256 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001257 }
1258 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001259 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1260 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001261}
1262
asapersson827cab32016-11-02 09:08:47 -07001263TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1264 EncodedImage encoded_image;
1265 CodecSpecificInfo codec_info;
1266 codec_info.codecType = kVideoCodecH264;
1267
1268 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1269 encoded_image.qp_ = kQpIdx0;
1270 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1271 }
1272 statistics_proxy_.reset();
1273 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264"));
1274 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264", kQpIdx0));
1275}
1276
asapersson4ee70462016-10-31 04:05:12 -07001277TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001278 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1279 // Configure one stream.
1280 VideoEncoderConfig config;
1281 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1282 VideoStream stream1;
1283 stream1.width = kWidth;
1284 stream1.height = kHeight;
1285 statistics_proxy_->OnEncoderReconfigured(config, {stream1}, kPreferredBps);
1286
1287 const int64_t kMaxEncodedFrameWindowMs = 800;
1288 const int kFps = 20;
1289 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1290 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1291 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1292
1293 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001294 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001295 encoded_image._encodedWidth = kWidth;
1296 encoded_image._encodedHeight = kHeight;
1297 for (int i = 0; i < kMinSamples; ++i) {
1298 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1299 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001300 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001301 }
asapersson4ee70462016-10-31 04:05:12 -07001302
1303 // Histograms are updated when the statistics_proxy_ is deleted.
1304 statistics_proxy_.reset();
1305 EXPECT_EQ(0, metrics::NumSamples(
1306 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1307 EXPECT_EQ(0, metrics::NumSamples(
1308 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1309}
1310
1311TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001312 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1313 // Configure two streams.
1314 VideoEncoderConfig config;
1315 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1316 VideoStream stream1;
1317 stream1.width = kWidth / 2;
1318 stream1.height = kHeight / 2;
1319 VideoStream stream2;
1320 stream2.width = kWidth;
1321 stream2.height = kHeight;
1322 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1323 kPreferredBps);
1324
1325 const int64_t kMaxEncodedFrameWindowMs = 800;
1326 const int kFps = 20;
1327 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1328 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1329 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1330
1331 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001332 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001333 for (int i = 0; i < kMinSamples; ++i) {
1334 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1335 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1336 encoded_image._encodedWidth = kWidth;
1337 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001338 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001339 encoded_image._encodedWidth = kWidth / 2;
1340 encoded_image._encodedHeight = kHeight / 2;
1341 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1342 }
asapersson4ee70462016-10-31 04:05:12 -07001343
1344 // Histograms are updated when the statistics_proxy_ is deleted.
1345 statistics_proxy_.reset();
1346 EXPECT_EQ(1, metrics::NumSamples(
1347 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1348 EXPECT_EQ(1, metrics::NumEvents(
1349 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1350 // No resolution disabled.
1351 EXPECT_EQ(0, metrics::NumSamples(
1352 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1353}
1354
1355TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001356 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1357 // Configure two streams.
1358 VideoEncoderConfig config;
1359 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1360 VideoStream stream1;
1361 stream1.width = kWidth / 2;
1362 stream1.height = kHeight / 2;
1363 VideoStream stream2;
1364 stream2.width = kWidth;
1365 stream2.height = kHeight;
1366 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1367 kPreferredBps);
1368
1369 const int64_t kMaxEncodedFrameWindowMs = 800;
1370 const int kFps = 20;
1371 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1372 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1373 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1374
1375 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001376 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001377 encoded_image._encodedWidth = kWidth / 2;
1378 encoded_image._encodedHeight = kHeight / 2;
1379 for (int i = 0; i < kMinSamples; ++i) {
1380 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1381 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001382 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001383 }
asapersson4ee70462016-10-31 04:05:12 -07001384
1385 // Histograms are updated when the statistics_proxy_ is deleted.
1386 statistics_proxy_.reset();
1387 EXPECT_EQ(1, metrics::NumSamples(
1388 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1389 EXPECT_EQ(1, metrics::NumEvents(
1390 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001391 // One resolution disabled.
asapersson4ee70462016-10-31 04:05:12 -07001392 EXPECT_EQ(1, metrics::NumSamples(
1393 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001394 EXPECT_EQ(1, metrics::NumEvents(
1395 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
asapersson4ee70462016-10-31 04:05:12 -07001396}
1397
1398TEST_F(SendStatisticsProxyTest,
1399 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -07001400 VideoStreamEncoder::AdaptCounts cpu_counts;
1401 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001402 quality_counts.resolution = -1;
1403 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001404 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001405 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001406 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001407
1408 // Histograms are updated when the statistics_proxy_ is deleted.
1409 statistics_proxy_.reset();
1410 EXPECT_EQ(
1411 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1412 EXPECT_EQ(0, metrics::NumSamples(
1413 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1414}
1415
1416TEST_F(SendStatisticsProxyTest,
1417 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
mflodmancc3d4422017-08-03 08:27:51 -07001418 VideoStreamEncoder::AdaptCounts cpu_counts;
1419 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001420 quality_counts.resolution = 0;
1421 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001422 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001423 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001424 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001425
1426 // Histograms are updated when the statistics_proxy_ is deleted.
1427 statistics_proxy_.reset();
1428 EXPECT_EQ(
1429 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1430 EXPECT_EQ(1, metrics::NumEvents(
1431 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1432 // No resolution downscale.
1433 EXPECT_EQ(0, metrics::NumSamples(
1434 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1435}
1436
1437TEST_F(SendStatisticsProxyTest,
1438 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1439 const int kDownscales = 2;
mflodmancc3d4422017-08-03 08:27:51 -07001440 VideoStreamEncoder::AdaptCounts cpu_counts;
1441 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001442 quality_counts.resolution = kDownscales;
1443 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001444 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001445 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001446 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001447 // Histograms are updated when the statistics_proxy_ is deleted.
1448 statistics_proxy_.reset();
1449 EXPECT_EQ(
1450 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1451 EXPECT_EQ(1, metrics::NumEvents(
1452 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1453 // Resolution downscales.
1454 EXPECT_EQ(1, metrics::NumSamples(
1455 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1456 EXPECT_EQ(
1457 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1458 kDownscales));
1459}
1460
1461TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1462 // Initially false.
1463 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01001464
Åsa Perssonaa329e72017-12-15 15:54:44 +01001465 // Configure two streams.
1466 VideoEncoderConfig config;
1467 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1468 VideoStream stream1;
1469 stream1.width = kWidth / 2;
1470 stream1.height = kHeight / 2;
1471 VideoStream stream2;
1472 stream2.width = kWidth;
1473 stream2.height = kHeight;
1474 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
1475 kPreferredBps);
1476
1477 const int64_t kMaxEncodedFrameWindowMs = 800;
1478 const int kFps = 20;
1479 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1480 kFps * kMaxEncodedFrameWindowMs / 1000;
1481
1482 // One stream encoded.
1483 EncodedImage encoded_image;
1484 encoded_image._encodedWidth = kWidth / 2;
1485 encoded_image._encodedHeight = kHeight / 2;
1486 for (int i = 0; i < kMinSamples; ++i) {
1487 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1488 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1489 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1490 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1491 }
1492
1493 // First frame removed from EncodedFrameMap, stats updated.
1494 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1495 ++encoded_image._timeStamp;
kthelgason0cd27ba2016-12-19 06:32:16 -08001496 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1497 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1498
Åsa Perssonaa329e72017-12-15 15:54:44 +01001499 // Two streams encoded.
1500 for (int i = 0; i < kMinSamples; ++i) {
1501 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1502 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
1503 encoded_image._encodedWidth = kWidth;
1504 encoded_image._encodedHeight = kHeight;
1505 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1506 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1507 encoded_image._encodedWidth = kWidth / 2;
1508 encoded_image._encodedHeight = kHeight / 2;
1509 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1510 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1511 }
1512
1513 // First frame with two streams removed, expect no resolution limit.
1514 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1515 encoded_image._timeStamp += (kRtpClockRateHz / kFps);
asapersson4ee70462016-10-31 04:05:12 -07001516 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1517 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001518
1519 // Resolution scaled due to quality.
mflodmancc3d4422017-08-03 08:27:51 -07001520 VideoStreamEncoder::AdaptCounts cpu_counts;
1521 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001522 quality_counts.resolution = 1;
1523 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001524 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1525 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1526}
1527
asapersson66d4b372016-12-19 06:50:53 -08001528TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1529 // Initially zero.
1530 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1531
1532 const int kBitrate = 100000;
1533 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1534 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1535
1536 statistics_proxy_->OnSetEncoderTargetRate(0);
1537 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1538}
1539
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001540TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001541 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001542 std::max(
1543 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1544 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1545 config_.rtp.rtx.ssrcs.end())) +
1546 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001547 // From RtcpStatisticsCallback.
1548 RtcpStatistics rtcp_stats;
1549 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001550 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001551
1552 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001553 uint32_t total = 0;
1554 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001555 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001556 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001557
1558 // From FrameCountObserver.
1559 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001560 FrameCounts frame_counts;
1561 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001562 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001563
1564 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1565 EXPECT_TRUE(stats.substreams.empty());
1566}
1567
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001568TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1569 static const int kEncodedWidth = 123;
1570 static const int kEncodedHeight = 81;
1571 EncodedImage encoded_image;
1572 encoded_image._encodedWidth = kEncodedWidth;
1573 encoded_image._encodedHeight = kEncodedHeight;
1574
kjellander02b3d272016-04-20 05:05:54 -07001575 CodecSpecificInfo codec_info;
1576 codec_info.codecType = kVideoCodecVP8;
1577 codec_info.codecSpecific.VP8.simulcastIdx = 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001578
kjellander02b3d272016-04-20 05:05:54 -07001579 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1580 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1581 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001582
1583 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001584 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1585 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1586 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1587 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001588
1589 // Forward almost to timeout, this should not have removed stats.
1590 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1591 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001592 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1593 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001594
1595 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1596 // resolution still times out (no global timeout for all stats).
1597 RtcpStatistics rtcp_statistics;
1598 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1599 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1600
1601 // Report stats for second SSRC to make sure it's not outdated along with the
1602 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001603 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1604 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001605
1606 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1607 // reported, but substream 1 should.
1608 fake_clock_.AdvanceTimeMilliseconds(1);
1609 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001610 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1611 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1612 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1613 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001614}
1615
Peter Boström20f3f942015-05-15 11:33:39 +02001616TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1617 static const int kEncodedWidth = 123;
1618 static const int kEncodedHeight = 81;
1619 EncodedImage encoded_image;
1620 encoded_image._encodedWidth = kEncodedWidth;
1621 encoded_image._encodedHeight = kEncodedHeight;
1622
kjellander02b3d272016-04-20 05:05:54 -07001623 CodecSpecificInfo codec_info;
1624 codec_info.codecType = kVideoCodecVP8;
1625 codec_info.codecSpecific.VP8.simulcastIdx = 0;
Peter Boström20f3f942015-05-15 11:33:39 +02001626
kjellander02b3d272016-04-20 05:05:54 -07001627 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1628 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1629 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001630
1631 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1632 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1633 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1634 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1635 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1636 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1637}
1638
1639TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001640 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001641 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1642 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1643 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1644
1645 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1646
1647 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001648 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001649 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001650 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001651 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1652 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1653 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1654}
1655
sprang07fb9be2016-02-24 07:55:00 -08001656TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1657 RtcpPacketTypeCounterObserver* proxy =
1658 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1659 RtcpPacketTypeCounter counters;
1660 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1661 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1662 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1663
1664 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1665
1666 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1667 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1668 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1669 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1670 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1671
1672 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1673 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1674
1675 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001676 VideoEncoderConfig config;
1677 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001678 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
sprang07fb9be2016-02-24 07:55:00 -08001679
asapersson01d70a32016-05-20 06:29:46 -07001680 EXPECT_EQ(1,
1681 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1682 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1683 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1684 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001685 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1686
1687 const int kRate = 60 * 2; // Packets per minute with two streams.
1688
asapersson01d70a32016-05-20 06:29:46 -07001689 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1690 1 * kRate));
1691 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1692 2 * kRate));
1693 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1694 3 * kRate));
1695 EXPECT_EQ(
1696 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1697 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001698
1699 // New start time but same counter values.
1700 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1701 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1702
1703 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1704
1705 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1706 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1707 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1708 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1709 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1710
1711 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1712 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1713
1714 SetUp(); // Reset stats proxy also causes histograms to be reported.
1715
asapersson01d70a32016-05-20 06:29:46 -07001716 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001717 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001718 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001719 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001720 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001721 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1722 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001723 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001724 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1725
asapersson01d70a32016-05-20 06:29:46 -07001726 EXPECT_EQ(1, metrics::NumEvents(
1727 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1728 1 * kRate));
1729 EXPECT_EQ(1, metrics::NumEvents(
1730 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1731 2 * kRate));
1732 EXPECT_EQ(1, metrics::NumEvents(
1733 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1734 3 * kRate));
1735 EXPECT_EQ(1,
1736 metrics::NumEvents(
1737 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1738 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001739}
1740
asaperssona6a699a2016-11-25 03:52:46 -08001741TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1742 statistics_proxy_.reset(
1743 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1744 VideoEncoderConfig::ContentType::kRealtimeVideo));
1745
1746 StreamDataCountersCallback* proxy =
1747 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1748 StreamDataCounters counters;
1749 proxy->DataCountersUpdated(counters, kFirstSsrc);
1750 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1751
1752 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1753 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1754}
1755
1756TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1757 statistics_proxy_.reset(
1758 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1759 VideoEncoderConfig::ContentType::kRealtimeVideo));
1760
1761 StreamDataCountersCallback* proxy =
1762 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001763 StreamDataCounters counters;
1764 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001765
asapersson93e1e232017-02-06 05:18:35 -08001766 const int kMinRequiredPeriodSamples = 8;
1767 const int kPeriodIntervalMs = 2000;
1768 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1769 counters.transmitted.packets += 20;
1770 counters.transmitted.header_bytes += 500;
1771 counters.transmitted.padding_bytes += 1000;
1772 counters.transmitted.payload_bytes += 2000;
1773 counters.retransmitted.packets += 2;
1774 counters.retransmitted.header_bytes += 25;
1775 counters.retransmitted.padding_bytes += 100;
1776 counters.retransmitted.payload_bytes += 250;
1777 counters.fec = counters.retransmitted;
1778 rtx_counters.transmitted = counters.transmitted;
1779 // Advance one interval and update counters.
1780 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1781 proxy->DataCountersUpdated(counters, kFirstSsrc);
1782 proxy->DataCountersUpdated(counters, kSecondSsrc);
1783 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1784 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1785 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1786 }
asaperssona6a699a2016-11-25 03:52:46 -08001787
asaperssona6a699a2016-11-25 03:52:46 -08001788 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001789 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001790 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001791 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1792 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1793 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1794 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1795 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001796 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001797 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1798 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001799 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001800 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1801 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1802 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1803 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1804 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001805 EXPECT_EQ(1,
1806 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001807 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001808 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001809}
1810
Erik Språng22c2b482016-03-01 09:40:42 +01001811TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1812 StreamDataCountersCallback* proxy =
1813 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1814 StreamDataCounters counters;
1815 StreamDataCounters rtx_counters;
1816 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001817
asapersson93e1e232017-02-06 05:18:35 -08001818 const int kMinRequiredPeriodSamples = 8;
1819 const int kPeriodIntervalMs = 2000;
1820 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1821 counters.transmitted.packets += 20;
1822 counters.transmitted.header_bytes += 500;
1823 counters.transmitted.padding_bytes += 1000;
1824 counters.transmitted.payload_bytes += 2000;
1825 counters.retransmitted.packets += 2;
1826 counters.retransmitted.header_bytes += 25;
1827 counters.retransmitted.padding_bytes += 100;
1828 counters.retransmitted.payload_bytes += 250;
1829 counters.fec = counters.retransmitted;
1830 rtx_counters.transmitted = counters.transmitted;
1831 // Advance one interval and update counters.
1832 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1833 proxy->DataCountersUpdated(counters, kFirstSsrc);
1834 proxy->DataCountersUpdated(counters, kSecondSsrc);
1835 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1836 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1837 }
Erik Språng22c2b482016-03-01 09:40:42 +01001838
1839 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001840 VideoEncoderConfig config;
1841 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001842 statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
Erik Språng22c2b482016-03-01 09:40:42 +01001843
asapersson93e1e232017-02-06 05:18:35 -08001844 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001845 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001846 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1847 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1848 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1849 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1850 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001851 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001852 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1853 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001854 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001855 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1856 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1857 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1858 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1859 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01001860 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07001861 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001862 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001863 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01001864
asapersson93e1e232017-02-06 05:18:35 -08001865 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01001866 // Double counter values, this should result in the same counts as before but
1867 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08001868 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1869 counters.transmitted.packets += 20;
1870 counters.transmitted.header_bytes += 500;
1871 counters.transmitted.padding_bytes += 1000;
1872 counters.transmitted.payload_bytes += 2000;
1873 counters.retransmitted.packets += 2;
1874 counters.retransmitted.header_bytes += 25;
1875 counters.retransmitted.padding_bytes += 100;
1876 counters.retransmitted.payload_bytes += 250;
1877 counters.fec = counters.retransmitted;
1878 rtx_counters.transmitted = counters.transmitted;
1879 // Advance one interval and update counters.
1880 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1881 proxy->DataCountersUpdated(counters, kFirstSsrc);
1882 proxy->DataCountersUpdated(counters, kSecondSsrc);
1883 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1884 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1885 }
Erik Språng22c2b482016-03-01 09:40:42 +01001886
asapersson93e1e232017-02-06 05:18:35 -08001887 // Reset stats proxy also causes histograms to be reported.
1888 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01001889
asapersson93e1e232017-02-06 05:18:35 -08001890 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001891 EXPECT_EQ(1,
1892 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001893 EXPECT_EQ(
1894 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
1895 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1896 EXPECT_EQ(
1897 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
1898 EXPECT_EQ(1, metrics::NumEvents(
1899 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
1900 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001901 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001902 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001903 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001904 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
1905 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 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.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001908 EXPECT_EQ(1, metrics::NumEvents(
1909 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
1910 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1911 EXPECT_EQ(
1912 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
1913 EXPECT_EQ(1, metrics::NumEvents(
1914 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
1915 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07001916 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001917 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001918 EXPECT_EQ(1,
1919 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001920 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
1921}
Erik Språng22c2b482016-03-01 09:40:42 +01001922
asapersson93e1e232017-02-06 05:18:35 -08001923TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
1924 StreamDataCountersCallback* proxy =
1925 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1926 StreamDataCounters counters;
1927 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01001928
asapersson93e1e232017-02-06 05:18:35 -08001929 const int kMinRequiredPeriodSamples = 8;
1930 const int kPeriodIntervalMs = 2000;
1931 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1932 counters.transmitted.packets += 20;
1933 counters.transmitted.header_bytes += 500;
1934 counters.transmitted.payload_bytes += 2000;
1935 counters.fec = counters.retransmitted;
1936 // Advance one interval and update counters.
1937 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1938 proxy->DataCountersUpdated(counters, kFirstSsrc);
1939 }
1940
1941 // RTX enabled. No data sent over RTX.
1942 statistics_proxy_.reset();
1943 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1944 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
1945}
1946
1947TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
1948 VideoSendStream::Config config(nullptr);
1949 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
1950 statistics_proxy_.reset(new SendStatisticsProxy(
1951 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1952
1953 StreamDataCountersCallback* proxy =
1954 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1955 StreamDataCounters counters;
1956
1957 const int kMinRequiredPeriodSamples = 8;
1958 const int kPeriodIntervalMs = 2000;
1959 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1960 counters.transmitted.packets += 20;
1961 counters.transmitted.header_bytes += 500;
1962 counters.transmitted.payload_bytes += 2000;
1963 counters.fec = counters.retransmitted;
1964 // Advance one interval and update counters.
1965 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1966 proxy->DataCountersUpdated(counters, kFirstSsrc);
1967 }
1968
1969 // RTX not enabled.
1970 statistics_proxy_.reset();
1971 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1972}
1973
1974TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
1975 StreamDataCountersCallback* proxy =
1976 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1977 StreamDataCounters counters;
1978 StreamDataCounters rtx_counters;
1979
1980 const int kMinRequiredPeriodSamples = 8;
1981 const int kPeriodIntervalMs = 2000;
1982 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1983 counters.transmitted.packets += 20;
1984 counters.transmitted.header_bytes += 500;
1985 counters.transmitted.payload_bytes += 2000;
1986 // Advance one interval and update counters.
1987 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1988 proxy->DataCountersUpdated(counters, kFirstSsrc);
1989 }
1990
1991 // FEC enabled. No FEC data sent.
1992 statistics_proxy_.reset();
1993 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1994 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
1995}
1996
1997TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
1998 VideoSendStream::Config config(nullptr);
1999 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2000 statistics_proxy_.reset(new SendStatisticsProxy(
2001 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2002
2003 StreamDataCountersCallback* proxy =
2004 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2005 StreamDataCounters counters;
2006
2007 const int kMinRequiredPeriodSamples = 8;
2008 const int kPeriodIntervalMs = 2000;
2009 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2010 counters.transmitted.packets += 20;
2011 counters.transmitted.header_bytes += 500;
2012 counters.transmitted.payload_bytes += 2000;
2013 counters.fec = counters.retransmitted;
2014 // Advance one interval and update counters.
2015 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2016 proxy->DataCountersUpdated(counters, kFirstSsrc);
2017 }
2018
2019 // FEC not enabled.
2020 statistics_proxy_.reset();
2021 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002022}
2023
asapersson8d75ac72017-09-15 06:41:15 -07002024TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
2025 const char* kName = "encoderName";
2026 EncodedImage encoded_image;
2027 CodecSpecificInfo codec_info;
2028 codec_info.codec_name = kName;
2029 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2030 EXPECT_STREQ(
2031 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str());
2032}
2033
2034class ForcedFallbackTest : public SendStatisticsProxyTest {
2035 public:
2036 explicit ForcedFallbackTest(const std::string& field_trials)
2037 : SendStatisticsProxyTest(field_trials) {
2038 codec_info_.codecType = kVideoCodecVP8;
2039 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
2040 codec_info_.codecSpecific.VP8.temporalIdx = 0;
2041 codec_info_.codec_name = "fake_codec";
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002042 encoded_image_._encodedWidth = kWidth;
2043 encoded_image_._encodedHeight = kHeight;
asapersson8d75ac72017-09-15 06:41:15 -07002044 }
2045
2046 ~ForcedFallbackTest() override {}
2047
2048 protected:
2049 void InsertEncodedFrames(int num_frames, int interval_ms) {
2050 // First frame is not updating stats, insert initial frame.
2051 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2052 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2053 }
2054 for (int i = 0; i < num_frames; ++i) {
2055 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2056 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2057 }
2058 // Add frame to include last time interval.
2059 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2060 }
2061
2062 EncodedImage encoded_image_;
2063 CodecSpecificInfo codec_info_;
2064 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2065 const int kFrameIntervalMs = 1000;
2066 const int kMinFrames = 20; // Min run time 20 sec.
2067};
2068
2069class ForcedFallbackDisabled : public ForcedFallbackTest {
2070 public:
2071 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002072 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2073 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002074};
2075
2076class ForcedFallbackEnabled : public ForcedFallbackTest {
2077 public:
2078 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002079 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2080 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002081};
2082
2083TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2084 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2085 statistics_proxy_.reset();
2086 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2087 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2088}
2089
2090TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2091 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002092 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002093 statistics_proxy_.reset();
2094 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2095 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2096 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2097 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2098}
2099
2100TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2101 codec_info_.codecType = kVideoCodecVP9;
2102 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2103 statistics_proxy_.reset();
2104 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2105 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2106}
2107
2108TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2109 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2110 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2111 statistics_proxy_.reset();
2112 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2113 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2114}
2115
2116TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
2117 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
2118 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2119 statistics_proxy_.reset();
2120 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2121 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2122}
2123
2124TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2125 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2126 statistics_proxy_.reset();
2127 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2128 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2129}
2130
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002131TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2132 InsertEncodedFrames(1, kFrameIntervalMs);
2133 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2134}
2135
2136TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2137 InsertEncodedFrames(1, kFrameIntervalMs);
2138 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2139}
2140
2141TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
2142 codec_info_.codec_name = "libvpx";
2143 InsertEncodedFrames(1, kFrameIntervalMs);
2144 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2145}
2146
2147TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2148 encoded_image_._encodedWidth = kWidth + 1;
2149 InsertEncodedFrames(1, kFrameIntervalMs);
2150 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2151}
2152
2153TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
2154 codec_info_.codec_name = "libvpx";
2155 InsertEncodedFrames(1, kFrameIntervalMs);
2156 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2157}
2158
2159TEST_F(ForcedFallbackDisabled,
2160 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2161 encoded_image_._encodedWidth = kWidth + 1;
2162 statistics_proxy_->OnMinPixelLimitReached();
2163 InsertEncodedFrames(1, kFrameIntervalMs);
2164 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2165}
2166
asapersson8d75ac72017-09-15 06:41:15 -07002167TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2168 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002169 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002170 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002171 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002172 codec_info_.codec_name = "libvpx";
2173 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002174 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002175
2176 statistics_proxy_.reset();
2177 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2178 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2179 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2180 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2181}
2182
2183TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2184 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2185 const int kMaxFrameDiffMs = 2000;
2186
2187 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2188 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002189 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002190 codec_info_.codec_name = "libvpx";
2191 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002192 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002193 codec_info_.codec_name = "notlibvpx";
2194 InsertEncodedFrames(20, 1000);
2195 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2196 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002197 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002198 codec_info_.codec_name = "notlibvpx2";
2199 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002200 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002201 codec_info_.codec_name = "libvpx";
2202 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002203 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002204
2205 statistics_proxy_.reset();
2206 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2207 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2208 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2209 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
2210}
2211
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002212TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2213 encoded_image_._encodedWidth = kWidth + 1;
asapersson8d75ac72017-09-15 06:41:15 -07002214 codec_info_.codec_name = "libvpx";
2215 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2216
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002217 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002218 statistics_proxy_.reset();
2219 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2220 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2221}
2222
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002223TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2224 encoded_image_._encodedWidth = kWidth;
asapersson8d75ac72017-09-15 06:41:15 -07002225 codec_info_.codec_name = "libvpx";
2226 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2227
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002228 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002229 statistics_proxy_.reset();
2230 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2231 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2232}
2233
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002234} // namespace webrtc