blob: 8b49a268b6361d2eab01b033b7690c16d980597f [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
Steve Antonbd631a02019-03-28 10:51:27 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
17#include <vector>
18
Steve Antonbd631a02019-03-28 10:51:27 -070019#include "absl/algorithm/container.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020020#include "api/units/timestamp.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020021#include "api/video/video_bitrate_allocation.h"
22#include "api/video/video_codec_type.h"
23#include "api/video_codecs/video_codec.h"
24#include "api/video_codecs/video_encoder_config.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020025#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070027#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000029
30namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070031namespace {
32const uint32_t kFirstSsrc = 17;
33const uint32_t kSecondSsrc = 42;
34const uint32_t kFirstRtxSsrc = 18;
35const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080036const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080037const int kFpsPeriodicIntervalMs = 2000;
38const int kWidth = 640;
39const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070040const int kQpIdx0 = 21;
41const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010042const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080043const CodecSpecificInfo kDefaultCodecInfo = []() {
44 CodecSpecificInfo codec_info;
45 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080046 return codec_info;
47}();
asapersson5265fed2016-04-18 02:58:47 -070048} // namespace
sprang07fb9be2016-02-24 07:55:00 -080049
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000050class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000051 public:
asapersson8d75ac72017-09-15 06:41:15 -070052 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
53 explicit SendStatisticsProxyTest(const std::string& field_trials)
54 : override_field_trials_(field_trials),
55 fake_clock_(1234),
56 config_(GetTestConfig()),
57 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070058 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000059 virtual ~SendStatisticsProxyTest() {}
60
61 protected:
62 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070063 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080064 statistics_proxy_.reset(new SendStatisticsProxy(
65 &fake_clock_, GetTestConfig(),
66 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000067 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010068 for (const auto& ssrc : config_.rtp.ssrcs) {
69 expected_.substreams[ssrc].type =
70 VideoSendStream::StreamStats::StreamType::kMedia;
71 }
72 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
73 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
74 expected_.substreams[ssrc].type =
75 VideoSendStream::StreamStats::StreamType::kRtx;
76 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
77 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000078 }
79
80 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070081 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080082 config.rtp.ssrcs.push_back(kFirstSsrc);
83 config.rtp.ssrcs.push_back(kSecondSsrc);
84 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
85 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070086 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000087 return config;
88 }
89
asaperssona6a699a2016-11-25 03:52:46 -080090 VideoSendStream::Config GetTestConfigWithFlexFec() {
91 VideoSendStream::Config config(nullptr);
92 config.rtp.ssrcs.push_back(kFirstSsrc);
93 config.rtp.ssrcs.push_back(kSecondSsrc);
94 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
95 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080096 config.rtp.flexfec.payload_type = 50;
97 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +010098 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -080099 return config;
100 }
101
102 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
103 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
104 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
105 stats.substreams.find(ssrc);
106 EXPECT_NE(it, stats.substreams.end());
107 return it->second;
108 }
109
asapersson66d4b372016-12-19 06:50:53 -0800110 void UpdateDataCounters(uint32_t ssrc) {
111 StreamDataCountersCallback* proxy =
112 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
113 StreamDataCounters counters;
114 proxy->DataCountersUpdated(counters, ssrc);
115 }
116
sprang@webrtc.org09315702014-02-07 12:06:29 +0000117 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000118 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
119 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000120 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000121 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000122
123 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000124 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000125 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000126 it != one.substreams.end(); ++it) {
127 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
128 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000129 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000130 const VideoSendStream::StreamStats& a = it->second;
131 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
Henrik Boströmf45ca372020-03-24 13:30:50 +0100133 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000134 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
135 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000136 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000137 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
138 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000139
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000140 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
141 b.rtp_stats.transmitted.payload_bytes);
142 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
143 b.rtp_stats.transmitted.header_bytes);
144 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
145 b.rtp_stats.transmitted.padding_bytes);
146 EXPECT_EQ(a.rtp_stats.transmitted.packets,
147 b.rtp_stats.transmitted.packets);
148 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
149 b.rtp_stats.retransmitted.packets);
150 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000151
152 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700153 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
154 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
155 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000156 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
157 }
158 }
159
asapersson8d75ac72017-09-15 06:41:15 -0700160 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000161 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800162 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000163 VideoSendStream::Config config_;
164 int avg_delay_ms_;
165 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000166 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000167 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
168 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000169};
170
171TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
172 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700173 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000174 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000175
176 // Add statistics with some arbitrary, but unique, numbers.
177 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700178 ssrc_stats.rtcp_stats.packets_lost = offset;
179 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000180 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
181 ssrc_stats.rtcp_stats.jitter = offset + 3;
182 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
183 }
asapersson35151f32016-05-02 23:44:01 -0700184 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000185 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000186
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000187 // Add statistics with some arbitrary, but unique, numbers.
188 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700189 ssrc_stats.rtcp_stats.packets_lost = offset;
190 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000191 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
192 ssrc_stats.rtcp_stats.jitter = offset + 3;
193 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
194 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000195 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000196 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000197}
198
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000199TEST_F(SendStatisticsProxyTest, Suspended) {
200 // Verify that the value is false by default.
201 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
202
203 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200204 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000205 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
206
207 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200208 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000209 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
210}
211
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000212TEST_F(SendStatisticsProxyTest, FrameCounts) {
213 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700214 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +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);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000223 }
asapersson35151f32016-05-02 23:44:01 -0700224 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000225 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000226 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
227 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000228 FrameCounts frame_counts;
229 frame_counts.key_frames = offset;
230 frame_counts.delta_frames = offset + 1;
231 stats.frame_counts = frame_counts;
232 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000233 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000234
235 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000236 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000237}
238
239TEST_F(SendStatisticsProxyTest, DataCounters) {
240 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700241 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000242 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
243 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000244 size_t offset = ssrc * sizeof(StreamDataCounters);
245 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000246 counters.transmitted.payload_bytes = offset;
247 counters.transmitted.header_bytes = offset + 1;
248 counters.fec.packets = offset_uint32 + 2;
249 counters.transmitted.padding_bytes = offset + 3;
250 counters.retransmitted.packets = offset_uint32 + 4;
251 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000252 callback->DataCountersUpdated(counters, ssrc);
253 }
asapersson35151f32016-05-02 23:44:01 -0700254 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000255 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
256 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000257 size_t offset = ssrc * sizeof(StreamDataCounters);
258 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000259 counters.transmitted.payload_bytes = offset;
260 counters.transmitted.header_bytes = offset + 1;
261 counters.fec.packets = offset_uint32 + 2;
262 counters.transmitted.padding_bytes = offset + 3;
263 counters.retransmitted.packets = offset_uint32 + 4;
264 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000265 callback->DataCountersUpdated(counters, ssrc);
266 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000267
268 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000269 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000270}
271
272TEST_F(SendStatisticsProxyTest, Bitrate) {
273 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700274 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700275 uint32_t total;
276 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +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;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000283 }
asapersson35151f32016-05-02 23:44:01 -0700284 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700285 uint32_t total;
286 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000287 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700288 total = ssrc;
289 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000290 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700291 expected_.substreams[ssrc].total_bitrate_bps = total;
292 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000293 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000294
295 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000296 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000297}
298
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000299TEST_F(SendStatisticsProxyTest, SendSideDelay) {
300 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700301 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000302 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
303 // stream.
304 int avg_delay_ms = ssrc;
305 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200306 uint64_t total_packet_send_delay_ms = ssrc + 2;
307 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
308 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000309 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
310 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200311 expected_.substreams[ssrc].total_packet_send_delay_ms =
312 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000313 }
asapersson35151f32016-05-02 23:44:01 -0700314 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000315 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
316 // stream.
317 int avg_delay_ms = ssrc;
318 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200319 uint64_t total_packet_send_delay_ms = ssrc + 2;
320 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
321 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000322 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
323 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200324 expected_.substreams[ssrc].total_packet_send_delay_ms =
325 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000326 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000327 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000328 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000329}
330
Peter Boströme4499152016-02-05 11:13:28 +0100331TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800332 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200333 int encode_usage_percent = 80;
334 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
335 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800336
337 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
338 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200339 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800340}
341
Henrik Boström5684af52019-04-02 15:05:21 +0200342TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
343 const int kEncodeUsagePercent = 0; // Don't care for this test.
344 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
345 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
346 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
347 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
348 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
349}
350
sakal43536c32016-10-24 01:46:43 -0700351TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
352 EncodedImage encoded_image;
353 CodecSpecificInfo codec_info;
354 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
355 for (uint32_t i = 1; i <= 3; ++i) {
356 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
357 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
358 }
359}
360
sakal87da4042016-10-31 06:53:47 -0700361TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
362 EncodedImage encoded_image;
363 CodecSpecificInfo codec_info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200364 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700365 encoded_image.qp_ = 3;
366 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100367 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700368 encoded_image.qp_ = 127;
369 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100370 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700371}
372
373TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
374 EncodedImage encoded_image;
375 CodecSpecificInfo codec_info;
376 encoded_image.qp_ = -1;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200377 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700378 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200379 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakal87da4042016-10-31 06:53:47 -0700380}
381
Henrik Boström23aff9b2019-05-20 15:15:38 +0200382TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
383 const uint32_t kTargetBytesPerSecond = 100000;
384 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
385 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
386
387 EncodedImage encoded_image;
388 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
389 // On the first frame we don't know the frame rate yet, calculation yields
390 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
391 // increment by a full |kTargetBytesPerSecond|.
392 EXPECT_EQ(kTargetBytesPerSecond,
393 statistics_proxy_->GetStats().total_encoded_bytes_target);
394}
395
396TEST_F(SendStatisticsProxyTest,
397 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
398 const uint32_t kTargetBytesPerSecond = 100000;
399 const int kInterframeDelayMs = 100;
400
401 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
402 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
403 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
404 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
405 // this test can stop relying on rtc::ScopedFakeClock.
406 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100407 fake_global_clock.SetTime(
408 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200409
410 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
411 EncodedImage encoded_image;
412
413 // First frame
414 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
415 uint64_t first_total_encoded_bytes_target =
416 statistics_proxy_->GetStats().total_encoded_bytes_target;
417 // Second frame
418 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100419 fake_global_clock.SetTime(
420 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200421 encoded_image.SetTimestamp(encoded_image.Timestamp() +
422 90 * kInterframeDelayMs);
423 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
424
425 auto stats = statistics_proxy_->GetStats();
426 // By the time the second frame arrives, one frame has previously arrived
427 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
428 // the second frame's arrival should be 10 FPS.
429 uint64_t delta_encoded_bytes_target =
430 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
431 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
432}
433
asapersson09f05612017-05-15 23:40:18 -0700434TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200435 SendStatisticsProxy::AdaptationSteps cpu_counts;
436 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700437 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700438 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200439 cpu_counts.num_framerate_reductions = 1;
440 cpu_counts.num_resolution_reductions = 0;
441 statistics_proxy_->OnAdaptationChanged(
442 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
443 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700444 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700445 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200446 cpu_counts.num_framerate_reductions = 0;
447 cpu_counts.num_resolution_reductions = 1;
448 statistics_proxy_->OnAdaptationChanged(
449 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
450 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700451 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700452 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200453 cpu_counts.num_framerate_reductions = 1;
454 cpu_counts.num_resolution_reductions = absl::nullopt;
455 statistics_proxy_->OnAdaptationChanged(
456 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
457 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700458 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700459 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200460 cpu_counts.num_framerate_reductions = absl::nullopt;
461 cpu_counts.num_resolution_reductions = absl::nullopt;
462 statistics_proxy_->OnAdaptationChanged(
463 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
464 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700465 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
466 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
467}
468
469TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Niels Möller213618e2018-07-24 09:29:58 +0200470 SendStatisticsProxy::AdaptationSteps cpu_counts;
471 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700472 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
473 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200474 quality_counts.num_framerate_reductions = 1;
475 quality_counts.num_resolution_reductions = 0;
476 statistics_proxy_->OnAdaptationChanged(
477 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
478 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700479 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
480 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200481 quality_counts.num_framerate_reductions = 0;
482 quality_counts.num_resolution_reductions = 1;
483 statistics_proxy_->OnAdaptationChanged(
484 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
485 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700486 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
487 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200488 quality_counts.num_framerate_reductions = 1;
489 quality_counts.num_resolution_reductions = absl::nullopt;
490 statistics_proxy_->OnAdaptationChanged(
491 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
492 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700493 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
494 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Niels Möller213618e2018-07-24 09:29:58 +0200495 quality_counts.num_framerate_reductions = absl::nullopt;
496 quality_counts.num_resolution_reductions = absl::nullopt;
497 statistics_proxy_->OnAdaptationChanged(
498 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
499 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700500 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
501 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
502}
503
504TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200505 SendStatisticsProxy::AdaptationSteps cpu_counts;
506 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700507 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
508
Niels Möller213618e2018-07-24 09:29:58 +0200509 cpu_counts.num_resolution_reductions = 1;
510 statistics_proxy_->OnAdaptationChanged(
511 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
512 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700513 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700514 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
515 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
516
Niels Möller213618e2018-07-24 09:29:58 +0200517 cpu_counts.num_resolution_reductions = 2;
518 statistics_proxy_->OnAdaptationChanged(
519 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
520 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700521 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
522 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700523 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700524 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700525}
526
asapersson09f05612017-05-15 23:40:18 -0700527TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Niels Möller213618e2018-07-24 09:29:58 +0200528 SendStatisticsProxy::AdaptationSteps cpu_counts;
529 SendStatisticsProxy::AdaptationSteps quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700530 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
531
Niels Möller213618e2018-07-24 09:29:58 +0200532 quality_counts.num_framerate_reductions = 1;
533 statistics_proxy_->OnAdaptationChanged(
534 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
535 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700536 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
537 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700538 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
539
Niels Möller213618e2018-07-24 09:29:58 +0200540 quality_counts.num_framerate_reductions = 0;
541 statistics_proxy_->OnAdaptationChanged(
542 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
543 quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700544 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700545 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700546 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
547 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700548}
549
asapersson09f05612017-05-15 23:40:18 -0700550TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700551 // First RTP packet sent.
552 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700553 // Min runtime has passed.
554 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
555 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100556 EXPECT_METRIC_EQ(
557 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
558 EXPECT_METRIC_EQ(
559 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700560}
561
562TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700563 // First RTP packet sent.
564 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700565 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200566 SendStatisticsProxy::AdaptationSteps cpu_counts;
567 SendStatisticsProxy::AdaptationSteps quality_counts;
568 statistics_proxy_->OnAdaptationChanged(
569 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
570 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700571 // Min runtime has not passed.
572 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
573 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100574 EXPECT_METRIC_EQ(
575 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
576 EXPECT_METRIC_EQ(
577 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700578}
579
asapersson09f05612017-05-15 23:40:18 -0700580TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700581 // First RTP packet sent.
582 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700583 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200584 SendStatisticsProxy::AdaptationSteps cpu_counts;
585 SendStatisticsProxy::AdaptationSteps quality_counts;
586 statistics_proxy_->OnAdaptationChanged(
587 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
588 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700589 // Min runtime has passed.
590 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
591 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100592 EXPECT_METRIC_EQ(
593 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
594 EXPECT_METRIC_EQ(
595 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
596 EXPECT_METRIC_EQ(
597 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
598 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700599 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
600}
601
602TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700603 // First RTP packet sent.
604 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700605 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200606 SendStatisticsProxy::AdaptationSteps cpu_counts;
607 SendStatisticsProxy::AdaptationSteps quality_counts;
608 statistics_proxy_->OnAdaptationChanged(
609 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
610 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700611 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200612 statistics_proxy_->OnAdaptationChanged(
613 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
614 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700615 fake_clock_.AdvanceTimeMilliseconds(10000);
616 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100617 EXPECT_METRIC_EQ(
618 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
619 EXPECT_METRIC_EQ(
620 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700621}
622
Åsa Persson875841d2018-01-08 08:49:53 +0100623TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
624 // First RTP packet sent.
625 UpdateDataCounters(kFirstSsrc);
626 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200627 SendStatisticsProxy::AdaptationSteps cpu_counts;
628 SendStatisticsProxy::AdaptationSteps quality_counts;
629 statistics_proxy_->OnAdaptationChanged(
630 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
631 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100632 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200633 statistics_proxy_->OnAdaptationChanged(
634 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
635 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100636 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
637 fake_clock_.AdvanceTimeMilliseconds(10000);
638 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100639 EXPECT_METRIC_EQ(
640 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
641 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100642 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
643}
644
645TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
646 // First RTP packet sent.
647 UpdateDataCounters(kFirstSsrc);
648 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200649 SendStatisticsProxy::AdaptationSteps cpu_counts;
650 SendStatisticsProxy::AdaptationSteps quality_counts;
651 statistics_proxy_->OnAdaptationChanged(
652 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
653 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100654 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200655 quality_counts.num_resolution_reductions = 1;
656 statistics_proxy_->OnAdaptationChanged(
657 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
658 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100659 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200660 quality_counts.num_resolution_reductions = 2;
661 statistics_proxy_->OnAdaptationChanged(
662 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
663 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100664 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200665 quality_counts.num_resolution_reductions = 3;
666 statistics_proxy_->OnAdaptationChanged(
667 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
668 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100669 fake_clock_.AdvanceTimeMilliseconds(10000);
670 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100671 EXPECT_METRIC_EQ(
672 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
673 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100674 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
675}
676
677TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
678 // First RTP packet sent.
679 UpdateDataCounters(kFirstSsrc);
680 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200681 SendStatisticsProxy::AdaptationSteps cpu_counts;
682 SendStatisticsProxy::AdaptationSteps quality_counts;
683 statistics_proxy_->OnAdaptationChanged(
684 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
685 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100686 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200687 statistics_proxy_->OnAdaptationChanged(
688 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
689 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100690 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
691 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
692 fake_clock_.AdvanceTimeMilliseconds(10000);
693 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100694 EXPECT_METRIC_EQ(
695 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
696 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100697 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
698}
699
700TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
701 // First RTP packet sent.
702 UpdateDataCounters(kFirstSsrc);
703 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200704 SendStatisticsProxy::AdaptationSteps cpu_counts;
705 SendStatisticsProxy::AdaptationSteps quality_counts;
706 statistics_proxy_->OnAdaptationChanged(
707 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
708 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100709 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Niels Möller213618e2018-07-24 09:29:58 +0200710 quality_counts.num_resolution_reductions = 1;
711 statistics_proxy_->OnAdaptationChanged(
712 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
713 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100714 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200715 quality_counts.num_resolution_reductions = 2;
716 statistics_proxy_->OnAdaptationChanged(
717 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
718 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100719 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Niels Möller213618e2018-07-24 09:29:58 +0200720 quality_counts.num_resolution_reductions = 3;
721 statistics_proxy_->OnAdaptationChanged(
722 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
723 quality_counts);
724 quality_counts.num_framerate_reductions = 1;
725 statistics_proxy_->OnAdaptationChanged(
726 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
727 quality_counts);
728 quality_counts.num_framerate_reductions = 0;
729 statistics_proxy_->OnAdaptationChanged(
730 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
731 quality_counts);
732 quality_counts.num_resolution_reductions = 2; // Initial resolution up.
733 statistics_proxy_->OnAdaptationChanged(
734 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
735 quality_counts);
736 quality_counts.num_resolution_reductions = 1; // Initial resolution up.
737 statistics_proxy_->OnAdaptationChanged(
738 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
739 quality_counts);
740 quality_counts.num_resolution_reductions = 0;
741 statistics_proxy_->OnAdaptationChanged(
742 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
743 quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100744
745 fake_clock_.AdvanceTimeMilliseconds(10000);
746 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100747 EXPECT_METRIC_EQ(
748 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
749 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100750 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
751}
752
asapersson6eca98b2017-04-04 23:40:50 -0700753TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700754 // First RTP packet sent.
755 UpdateDataCounters(kFirstSsrc);
756
asapersson09f05612017-05-15 23:40:18 -0700757 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200758 SendStatisticsProxy::AdaptationSteps cpu_counts;
759 SendStatisticsProxy::AdaptationSteps quality_counts;
760 quality_counts.num_framerate_reductions = absl::nullopt;
761 quality_counts.num_resolution_reductions = absl::nullopt;
762 statistics_proxy_->OnAdaptationChanged(
763 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
764 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700765 fake_clock_.AdvanceTimeMilliseconds(10000);
766
asapersson09f05612017-05-15 23:40:18 -0700767 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700768 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200769 quality_counts.num_framerate_reductions = 0;
770 statistics_proxy_->OnAdaptationChanged(
771 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
772 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700773 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200774 statistics_proxy_->OnAdaptationChanged(
775 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
776 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700777 fake_clock_.AdvanceTimeMilliseconds(9000);
Niels Möller213618e2018-07-24 09:29:58 +0200778 statistics_proxy_->OnAdaptationChanged(
779 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
780 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700781 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +0200782 statistics_proxy_->OnAdaptationChanged(
783 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
784 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700785
asapersson09f05612017-05-15 23:40:18 -0700786 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200787 quality_counts.num_framerate_reductions = absl::nullopt;
788 statistics_proxy_->OnAdaptationChanged(
789 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
790 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700791 fake_clock_.AdvanceTimeMilliseconds(30000);
792
asapersson09f05612017-05-15 23:40:18 -0700793 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700794 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200795 quality_counts.num_resolution_reductions = 0;
796 statistics_proxy_->OnAdaptationChanged(
797 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
798 quality_counts);
799 statistics_proxy_->OnAdaptationChanged(
800 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
801 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700802 fake_clock_.AdvanceTimeMilliseconds(10000);
803
asapersson09f05612017-05-15 23:40:18 -0700804 // Disable quality adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200805 quality_counts.num_resolution_reductions = absl::nullopt;
806 statistics_proxy_->OnAdaptationChanged(
807 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
808 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700809 fake_clock_.AdvanceTimeMilliseconds(5000);
Niels Möller213618e2018-07-24 09:29:58 +0200810 statistics_proxy_->OnAdaptationChanged(
811 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
812 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700813 fake_clock_.AdvanceTimeMilliseconds(20000);
814
asapersson0944a802017-04-07 00:57:58 -0700815 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700816 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100817 EXPECT_METRIC_EQ(
818 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
819 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700820 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
821}
822
asapersson0944a802017-04-07 00:57:58 -0700823TEST_F(SendStatisticsProxyTest,
824 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
825 // First RTP packet sent.
826 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700827
asapersson0944a802017-04-07 00:57:58 -0700828 // Suspend and resume video.
829 statistics_proxy_->OnSuspendChange(true);
830 fake_clock_.AdvanceTimeMilliseconds(5000);
831 statistics_proxy_->OnSuspendChange(false);
832
833 // Min runtime has passed but scaling not enabled.
834 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
835 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100836 EXPECT_METRIC_EQ(
837 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
838 EXPECT_METRIC_EQ(
839 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700840}
841
842TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
843 // First RTP packet sent.
844 UpdateDataCounters(kFirstSsrc);
845
asapersson09f05612017-05-15 23:40:18 -0700846 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200847 SendStatisticsProxy::AdaptationSteps cpu_counts;
848 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700849 // Adapt changes: 2, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200850 statistics_proxy_->OnAdaptationChanged(
851 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
852 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700853 fake_clock_.AdvanceTimeMilliseconds(20000);
Niels Möller213618e2018-07-24 09:29:58 +0200854 statistics_proxy_->OnAdaptationChanged(
855 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
856 quality_counts);
857 statistics_proxy_->OnAdaptationChanged(
858 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
859 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700860
861 // Suspend and resume video.
862 statistics_proxy_->OnSuspendChange(true);
863 fake_clock_.AdvanceTimeMilliseconds(30000);
864 statistics_proxy_->OnSuspendChange(false);
865
866 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200867 statistics_proxy_->OnAdaptationChanged(
868 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
869 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700870 fake_clock_.AdvanceTimeMilliseconds(10000);
871
872 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
873 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100874 EXPECT_METRIC_EQ(
875 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
876 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700877 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
878}
879
880TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
881 // First RTP packet sent.
882 UpdateDataCounters(kFirstSsrc);
883
884 // Video not suspended.
885 statistics_proxy_->OnSuspendChange(false);
886 fake_clock_.AdvanceTimeMilliseconds(30000);
887
asapersson09f05612017-05-15 23:40:18 -0700888 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200889 SendStatisticsProxy::AdaptationSteps cpu_counts;
890 SendStatisticsProxy::AdaptationSteps quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700891 // Adapt changes: 1, elapsed time: 20 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200892 statistics_proxy_->OnAdaptationChanged(
893 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
894 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700895 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200896 statistics_proxy_->OnAdaptationChanged(
897 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
898 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700899
900 // Video not suspended, stats time already started.
901 statistics_proxy_->OnSuspendChange(false);
902 fake_clock_.AdvanceTimeMilliseconds(10000);
903
asapersson09f05612017-05-15 23:40:18 -0700904 // Disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200905 cpu_counts.num_framerate_reductions = absl::nullopt;
906 cpu_counts.num_resolution_reductions = absl::nullopt;
907 statistics_proxy_->OnAdaptationChanged(
908 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
909 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700910 fake_clock_.AdvanceTimeMilliseconds(30000);
911
912 // Suspend and resume video, stats time not started when scaling not enabled.
913 statistics_proxy_->OnSuspendChange(true);
914 fake_clock_.AdvanceTimeMilliseconds(30000);
915 statistics_proxy_->OnSuspendChange(false);
916 fake_clock_.AdvanceTimeMilliseconds(30000);
917
asapersson09f05612017-05-15 23:40:18 -0700918 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700919 // Adapt changes: 1, elapsed time: 10 sec.
Niels Möller213618e2018-07-24 09:29:58 +0200920 cpu_counts.num_framerate_reductions = 0;
921 cpu_counts.num_resolution_reductions = 0;
922 statistics_proxy_->OnAdaptationChanged(
923 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
924 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700925 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200926 statistics_proxy_->OnAdaptationChanged(
927 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
928 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700929
930 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
931 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100932 EXPECT_METRIC_EQ(
933 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
934 EXPECT_METRIC_EQ(
935 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700936}
937
938TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
939 // First RTP packet sent.
940 UpdateDataCounters(kFirstSsrc);
941
942 // Video suspended.
943 statistics_proxy_->OnSuspendChange(true);
944
asapersson09f05612017-05-15 23:40:18 -0700945 // Enable adaptation, stats time not started when suspended.
Niels Möller213618e2018-07-24 09:29:58 +0200946 SendStatisticsProxy::AdaptationSteps cpu_counts;
947 SendStatisticsProxy::AdaptationSteps quality_counts;
948 statistics_proxy_->OnAdaptationChanged(
949 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
950 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700951 fake_clock_.AdvanceTimeMilliseconds(10000);
952
953 // Resume video, stats time started.
954 // Adapt changes: 1, elapsed time: 10 sec.
955 statistics_proxy_->OnSuspendChange(false);
956 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200957 statistics_proxy_->OnAdaptationChanged(
958 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
959 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700960
961 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
962 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100963 EXPECT_METRIC_EQ(
964 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
965 EXPECT_METRIC_EQ(
966 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -0700967}
968
969TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700970 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700971 // Elapsed time before first packet is sent should be excluded.
Niels Möller213618e2018-07-24 09:29:58 +0200972 SendStatisticsProxy::AdaptationSteps cpu_counts;
973 SendStatisticsProxy::AdaptationSteps quality_counts;
974 statistics_proxy_->OnAdaptationChanged(
975 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
976 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700977 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700978 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700979
asapersson0944a802017-04-07 00:57:58 -0700980 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700981 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +0200982 statistics_proxy_->OnAdaptationChanged(
983 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
984 quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700985 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700986
asapersson0944a802017-04-07 00:57:58 -0700987 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700988 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100989 EXPECT_METRIC_EQ(
990 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
991 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700992 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
993}
994
995TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700996 // Enable and disable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +0200997 SendStatisticsProxy::AdaptationSteps cpu_counts;
998 SendStatisticsProxy::AdaptationSteps quality_counts;
999 statistics_proxy_->OnAdaptationChanged(
1000 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1001 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001002 fake_clock_.AdvanceTimeMilliseconds(60000);
Niels Möller213618e2018-07-24 09:29:58 +02001003 cpu_counts.num_framerate_reductions = absl::nullopt;
1004 cpu_counts.num_resolution_reductions = absl::nullopt;
1005 statistics_proxy_->OnAdaptationChanged(
1006 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1007 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001008
1009 // Send first packet, scaling disabled.
1010 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001011 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001012 fake_clock_.AdvanceTimeMilliseconds(60000);
1013
asapersson09f05612017-05-15 23:40:18 -07001014 // Enable adaptation.
Niels Möller213618e2018-07-24 09:29:58 +02001015 cpu_counts.num_resolution_reductions = 0;
1016 statistics_proxy_->OnAdaptationChanged(
1017 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1018 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001019 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001020 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001021
asapersson0944a802017-04-07 00:57:58 -07001022 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001023 fake_clock_.AdvanceTimeMilliseconds(10000);
Niels Möller213618e2018-07-24 09:29:58 +02001024 statistics_proxy_->OnAdaptationChanged(
1025 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1026 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001027
asapersson0944a802017-04-07 00:57:58 -07001028 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001029 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001030 EXPECT_METRIC_EQ(
1031 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1032 EXPECT_METRIC_EQ(
1033 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001034}
1035
1036TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001037 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001038 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001039 SendStatisticsProxy::AdaptationSteps cpu_counts;
1040 SendStatisticsProxy::AdaptationSteps quality_counts;
1041 quality_counts.num_framerate_reductions = absl::nullopt;
1042 quality_counts.num_resolution_reductions = absl::nullopt;
1043 statistics_proxy_->OnAdaptationChanged(
1044 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1045 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001046
asapersson0944a802017-04-07 00:57:58 -07001047 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001048 statistics_proxy_->OnAdaptationChanged(
1049 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1050 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001051 fake_clock_.AdvanceTimeMilliseconds(6000);
Niels Möller213618e2018-07-24 09:29:58 +02001052 statistics_proxy_->OnAdaptationChanged(
1053 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1054 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001055 fake_clock_.AdvanceTimeMilliseconds(9000);
1056
1057 // Switch content type, real-time stats should be updated.
1058 VideoEncoderConfig config;
1059 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001060 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001061 EXPECT_METRIC_EQ(
1062 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1063 EXPECT_METRIC_EQ(
1064 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1065 EXPECT_METRIC_EQ(
1066 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001067
asapersson0944a802017-04-07 00:57:58 -07001068 // First RTP packet sent, scaling enabled.
1069 UpdateDataCounters(kFirstSsrc);
Niels Möller213618e2018-07-24 09:29:58 +02001070 statistics_proxy_->OnAdaptationChanged(
1071 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1072 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001073
asapersson0944a802017-04-07 00:57:58 -07001074 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Niels Möller213618e2018-07-24 09:29:58 +02001075 statistics_proxy_->OnAdaptationChanged(
1076 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1077 quality_counts);
1078 statistics_proxy_->OnAdaptationChanged(
1079 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1080 quality_counts);
1081 statistics_proxy_->OnAdaptationChanged(
1082 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1083 quality_counts);
1084 statistics_proxy_->OnAdaptationChanged(
1085 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1086 quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001087 fake_clock_.AdvanceTimeMilliseconds(120000);
1088
1089 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001090 EXPECT_METRIC_EQ(1,
1091 metrics::NumSamples(
1092 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1093 EXPECT_METRIC_EQ(
1094 1, metrics::NumEvents(
1095 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1096 EXPECT_METRIC_EQ(
1097 0, metrics::NumSamples(
1098 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001099}
1100
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001101TEST_F(SendStatisticsProxyTest,
1102 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
1103 SendStatisticsProxy::AdaptationSteps cpu_counts;
1104 SendStatisticsProxy::AdaptationSteps quality_counts;
1105
1106 cpu_counts.num_resolution_reductions = 1;
1107
1108 statistics_proxy_->OnAdaptationChanged(
1109 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1110 quality_counts);
1111
1112 EXPECT_EQ(QualityLimitationReason::kCpu,
1113 statistics_proxy_->GetStats().quality_limitation_reason);
1114}
1115
1116TEST_F(SendStatisticsProxyTest,
1117 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
1118 SendStatisticsProxy::AdaptationSteps cpu_counts;
1119 SendStatisticsProxy::AdaptationSteps quality_counts;
1120
1121 cpu_counts.num_framerate_reductions = 1;
1122
1123 statistics_proxy_->OnAdaptationChanged(
1124 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1125 quality_counts);
1126
1127 EXPECT_EQ(QualityLimitationReason::kCpu,
1128 statistics_proxy_->GetStats().quality_limitation_reason);
1129}
1130
1131TEST_F(SendStatisticsProxyTest,
1132 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
1133 SendStatisticsProxy::AdaptationSteps cpu_counts;
1134 SendStatisticsProxy::AdaptationSteps quality_counts;
1135
1136 quality_counts.num_resolution_reductions = 1;
1137
1138 statistics_proxy_->OnAdaptationChanged(
1139 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1140 quality_counts);
1141
1142 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1143 statistics_proxy_->GetStats().quality_limitation_reason);
1144}
1145
1146TEST_F(SendStatisticsProxyTest,
1147 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
1148 SendStatisticsProxy::AdaptationSteps cpu_counts;
1149 SendStatisticsProxy::AdaptationSteps quality_counts;
1150
1151 quality_counts.num_framerate_reductions = 1;
1152
1153 statistics_proxy_->OnAdaptationChanged(
1154 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1155 quality_counts);
1156
1157 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1158 statistics_proxy_->GetStats().quality_limitation_reason);
1159}
1160
1161TEST_F(SendStatisticsProxyTest,
1162 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
1163 SendStatisticsProxy::AdaptationSteps cpu_counts;
1164 SendStatisticsProxy::AdaptationSteps quality_counts;
1165
1166 cpu_counts.num_resolution_reductions = 1;
1167 quality_counts.num_resolution_reductions = 1;
1168
1169 // Even if the last adaptation reason is kCpu, if the counters indicate being
1170 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
1171 statistics_proxy_->OnAdaptationChanged(
1172 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1173 quality_counts);
1174
1175 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1176 statistics_proxy_->GetStats().quality_limitation_reason);
1177}
1178
1179TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
1180 SendStatisticsProxy::AdaptationSteps cpu_counts;
1181 SendStatisticsProxy::AdaptationSteps quality_counts;
1182
1183 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1184 // due to "none" being the default value.
1185 cpu_counts.num_resolution_reductions = 1;
1186 statistics_proxy_->OnAdaptationChanged(
1187 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1188 quality_counts);
1189 // Go back to not being limited.
1190 cpu_counts.num_resolution_reductions = 0;
1191 statistics_proxy_->OnAdaptationChanged(
1192 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1193 quality_counts);
1194
1195 EXPECT_EQ(QualityLimitationReason::kNone,
1196 statistics_proxy_->GetStats().quality_limitation_reason);
1197}
1198
1199TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
1200 SendStatisticsProxy::AdaptationSteps cpu_counts;
1201 SendStatisticsProxy::AdaptationSteps quality_counts;
1202
1203 // Not limited for 3000 ms
1204 fake_clock_.AdvanceTimeMilliseconds(3000);
1205 // CPU limited for 2000 ms
1206 cpu_counts.num_resolution_reductions = 1;
1207 statistics_proxy_->OnAdaptationChanged(
1208 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1209 quality_counts);
1210 fake_clock_.AdvanceTimeMilliseconds(2000);
1211 // Bandwidth limited for 1000 ms
1212 cpu_counts.num_resolution_reductions = 0;
1213 quality_counts.num_resolution_reductions = 1;
1214 statistics_proxy_->OnAdaptationChanged(
1215 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
1216 quality_counts);
1217 fake_clock_.AdvanceTimeMilliseconds(1000);
1218 // CPU limited for another 2000 ms
1219 cpu_counts.num_resolution_reductions = 1;
1220 quality_counts.num_resolution_reductions = 0;
1221 statistics_proxy_->OnAdaptationChanged(
1222 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1223 quality_counts);
1224 fake_clock_.AdvanceTimeMilliseconds(2000);
1225
1226 auto quality_limitation_durations_ms =
1227 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1228
1229 EXPECT_EQ(3000,
1230 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1231 EXPECT_EQ(4000,
1232 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1233 EXPECT_EQ(
1234 1000,
1235 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1236 EXPECT_EQ(0,
1237 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1238}
1239
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001240TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1241 EXPECT_EQ(
1242 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1243}
1244
1245TEST_F(SendStatisticsProxyTest,
1246 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1247 VideoCodec codec;
1248 VideoBitrateAllocation allocation;
1249 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1250 EXPECT_EQ(
1251 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1252}
1253
1254TEST_F(SendStatisticsProxyTest,
1255 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1256 VideoCodec codec;
1257 codec.simulcastStream[0].active = true;
1258 codec.simulcastStream[1].active = true;
1259 codec.simulcastStream[2].active = true;
1260 VideoBitrateAllocation allocation;
1261 allocation.SetBitrate(0, 0, 100);
1262 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1263 EXPECT_EQ(
1264 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1265}
1266
1267TEST_F(SendStatisticsProxyTest,
1268 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1269 VideoCodec codec;
1270 codec.simulcastStream[0].active = true;
1271 codec.simulcastStream[1].active = true;
1272 codec.simulcastStream[2].active = true;
1273 VideoBitrateAllocation allocation;
1274 allocation.SetBitrate(0, 0, 100);
1275 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1276 allocation.SetBitrate(1, 0, 100);
1277 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1278 EXPECT_EQ(
1279 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1280}
1281
1282TEST_F(SendStatisticsProxyTest,
1283 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1284 VideoCodec codec;
1285 codec.simulcastStream[0].active = true;
1286 VideoBitrateAllocation allocation;
1287 allocation.SetBitrate(0, 0, 100);
1288 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1289 // Layer 0 got more bandwidth, but still only one layer on
1290 allocation.SetBitrate(0, 0, 200);
1291 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1292 EXPECT_EQ(
1293 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1294}
1295
1296TEST_F(SendStatisticsProxyTest,
1297 QualityLimitationResolutionChangesWithTogglingLayers) {
1298 VideoCodec codec;
1299 codec.simulcastStream[0].active = true;
1300 codec.simulcastStream[1].active = true;
1301 codec.simulcastStream[2].active = true;
1302 VideoBitrateAllocation allocation;
1303 allocation.SetBitrate(0, 0, 100);
1304 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1305 EXPECT_EQ(
1306 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1307 allocation.SetBitrate(1, 0, 300);
1308 allocation.SetBitrate(2, 0, 500);
1309 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1310 EXPECT_EQ(
1311 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1312 // Layer 2 off
1313 allocation.SetBitrate(2, 0, 0);
1314 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1315 EXPECT_EQ(
1316 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1317 // Layer 2 back on
1318 allocation.SetBitrate(2, 0, 500);
1319 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1320 EXPECT_EQ(
1321 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1322 allocation.SetBitrate(0, 0, 0);
1323 allocation.SetBitrate(1, 0, 0);
1324 allocation.SetBitrate(2, 0, 0);
1325 // All layers off
1326 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1327 EXPECT_EQ(
1328 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1329}
1330
1331TEST_F(SendStatisticsProxyTest,
1332 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1333 VideoCodec codec;
1334 // 3 layers
1335 codec.simulcastStream[0].active = true;
1336 codec.simulcastStream[1].active = true;
1337 codec.simulcastStream[2].active = true;
1338 VideoBitrateAllocation allocation;
1339 allocation.SetBitrate(0, 0, 500);
1340 allocation.SetBitrate(1, 0, 500);
1341 allocation.SetBitrate(2, 0, 500);
1342 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1343 EXPECT_EQ(
1344 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1345
1346 // Down to one layer now, triggered by a config change
1347 codec.numberOfSimulcastStreams = 1;
1348 codec.simulcastStream[1].active = false;
1349 codec.simulcastStream[2].active = false;
1350 allocation.SetBitrate(0, 0, 100);
1351 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1352 EXPECT_EQ(
1353 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1354
1355 // Up to 3 layers again.
1356 codec.numberOfSimulcastStreams = 3;
1357 codec.simulcastStream[1].active = true;
1358 codec.simulcastStream[2].active = true;
1359 allocation.SetBitrate(0, 0, 500);
1360 allocation.SetBitrate(1, 0, 500);
1361 allocation.SetBitrate(2, 0, 500);
1362 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1363 EXPECT_EQ(
1364 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1365}
1366
1367TEST_F(SendStatisticsProxyTest,
1368 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1369 VideoCodec codec;
1370 codec.simulcastStream[0].active = true;
1371 codec.spatialLayers[0].active = true;
1372 codec.spatialLayers[1].active = true;
1373 codec.spatialLayers[2].active = true;
1374 VideoBitrateAllocation allocation;
1375 allocation.SetBitrate(0, 0, 500);
1376 allocation.SetBitrate(1, 0, 500);
1377 allocation.SetBitrate(2, 0, 500);
1378 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1379 EXPECT_EQ(
1380 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1381
1382 // Down to one layer now, triggered by a config change
1383 codec.spatialLayers[1].active = false;
1384 codec.spatialLayers[2].active = false;
1385 allocation.SetBitrate(0, 0, 100);
1386 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1387 EXPECT_EQ(
1388 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1389
1390 // Up to 3 layers again.
1391 codec.spatialLayers[1].active = true;
1392 codec.spatialLayers[2].active = true;
1393 allocation.SetBitrate(0, 0, 500);
1394 allocation.SetBitrate(1, 0, 500);
1395 allocation.SetBitrate(2, 0, 500);
1396 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1397 EXPECT_EQ(
1398 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1399}
1400
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001401TEST_F(SendStatisticsProxyTest,
1402 QualityLimitationReasonsAreCorrectForContentType) {
1403 // Realtime case.
1404 // Configure two streams.
1405 VideoEncoderConfig config;
1406 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1407 config.number_of_streams = 2;
1408 VideoStream stream1;
1409 stream1.width = kWidth / 2;
1410 stream1.height = kHeight / 2;
1411 VideoStream stream2;
1412 stream2.width = kWidth;
1413 stream2.height = kHeight;
1414 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1415 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1416 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1417 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1418 QualityLimitationReason::kNone);
1419 // Bw disabled one layer.
1420 VideoCodec codec;
1421 codec.numberOfSimulcastStreams = 2;
1422 codec.simulcastStream[0].active = true;
1423 codec.simulcastStream[1].active = true;
1424 VideoBitrateAllocation allocation;
1425 // Some positive bitrate only on the first stream.
1426 allocation.SetBitrate(0, 0, 10000);
1427 allocation.SetBitrate(1, 0, 0);
1428 allocation.set_bw_limited(true);
1429 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1430 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1431 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1432 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1433 QualityLimitationReason::kBandwidth);
1434 // Bw enabled all layers.
1435 allocation.SetBitrate(1, 0, 10000);
1436 allocation.set_bw_limited(false);
1437 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1438 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1439 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1440 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1441 QualityLimitationReason::kNone);
1442
1443 // Screencast case
1444 // Configure two streams.
1445 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1446 config.number_of_streams = 2;
1447 stream1.width = kWidth;
1448 stream1.height = kHeight;
1449 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1450 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1451 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1452 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1453 QualityLimitationReason::kNone);
1454 // Bw disabled one layer.
1455 // Some positive bitrate only on the second stream.
1456 allocation.SetBitrate(0, 0, 10000);
1457 allocation.SetBitrate(1, 0, 0);
1458 allocation.set_bw_limited(true);
1459 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1460 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1461 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1462 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1463 QualityLimitationReason::kBandwidth);
1464 // Bw enabled all layers.
1465 allocation.SetBitrate(1, 0, 10000);
1466 allocation.set_bw_limited(false);
1467 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1468 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1469 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1470 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1471 QualityLimitationReason::kNone);
1472}
1473
asapersson59bac1a2016-01-07 23:36:00 -08001474TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001475 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001476 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1477
Pera48ddb72016-09-29 11:48:50 +02001478 // No switch, stats should not be updated.
1479 VideoEncoderConfig config;
1480 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001481 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001482 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001483
1484 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001485 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001486 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001487 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001488}
1489
asapersson320e45a2016-11-29 01:40:35 -08001490TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1491 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1492 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001493
asapersson320e45a2016-11-29 01:40:35 -08001494 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001495 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1496 EXPECT_METRIC_EQ(
1497 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1498 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1499 EXPECT_METRIC_EQ(
1500 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001501}
1502
1503TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001504 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001505 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001506 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1507 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1508 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001509 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001510
1511 // Not enough samples, stats should not be updated.
1512 for (int i = 0; i < kMinSamples - 1; ++i) {
1513 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001514 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001515 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1516 }
Åsa Persson0122e842017-10-16 12:19:23 +02001517 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001518 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1519 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001520
1521 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001522 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001523 for (int i = 0; i < kMinSamples; ++i) {
1524 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001525 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001526 encoded_image._encodedWidth = kWidth;
1527 encoded_image._encodedHeight = kHeight;
1528 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1529 encoded_image._encodedWidth = kWidth / 2;
1530 encoded_image._encodedHeight = kHeight / 2;
1531 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1532 }
1533
asapersson320e45a2016-11-29 01:40:35 -08001534 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001535 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1536 EXPECT_METRIC_EQ(
1537 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1538 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1539 EXPECT_METRIC_EQ(
1540 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001541}
1542
1543TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1544 const int kFps = 20;
1545 const int kMinPeriodicSamples = 6;
1546 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1547 for (int i = 0; i <= frames; ++i) {
1548 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1549 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1550 }
1551 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001552 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1553 EXPECT_METRIC_EQ(
1554 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001555}
1556
1557TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1558 EncodedImage encoded_image;
1559 const int kFps = 20;
1560 const int kMinPeriodicSamples = 6;
1561 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001562 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001563 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001564 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001565 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1566 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001567 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1568 }
1569 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001570 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1571 EXPECT_METRIC_EQ(
1572 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001573}
1574
1575TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1576 const int kFps = 20;
1577 const int kSuspendTimeMs = 10000;
1578 const int kMinPeriodicSamples = 6;
1579 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1580 for (int i = 0; i < frames; ++i) {
1581 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1582 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1583 }
1584 // Suspend.
1585 statistics_proxy_->OnSuspendChange(true);
1586 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1587
1588 for (int i = 0; i < frames; ++i) {
1589 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1590 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1591 }
1592 // Suspended time interval should not affect the framerate.
1593 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001594 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1595 EXPECT_METRIC_EQ(
1596 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001597}
1598
1599TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1600 EncodedImage encoded_image;
1601 const int kFps = 20;
1602 const int kSuspendTimeMs = 10000;
1603 const int kMinPeriodicSamples = 6;
1604 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001605 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001606 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001607 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001608 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1609 }
1610 // Suspend.
1611 statistics_proxy_->OnSuspendChange(true);
1612 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1613
Åsa Persson0122e842017-10-16 12:19:23 +02001614 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001615 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001616 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001617 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1618 }
1619 // Suspended time interval should not affect the framerate.
1620 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001621 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1622 EXPECT_METRIC_EQ(
1623 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001624}
1625
asaperssonf4e44af2017-04-19 02:01:06 -07001626TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02001627 SendStatisticsProxy::AdaptationSteps cpu_counts;
1628 SendStatisticsProxy::AdaptationSteps quality_counts;
1629 cpu_counts.num_resolution_reductions = absl::nullopt;
1630 statistics_proxy_->OnAdaptationChanged(
1631 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1632 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001633
1634 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1635 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1636
1637 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001638 EXPECT_METRIC_EQ(
1639 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001640}
1641
1642TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Niels Möller213618e2018-07-24 09:29:58 +02001643 SendStatisticsProxy::AdaptationSteps cpu_counts;
1644 SendStatisticsProxy::AdaptationSteps quality_counts;
1645 cpu_counts.num_resolution_reductions = 0;
1646 statistics_proxy_->OnAdaptationChanged(
1647 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
1648 quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -07001649
perkj803d97f2016-11-01 11:45:46 -07001650 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1651 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1652
Niels Möller213618e2018-07-24 09:29:58 +02001653 cpu_counts.num_resolution_reductions = 1;
1654 statistics_proxy_->OnAdaptationChanged(
1655 VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
1656 quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001657
1658 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1659 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1660
1661 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001662 EXPECT_METRIC_EQ(
1663 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1664 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001665 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1666}
1667
asapersson4374a092016-07-27 00:39:09 -07001668TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1669 const int64_t kTimeSec = 3;
1670 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1671 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001672 EXPECT_METRIC_EQ(
1673 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1674 EXPECT_METRIC_EQ(
1675 1,
1676 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001677}
1678
1679TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1680 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1681 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001682 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001683}
1684
asapersson66d4b372016-12-19 06:50:53 -08001685TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1686 // First RTP packet sent.
1687 UpdateDataCounters(kFirstSsrc);
1688
1689 // Min runtime has passed.
1690 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1691 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001692 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1693 EXPECT_METRIC_EQ(1,
1694 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001695}
1696
1697TEST_F(SendStatisticsProxyTest,
1698 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1699 // First RTP packet sent.
1700 UpdateDataCounters(kFirstSsrc);
1701
1702 // Min runtime has not passed.
1703 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1704 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001705 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1706 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001707}
1708
1709TEST_F(SendStatisticsProxyTest,
1710 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1711 // First RTP packet not sent.
1712 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1713 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001714 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001715}
1716
1717TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1718 // First RTP packet sent and min runtime passed.
1719 UpdateDataCounters(kFirstSsrc);
1720
1721 // No change. Video: 10000 ms, paused: 0 ms (0%).
1722 statistics_proxy_->OnSetEncoderTargetRate(50000);
1723 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1724 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1725
1726 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001727 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1728 EXPECT_METRIC_EQ(1,
1729 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1730 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1731 EXPECT_METRIC_EQ(1,
1732 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001733}
1734
1735TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1736 // First RTP packet sent and min runtime passed.
1737 UpdateDataCounters(kFirstSsrc);
1738
1739 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1740 statistics_proxy_->OnSetEncoderTargetRate(50000);
1741 fake_clock_.AdvanceTimeMilliseconds(7000);
1742 statistics_proxy_->OnSetEncoderTargetRate(0);
1743 fake_clock_.AdvanceTimeMilliseconds(3000);
1744 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1745
1746 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001747 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1748 EXPECT_METRIC_EQ(1,
1749 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1750 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1751 EXPECT_METRIC_EQ(1,
1752 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001753}
1754
1755TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1756 // First RTP packet sent.
1757 UpdateDataCounters(kFirstSsrc);
1758
1759 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1760 statistics_proxy_->OnSetEncoderTargetRate(0);
1761 fake_clock_.AdvanceTimeMilliseconds(1000);
1762 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1763 fake_clock_.AdvanceTimeMilliseconds(7000);
1764 statistics_proxy_->OnSetEncoderTargetRate(60000);
1765 fake_clock_.AdvanceTimeMilliseconds(3000);
1766 statistics_proxy_->OnSetEncoderTargetRate(0);
1767 fake_clock_.AdvanceTimeMilliseconds(250);
1768 statistics_proxy_->OnSetEncoderTargetRate(0);
1769 fake_clock_.AdvanceTimeMilliseconds(750);
1770 statistics_proxy_->OnSetEncoderTargetRate(60000);
1771 fake_clock_.AdvanceTimeMilliseconds(5000);
1772 statistics_proxy_->OnSetEncoderTargetRate(50000);
1773 fake_clock_.AdvanceTimeMilliseconds(4000);
1774 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1775
1776 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001777 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1778 EXPECT_METRIC_EQ(1,
1779 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1780 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1781 EXPECT_METRIC_EQ(1,
1782 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001783}
1784
1785TEST_F(SendStatisticsProxyTest,
1786 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1787 // First RTP packet sent.
1788 UpdateDataCounters(kFirstSsrc);
1789 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1790
1791 // Min runtime has not passed.
1792 statistics_proxy_->OnSetEncoderTargetRate(50000);
1793 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1794 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1795
1796 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001797 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001798}
1799
asapersson118ef002016-03-31 00:00:19 -07001800TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001801 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001802 CodecSpecificInfo codec_info;
1803 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001804
perkj803d97f2016-11-01 11:45:46 -07001805 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001806 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001807 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001808 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001809 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001810 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001811 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001812 }
1813 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001814 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1815 EXPECT_METRIC_EQ(
1816 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1817 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1818 EXPECT_METRIC_EQ(
1819 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001820}
1821
1822TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1823 VideoSendStream::Config config(nullptr);
1824 config.rtp.ssrcs.push_back(kFirstSsrc);
1825 statistics_proxy_.reset(new SendStatisticsProxy(
1826 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1827
asapersson118ef002016-03-31 00:00:19 -07001828 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001829 CodecSpecificInfo codec_info;
1830 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001831
perkj803d97f2016-11-01 11:45:46 -07001832 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001833 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001834 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001835 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001836 }
1837 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001838 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1839 EXPECT_METRIC_EQ(1,
1840 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001841}
1842
asapersson5265fed2016-04-18 02:58:47 -07001843TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001844 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001845 CodecSpecificInfo codec_info;
1846 codec_info.codecType = kVideoCodecVP9;
1847 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001848
perkj803d97f2016-11-01 11:45:46 -07001849 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001850 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001851 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001852 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001853 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001854 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001855 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001856 }
1857 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001858 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1859 EXPECT_METRIC_EQ(
1860 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1861 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1862 EXPECT_METRIC_EQ(
1863 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001864}
1865
1866TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1867 VideoSendStream::Config config(nullptr);
1868 config.rtp.ssrcs.push_back(kFirstSsrc);
1869 statistics_proxy_.reset(new SendStatisticsProxy(
1870 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1871
asapersson5265fed2016-04-18 02:58:47 -07001872 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001873 CodecSpecificInfo codec_info;
1874 codec_info.codecType = kVideoCodecVP9;
1875 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001876
perkj803d97f2016-11-01 11:45:46 -07001877 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001878 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001879 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001880 }
1881 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001882 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1883 EXPECT_METRIC_EQ(1,
1884 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001885}
1886
asapersson827cab32016-11-02 09:08:47 -07001887TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1888 EncodedImage encoded_image;
1889 CodecSpecificInfo codec_info;
1890 codec_info.codecType = kVideoCodecH264;
1891
1892 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001893 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001894 encoded_image.qp_ = kQpIdx0;
1895 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001896 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001897 encoded_image.qp_ = kQpIdx1;
1898 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001899 }
1900 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001901 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1902 EXPECT_METRIC_EQ(
1903 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1904 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1905 EXPECT_METRIC_EQ(
1906 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001907}
1908
asapersson4ee70462016-10-31 04:05:12 -07001909TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001910 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1911 // Configure one stream.
1912 VideoEncoderConfig config;
1913 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1914 VideoStream stream1;
1915 stream1.width = kWidth;
1916 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001917 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001918
1919 const int64_t kMaxEncodedFrameWindowMs = 800;
1920 const int kFps = 20;
1921 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1922 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1923 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1924
1925 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001926 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001927 encoded_image._encodedWidth = kWidth;
1928 encoded_image._encodedHeight = kHeight;
1929 for (int i = 0; i < kMinSamples; ++i) {
1930 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001931 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1932 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001933 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001934 }
asapersson4ee70462016-10-31 04:05:12 -07001935
1936 // Histograms are updated when the statistics_proxy_ is deleted.
1937 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001938 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1939 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1940 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1941 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001942}
1943
1944TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001945 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1946 // Configure two streams.
1947 VideoEncoderConfig config;
1948 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1949 VideoStream stream1;
1950 stream1.width = kWidth / 2;
1951 stream1.height = kHeight / 2;
1952 VideoStream stream2;
1953 stream2.width = kWidth;
1954 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001955 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001956
1957 const int64_t kMaxEncodedFrameWindowMs = 800;
1958 const int kFps = 20;
1959 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1960 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1961 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1962
1963 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001964 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001965 for (int i = 0; i < kMinSamples; ++i) {
1966 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001967 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1968 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001969 encoded_image._encodedWidth = kWidth;
1970 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001971 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001972 encoded_image._encodedWidth = kWidth / 2;
1973 encoded_image._encodedHeight = kHeight / 2;
1974 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1975 }
asapersson4ee70462016-10-31 04:05:12 -07001976
1977 // Histograms are updated when the statistics_proxy_ is deleted.
1978 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001979 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1980 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1981 EXPECT_METRIC_EQ(
1982 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
1983 0));
asapersson4ee70462016-10-31 04:05:12 -07001984 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01001985 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1986 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001987}
1988
1989TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001990 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1991 // Configure two streams.
1992 VideoEncoderConfig config;
1993 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1994 VideoStream stream1;
1995 stream1.width = kWidth / 2;
1996 stream1.height = kHeight / 2;
1997 VideoStream stream2;
1998 stream2.width = kWidth;
1999 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002000 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002001
2002 const int64_t kMaxEncodedFrameWindowMs = 800;
2003 const int kFps = 20;
2004 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2005 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2006 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2007
2008 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002009 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002010 encoded_image._encodedWidth = kWidth / 2;
2011 encoded_image._encodedHeight = kHeight / 2;
2012 for (int i = 0; i < kMinSamples; ++i) {
2013 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002014 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2015 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002016 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002017 }
asapersson4ee70462016-10-31 04:05:12 -07002018
2019 // Histograms are updated when the statistics_proxy_ is deleted.
2020 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002021 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2022 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2023 EXPECT_METRIC_EQ(
2024 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2025 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002026 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002027 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2028 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2029 EXPECT_METRIC_EQ(
2030 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2031 1));
asapersson4ee70462016-10-31 04:05:12 -07002032}
2033
2034TEST_F(SendStatisticsProxyTest,
2035 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Niels Möller213618e2018-07-24 09:29:58 +02002036 SendStatisticsProxy::AdaptationSteps cpu_counts;
2037 SendStatisticsProxy::AdaptationSteps quality_counts;
2038 quality_counts.num_resolution_reductions = absl::nullopt;
2039 statistics_proxy_->OnAdaptationChanged(
2040 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2041 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002042 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002043 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002044 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002045 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002046
2047 // Histograms are updated when the statistics_proxy_ is deleted.
2048 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002049 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002050 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002051 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2052 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002053}
2054
2055TEST_F(SendStatisticsProxyTest,
2056 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Niels Möller213618e2018-07-24 09:29:58 +02002057 SendStatisticsProxy::AdaptationSteps cpu_counts;
2058 SendStatisticsProxy::AdaptationSteps quality_counts;
2059 quality_counts.num_resolution_reductions = 0;
2060 statistics_proxy_->OnAdaptationChanged(
2061 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2062 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002063 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002064 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002065 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002066 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002067
2068 // Histograms are updated when the statistics_proxy_ is deleted.
2069 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002070 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002071 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002072 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2073 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002074 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002075 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2076 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002077}
2078
2079TEST_F(SendStatisticsProxyTest,
2080 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2081 const int kDownscales = 2;
Niels Möller213618e2018-07-24 09:29:58 +02002082 SendStatisticsProxy::AdaptationSteps cpu_counts;
2083 SendStatisticsProxy::AdaptationSteps quality_counts;
2084 quality_counts.num_resolution_reductions = kDownscales;
2085 statistics_proxy_->OnAdaptationChanged(
2086 VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
2087 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002088 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002089 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002090 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002091 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002092 // Histograms are updated when the statistics_proxy_ is deleted.
2093 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002094 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002095 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002096 EXPECT_METRIC_EQ(
2097 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2098 100));
asapersson4ee70462016-10-31 04:05:12 -07002099 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002100 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2101 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2102 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002103 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2104 kDownscales));
2105}
2106
2107TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2108 // Initially false.
2109 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002110
Åsa Perssonaa329e72017-12-15 15:54:44 +01002111 // Configure two streams.
2112 VideoEncoderConfig config;
2113 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002114 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002115 VideoStream stream1;
2116 stream1.width = kWidth / 2;
2117 stream1.height = kHeight / 2;
2118 VideoStream stream2;
2119 stream2.width = kWidth;
2120 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002121 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002122
Åsa Perssonaa329e72017-12-15 15:54:44 +01002123 // One stream encoded.
2124 EncodedImage encoded_image;
2125 encoded_image._encodedWidth = kWidth / 2;
2126 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002127
2128 // Resolution scaled due to quality.
Niels Möller213618e2018-07-24 09:29:58 +02002129 SendStatisticsProxy::AdaptationSteps cpu_counts;
2130 SendStatisticsProxy::AdaptationSteps quality_counts;
2131 quality_counts.num_resolution_reductions = 1;
2132 statistics_proxy_->OnAdaptationChanged(
2133 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2134 quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002135 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2136 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002137
2138 // Adapt up.
2139 quality_counts.num_resolution_reductions = 0;
2140 statistics_proxy_->OnAdaptationChanged(
2141 VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
2142 quality_counts);
2143 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2144 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2145
2146 // Bw disabled one layer.
2147 VideoCodec codec;
2148 codec.numberOfSimulcastStreams = 2;
2149 codec.simulcastStream[0].active = true;
2150 codec.simulcastStream[1].active = true;
2151 VideoBitrateAllocation allocation;
2152 // Some positive bitrate only on the second stream.
2153 allocation.SetBitrate(1, 0, 10000);
2154 allocation.set_bw_limited(true);
2155 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2156 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002157
2158 // Revert for the next test.
2159 allocation.set_bw_limited(false);
2160 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2161 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2162
2163 // Internal encoder scaler reduced resolution.
2164 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2165 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002166}
2167
asapersson66d4b372016-12-19 06:50:53 -08002168TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2169 // Initially zero.
2170 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2171
2172 const int kBitrate = 100000;
2173 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2174 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2175
2176 statistics_proxy_->OnSetEncoderTargetRate(0);
2177 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2178}
2179
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002180TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002181 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002182 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2183 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002184 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002185 // From RtcpStatisticsCallback.
2186 RtcpStatistics rtcp_stats;
2187 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002188 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002189
2190 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002191 uint32_t total = 0;
2192 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002193 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002194 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002195
2196 // From FrameCountObserver.
2197 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002198 FrameCounts frame_counts;
2199 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002200 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002201
2202 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2203 EXPECT_TRUE(stats.substreams.empty());
2204}
2205
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002206TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2207 static const int kEncodedWidth = 123;
2208 static const int kEncodedHeight = 81;
2209 EncodedImage encoded_image;
2210 encoded_image._encodedWidth = kEncodedWidth;
2211 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002212 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002213
kjellander02b3d272016-04-20 05:05:54 -07002214 CodecSpecificInfo codec_info;
2215 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002216
kjellander02b3d272016-04-20 05:05:54 -07002217 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002218 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002219 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002220
2221 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002222 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2223 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2224 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2225 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002226
2227 // Forward almost to timeout, this should not have removed stats.
2228 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2229 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002230 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2231 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002232
2233 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2234 // resolution still times out (no global timeout for all stats).
2235 RtcpStatistics rtcp_statistics;
2236 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2237 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2238
2239 // Report stats for second SSRC to make sure it's not outdated along with the
2240 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002241 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002242
2243 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2244 // reported, but substream 1 should.
2245 fake_clock_.AdvanceTimeMilliseconds(1);
2246 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002247 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2248 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2249 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2250 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002251}
2252
Peter Boström20f3f942015-05-15 11:33:39 +02002253TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2254 static const int kEncodedWidth = 123;
2255 static const int kEncodedHeight = 81;
2256 EncodedImage encoded_image;
2257 encoded_image._encodedWidth = kEncodedWidth;
2258 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002259 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002260
kjellander02b3d272016-04-20 05:05:54 -07002261 CodecSpecificInfo codec_info;
2262 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002263
kjellander02b3d272016-04-20 05:05:54 -07002264 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002265 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002266 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002267
2268 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2269 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2270 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2271 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2272 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2273 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2274}
2275
2276TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002277 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002278 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2279 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2280 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2281
2282 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2283
2284 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002285 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002286 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002287 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002288 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2289 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2290 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2291}
2292
sprang07fb9be2016-02-24 07:55:00 -08002293TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2294 RtcpPacketTypeCounterObserver* proxy =
2295 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2296 RtcpPacketTypeCounter counters;
2297 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2298 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2299 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2300
2301 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2302
2303 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2304 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2305 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2306 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2307 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2308
2309 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2310 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2311
2312 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002313 VideoEncoderConfig config;
2314 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002315 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002316
Ying Wangef3998f2019-12-09 13:06:53 +01002317 EXPECT_METRIC_EQ(
2318 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2319 EXPECT_METRIC_EQ(
2320 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2321 EXPECT_METRIC_EQ(
2322 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2323 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2324 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002325
2326 const int kRate = 60 * 2; // Packets per minute with two streams.
2327
Ying Wangef3998f2019-12-09 13:06:53 +01002328 EXPECT_METRIC_EQ(
2329 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2330 1 * kRate));
2331 EXPECT_METRIC_EQ(
2332 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2333 2 * kRate));
2334 EXPECT_METRIC_EQ(
2335 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2336 3 * kRate));
2337 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002338 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2339 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002340
2341 // New start time but same counter values.
2342 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2343 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2344
2345 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2346
2347 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2348 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2349 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2350 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2351 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2352
2353 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2354 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2355
2356 SetUp(); // Reset stats proxy also causes histograms to be reported.
2357
Ying Wangef3998f2019-12-09 13:06:53 +01002358 EXPECT_METRIC_EQ(
2359 1, metrics::NumSamples(
2360 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2361 EXPECT_METRIC_EQ(1,
2362 metrics::NumSamples(
2363 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2364 EXPECT_METRIC_EQ(1,
2365 metrics::NumSamples(
2366 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2367 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002368 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002369 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2370
Ying Wangef3998f2019-12-09 13:06:53 +01002371 EXPECT_METRIC_EQ(
2372 1,
2373 metrics::NumEvents(
2374 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2375 EXPECT_METRIC_EQ(
2376 1,
2377 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2378 2 * kRate));
2379 EXPECT_METRIC_EQ(
2380 1,
2381 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2382 3 * kRate));
2383 EXPECT_METRIC_EQ(
2384 1, metrics::NumEvents(
2385 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2386 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002387}
2388
Henrik Boströmf45ca372020-03-24 13:30:50 +01002389TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2390 StreamDataCountersCallback* proxy =
2391 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2392 StreamDataCounters counters;
2393 proxy->DataCountersUpdated(counters, kFirstSsrc);
2394 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2395
2396 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2397 VideoSendStream::StreamStats::StreamType::kRtx);
2398 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2399 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2400 VideoSendStream::StreamStats::StreamType::kRtx);
2401 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2402}
2403
asaperssona6a699a2016-11-25 03:52:46 -08002404TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2405 statistics_proxy_.reset(
2406 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2407 VideoEncoderConfig::ContentType::kRealtimeVideo));
2408
2409 StreamDataCountersCallback* proxy =
2410 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2411 StreamDataCounters counters;
2412 proxy->DataCountersUpdated(counters, kFirstSsrc);
2413 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2414
Henrik Boströmf45ca372020-03-24 13:30:50 +01002415 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2416 VideoSendStream::StreamStats::StreamType::kFlexfec);
2417 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2418 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2419 VideoSendStream::StreamStats::StreamType::kFlexfec);
2420 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002421}
2422
2423TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2424 statistics_proxy_.reset(
2425 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2426 VideoEncoderConfig::ContentType::kRealtimeVideo));
2427
2428 StreamDataCountersCallback* proxy =
2429 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002430 StreamDataCounters counters;
2431 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002432
asapersson93e1e232017-02-06 05:18:35 -08002433 const int kMinRequiredPeriodSamples = 8;
2434 const int kPeriodIntervalMs = 2000;
2435 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2436 counters.transmitted.packets += 20;
2437 counters.transmitted.header_bytes += 500;
2438 counters.transmitted.padding_bytes += 1000;
2439 counters.transmitted.payload_bytes += 2000;
2440 counters.retransmitted.packets += 2;
2441 counters.retransmitted.header_bytes += 25;
2442 counters.retransmitted.padding_bytes += 100;
2443 counters.retransmitted.payload_bytes += 250;
2444 counters.fec = counters.retransmitted;
2445 rtx_counters.transmitted = counters.transmitted;
2446 // Advance one interval and update counters.
2447 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2448 proxy->DataCountersUpdated(counters, kFirstSsrc);
2449 proxy->DataCountersUpdated(counters, kSecondSsrc);
2450 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2451 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2452 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2453 }
asaperssona6a699a2016-11-25 03:52:46 -08002454
asaperssona6a699a2016-11-25 03:52:46 -08002455 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002456 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002457 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2458 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002459 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002460 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2461 EXPECT_METRIC_EQ(1,
2462 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002463 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002464 EXPECT_METRIC_EQ(1,
2465 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2466 EXPECT_METRIC_EQ(
2467 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002468 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002469 EXPECT_METRIC_EQ(
2470 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2471 EXPECT_METRIC_EQ(
2472 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002473 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002474 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2475 EXPECT_METRIC_EQ(1,
2476 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002477 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002478 EXPECT_METRIC_EQ(
2479 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2480 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002481 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002482}
2483
Erik Språng22c2b482016-03-01 09:40:42 +01002484TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2485 StreamDataCountersCallback* proxy =
2486 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2487 StreamDataCounters counters;
2488 StreamDataCounters rtx_counters;
2489 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002490
asapersson93e1e232017-02-06 05:18:35 -08002491 const int kMinRequiredPeriodSamples = 8;
2492 const int kPeriodIntervalMs = 2000;
2493 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2494 counters.transmitted.packets += 20;
2495 counters.transmitted.header_bytes += 500;
2496 counters.transmitted.padding_bytes += 1000;
2497 counters.transmitted.payload_bytes += 2000;
2498 counters.retransmitted.packets += 2;
2499 counters.retransmitted.header_bytes += 25;
2500 counters.retransmitted.padding_bytes += 100;
2501 counters.retransmitted.payload_bytes += 250;
2502 counters.fec = counters.retransmitted;
2503 rtx_counters.transmitted = counters.transmitted;
2504 // Advance one interval and update counters.
2505 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2506 proxy->DataCountersUpdated(counters, kFirstSsrc);
2507 proxy->DataCountersUpdated(counters, kSecondSsrc);
2508 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2509 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2510 }
Erik Språng22c2b482016-03-01 09:40:42 +01002511
2512 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002513 VideoEncoderConfig config;
2514 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002515 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002516
asapersson93e1e232017-02-06 05:18:35 -08002517 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002518 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2519 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002520 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002521 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2522 EXPECT_METRIC_EQ(1,
2523 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002524 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002525 EXPECT_METRIC_EQ(1,
2526 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2527 EXPECT_METRIC_EQ(
2528 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002529 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002530 EXPECT_METRIC_EQ(
2531 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2532 EXPECT_METRIC_EQ(
2533 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002534 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002535 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2536 EXPECT_METRIC_EQ(1,
2537 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002538 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002539 EXPECT_METRIC_EQ(
2540 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2541 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002542 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002543
asapersson93e1e232017-02-06 05:18:35 -08002544 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002545 // Double counter values, this should result in the same counts as before but
2546 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002547 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2548 counters.transmitted.packets += 20;
2549 counters.transmitted.header_bytes += 500;
2550 counters.transmitted.padding_bytes += 1000;
2551 counters.transmitted.payload_bytes += 2000;
2552 counters.retransmitted.packets += 2;
2553 counters.retransmitted.header_bytes += 25;
2554 counters.retransmitted.padding_bytes += 100;
2555 counters.retransmitted.payload_bytes += 250;
2556 counters.fec = counters.retransmitted;
2557 rtx_counters.transmitted = counters.transmitted;
2558 // Advance one interval and update counters.
2559 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2560 proxy->DataCountersUpdated(counters, kFirstSsrc);
2561 proxy->DataCountersUpdated(counters, kSecondSsrc);
2562 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2563 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2564 }
Erik Språng22c2b482016-03-01 09:40:42 +01002565
asapersson93e1e232017-02-06 05:18:35 -08002566 // Reset stats proxy also causes histograms to be reported.
2567 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002568
asapersson93e1e232017-02-06 05:18:35 -08002569 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002570 EXPECT_METRIC_EQ(
2571 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2572 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002573 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2574 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002575 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002576 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002577 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2578 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002579 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002580 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2581 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2582 EXPECT_METRIC_EQ(
2583 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2584 12));
asapersson93e1e232017-02-06 05:18:35 -08002585 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002586 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2587 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2588 EXPECT_METRIC_EQ(
2589 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2590 16));
asapersson93e1e232017-02-06 05:18:35 -08002591 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002592 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002593 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002594 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2595 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002596 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002597 EXPECT_METRIC_EQ(
2598 1, metrics::NumSamples(
2599 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2600 EXPECT_METRIC_EQ(
2601 1, metrics::NumEvents(
2602 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002603}
Erik Språng22c2b482016-03-01 09:40:42 +01002604
asapersson93e1e232017-02-06 05:18:35 -08002605TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2606 StreamDataCountersCallback* proxy =
2607 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2608 StreamDataCounters counters;
2609 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002610
asapersson93e1e232017-02-06 05:18:35 -08002611 const int kMinRequiredPeriodSamples = 8;
2612 const int kPeriodIntervalMs = 2000;
2613 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2614 counters.transmitted.packets += 20;
2615 counters.transmitted.header_bytes += 500;
2616 counters.transmitted.payload_bytes += 2000;
2617 counters.fec = counters.retransmitted;
2618 // Advance one interval and update counters.
2619 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2620 proxy->DataCountersUpdated(counters, kFirstSsrc);
2621 }
2622
2623 // RTX enabled. No data sent over RTX.
2624 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002625 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2626 EXPECT_METRIC_EQ(1,
2627 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002628}
2629
2630TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2631 VideoSendStream::Config config(nullptr);
2632 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2633 statistics_proxy_.reset(new SendStatisticsProxy(
2634 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2635
2636 StreamDataCountersCallback* proxy =
2637 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2638 StreamDataCounters counters;
2639
2640 const int kMinRequiredPeriodSamples = 8;
2641 const int kPeriodIntervalMs = 2000;
2642 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2643 counters.transmitted.packets += 20;
2644 counters.transmitted.header_bytes += 500;
2645 counters.transmitted.payload_bytes += 2000;
2646 counters.fec = counters.retransmitted;
2647 // Advance one interval and update counters.
2648 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2649 proxy->DataCountersUpdated(counters, kFirstSsrc);
2650 }
2651
2652 // RTX not enabled.
2653 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002654 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002655}
2656
2657TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2658 StreamDataCountersCallback* proxy =
2659 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2660 StreamDataCounters counters;
2661 StreamDataCounters rtx_counters;
2662
2663 const int kMinRequiredPeriodSamples = 8;
2664 const int kPeriodIntervalMs = 2000;
2665 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2666 counters.transmitted.packets += 20;
2667 counters.transmitted.header_bytes += 500;
2668 counters.transmitted.payload_bytes += 2000;
2669 // Advance one interval and update counters.
2670 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2671 proxy->DataCountersUpdated(counters, kFirstSsrc);
2672 }
2673
2674 // FEC enabled. No FEC data sent.
2675 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002676 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2677 EXPECT_METRIC_EQ(1,
2678 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002679}
2680
2681TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2682 VideoSendStream::Config config(nullptr);
2683 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2684 statistics_proxy_.reset(new SendStatisticsProxy(
2685 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2686
2687 StreamDataCountersCallback* proxy =
2688 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2689 StreamDataCounters counters;
2690
2691 const int kMinRequiredPeriodSamples = 8;
2692 const int kPeriodIntervalMs = 2000;
2693 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2694 counters.transmitted.packets += 20;
2695 counters.transmitted.header_bytes += 500;
2696 counters.transmitted.payload_bytes += 2000;
2697 counters.fec = counters.retransmitted;
2698 // Advance one interval and update counters.
2699 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2700 proxy->DataCountersUpdated(counters, kFirstSsrc);
2701 }
2702
2703 // FEC not enabled.
2704 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002705 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002706}
2707
asapersson8d75ac72017-09-15 06:41:15 -07002708TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002709 const std::string kName = "encoderName";
2710 statistics_proxy_->OnEncoderImplementationChanged(kName);
2711 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002712}
2713
Sergey Silkinbb081a62018-09-04 18:34:22 +02002714TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2715 static const int kEncodedWidth = 123;
2716 static const int kEncodedHeight = 81;
2717 EncodedImage encoded_image;
2718 encoded_image._encodedWidth = kEncodedWidth;
2719 encoded_image._encodedHeight = kEncodedHeight;
2720 encoded_image.SetSpatialIndex(0);
2721
2722 CodecSpecificInfo codec_info;
2723 codec_info.codecType = kVideoCodecVP9;
2724
2725 // For first picture, it is expected that low layer updates resolution.
2726 codec_info.codecSpecific.VP9.end_of_picture = false;
2727 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2728 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2729 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2730 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2731
2732 // Top layer updates resolution.
2733 encoded_image._encodedWidth = kEncodedWidth * 2;
2734 encoded_image._encodedHeight = kEncodedHeight * 2;
2735 codec_info.codecSpecific.VP9.end_of_picture = true;
2736 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2737 stats = statistics_proxy_->GetStats();
2738 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2739 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2740
2741 // Low layer of next frame doesn't update resolution.
2742 encoded_image._encodedWidth = kEncodedWidth;
2743 encoded_image._encodedHeight = kEncodedHeight;
2744 codec_info.codecSpecific.VP9.end_of_picture = false;
2745 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2746 stats = statistics_proxy_->GetStats();
2747 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2748 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2749}
2750
asapersson8d75ac72017-09-15 06:41:15 -07002751class ForcedFallbackTest : public SendStatisticsProxyTest {
2752 public:
2753 explicit ForcedFallbackTest(const std::string& field_trials)
2754 : SendStatisticsProxyTest(field_trials) {
2755 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002756 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002757 encoded_image_._encodedWidth = kWidth;
2758 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002759 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002760 }
2761
2762 ~ForcedFallbackTest() override {}
2763
2764 protected:
2765 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002766 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2767
asapersson8d75ac72017-09-15 06:41:15 -07002768 // First frame is not updating stats, insert initial frame.
2769 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2770 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2771 }
2772 for (int i = 0; i < num_frames; ++i) {
2773 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2774 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2775 }
2776 // Add frame to include last time interval.
2777 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2778 }
2779
2780 EncodedImage encoded_image_;
2781 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002782 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002783 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2784 const int kFrameIntervalMs = 1000;
2785 const int kMinFrames = 20; // Min run time 20 sec.
2786};
2787
2788class ForcedFallbackDisabled : public ForcedFallbackTest {
2789 public:
2790 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002791 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2792 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002793};
2794
2795class ForcedFallbackEnabled : public ForcedFallbackTest {
2796 public:
2797 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002798 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2799 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002800};
2801
2802TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2803 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2804 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002805 EXPECT_METRIC_EQ(0,
2806 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2807 EXPECT_METRIC_EQ(
2808 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002809}
2810
2811TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2812 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002813 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002814 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002815 EXPECT_METRIC_EQ(1,
2816 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2817 EXPECT_METRIC_EQ(
2818 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2819 EXPECT_METRIC_EQ(
2820 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2821 EXPECT_METRIC_EQ(
2822 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002823}
2824
2825TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2826 codec_info_.codecType = kVideoCodecVP9;
2827 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2828 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002829 EXPECT_METRIC_EQ(0,
2830 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2831 EXPECT_METRIC_EQ(
2832 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002833}
2834
2835TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2836 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2837 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2838 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002839 EXPECT_METRIC_EQ(0,
2840 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2841 EXPECT_METRIC_EQ(
2842 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002843}
2844
2845TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002846 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002847 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2848 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002849 EXPECT_METRIC_EQ(0,
2850 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2851 EXPECT_METRIC_EQ(
2852 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002853}
2854
2855TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2856 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2857 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002858 EXPECT_METRIC_EQ(0,
2859 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2860 EXPECT_METRIC_EQ(
2861 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002862}
2863
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002864TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2865 InsertEncodedFrames(1, kFrameIntervalMs);
2866 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2867}
2868
2869TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2870 InsertEncodedFrames(1, kFrameIntervalMs);
2871 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2872}
2873
2874TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002875 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002876 InsertEncodedFrames(1, kFrameIntervalMs);
2877 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2878}
2879
2880TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2881 encoded_image_._encodedWidth = kWidth + 1;
2882 InsertEncodedFrames(1, kFrameIntervalMs);
2883 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2884}
2885
2886TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002887 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002888 InsertEncodedFrames(1, kFrameIntervalMs);
2889 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2890}
2891
2892TEST_F(ForcedFallbackDisabled,
2893 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2894 encoded_image_._encodedWidth = kWidth + 1;
2895 statistics_proxy_->OnMinPixelLimitReached();
2896 InsertEncodedFrames(1, kFrameIntervalMs);
2897 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2898}
2899
asapersson8d75ac72017-09-15 06:41:15 -07002900TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2901 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002902 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002903 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002904 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002905 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002906 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002907 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002908
2909 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002910 EXPECT_METRIC_EQ(1,
2911 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2912 EXPECT_METRIC_EQ(
2913 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2914 EXPECT_METRIC_EQ(
2915 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2916 EXPECT_METRIC_EQ(
2917 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002918}
2919
2920TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2921 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2922 const int kMaxFrameDiffMs = 2000;
2923
2924 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2925 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002926 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002927 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002928 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002929 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002930 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002931 InsertEncodedFrames(20, 1000);
2932 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2933 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002934 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002935 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002936 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002937 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002938 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002939 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002940 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002941
2942 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002943 EXPECT_METRIC_EQ(1,
2944 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2945 EXPECT_METRIC_EQ(
2946 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2947 EXPECT_METRIC_EQ(
2948 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2949 EXPECT_METRIC_EQ(
2950 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002951}
2952
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002953TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2954 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002955 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002956 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2957
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002958 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002959 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002960 EXPECT_METRIC_EQ(0,
2961 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2962 EXPECT_METRIC_EQ(
2963 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002964}
2965
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002966TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2967 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002968 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002969 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2970
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002971 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002972 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002973 EXPECT_METRIC_EQ(1,
2974 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2975 EXPECT_METRIC_EQ(
2976 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002977}
2978
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002979} // namespace webrtc