blob: 71b84c94437b53393f2210e88953bce3145d51cc [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 Shrubsolece0a11d2020-04-16 11:36:55 +020021#include "api/video/video_adaptation_reason.h"
Evan Shrubsolecc62b162019-09-09 11:26:45 +020022#include "api/video/video_bitrate_allocation.h"
23#include "api/video/video_codec_type.h"
24#include "api/video_codecs/video_codec.h"
25#include "api/video_codecs/video_encoder_config.h"
Henrik Boström23aff9b2019-05-20 15:15:38 +020026#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "system_wrappers/include/metrics.h"
asapersson8d75ac72017-09-15 06:41:15 -070028#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000030
31namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070032namespace {
33const uint32_t kFirstSsrc = 17;
34const uint32_t kSecondSsrc = 42;
35const uint32_t kFirstRtxSsrc = 18;
36const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080037const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080038const int kFpsPeriodicIntervalMs = 2000;
39const int kWidth = 640;
40const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070041const int kQpIdx0 = 21;
42const int kQpIdx1 = 39;
Åsa Perssonaa329e72017-12-15 15:54:44 +010043const int kRtpClockRateHz = 90000;
kthelgason0cd27ba2016-12-19 06:32:16 -080044const CodecSpecificInfo kDefaultCodecInfo = []() {
45 CodecSpecificInfo codec_info;
46 codec_info.codecType = kVideoCodecVP8;
kthelgason0cd27ba2016-12-19 06:32:16 -080047 return codec_info;
48}();
Evan Shrubsoledff79252020-04-16 11:34:32 +020049
50const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
51 true);
52const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
53 true,
54 false);
55const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
56 false,
57 true);
58const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
asapersson5265fed2016-04-18 02:58:47 -070059} // namespace
sprang07fb9be2016-02-24 07:55:00 -080060
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000061class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000062 public:
asapersson8d75ac72017-09-15 06:41:15 -070063 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
64 explicit SendStatisticsProxyTest(const std::string& field_trials)
65 : override_field_trials_(field_trials),
66 fake_clock_(1234),
Åsa Persson90719572021-04-08 19:05:30 +020067 config_(GetTestConfig()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000068 virtual ~SendStatisticsProxyTest() {}
69
70 protected:
71 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070072 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080073 statistics_proxy_.reset(new SendStatisticsProxy(
74 &fake_clock_, GetTestConfig(),
75 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000076 expected_ = VideoSendStream::Stats();
Henrik Boströmf45ca372020-03-24 13:30:50 +010077 for (const auto& ssrc : config_.rtp.ssrcs) {
78 expected_.substreams[ssrc].type =
79 VideoSendStream::StreamStats::StreamType::kMedia;
80 }
81 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
82 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
83 expected_.substreams[ssrc].type =
84 VideoSendStream::StreamStats::StreamType::kRtx;
85 expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
86 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000087 }
88
89 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070090 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080091 config.rtp.ssrcs.push_back(kFirstSsrc);
92 config.rtp.ssrcs.push_back(kSecondSsrc);
93 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
94 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070095 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000096 return config;
97 }
98
asaperssona6a699a2016-11-25 03:52:46 -080099 VideoSendStream::Config GetTestConfigWithFlexFec() {
100 VideoSendStream::Config config(nullptr);
101 config.rtp.ssrcs.push_back(kFirstSsrc);
102 config.rtp.ssrcs.push_back(kSecondSsrc);
103 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
104 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -0800105 config.rtp.flexfec.payload_type = 50;
106 config.rtp.flexfec.ssrc = kFlexFecSsrc;
Henrik Boströmf45ca372020-03-24 13:30:50 +0100107 config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
asaperssona6a699a2016-11-25 03:52:46 -0800108 return config;
109 }
110
111 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
112 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
113 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
114 stats.substreams.find(ssrc);
115 EXPECT_NE(it, stats.substreams.end());
116 return it->second;
117 }
118
asapersson66d4b372016-12-19 06:50:53 -0800119 void UpdateDataCounters(uint32_t ssrc) {
120 StreamDataCountersCallback* proxy =
121 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
122 StreamDataCounters counters;
123 proxy->DataCountersUpdated(counters, ssrc);
124 }
125
sprang@webrtc.org09315702014-02-07 12:06:29 +0000126 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
Di Wu668dbf62021-02-27 00:29:15 -0800127 EXPECT_EQ(one.frames, other.frames);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000128 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
129 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000130 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000131 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000132
133 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000134 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000135 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000136 it != one.substreams.end(); ++it) {
137 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
138 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000139 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000140 const VideoSendStream::StreamStats& a = it->second;
141 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142
Henrik Boströmf45ca372020-03-24 13:30:50 +0100143 EXPECT_EQ(a.type, b.type);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000144 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
145 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000146 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000147 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
148 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000149
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000150 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
151 b.rtp_stats.transmitted.payload_bytes);
152 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
153 b.rtp_stats.transmitted.header_bytes);
154 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
155 b.rtp_stats.transmitted.padding_bytes);
156 EXPECT_EQ(a.rtp_stats.transmitted.packets,
157 b.rtp_stats.transmitted.packets);
158 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
159 b.rtp_stats.retransmitted.packets);
160 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000161
162 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700163 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
164 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
165 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000166 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
167 }
168 }
169
asapersson8d75ac72017-09-15 06:41:15 -0700170 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000171 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800172 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000173 VideoSendStream::Config config_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000174 VideoSendStream::Stats expected_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000175};
176
177TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
178 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700179 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000180 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000181
182 // Add statistics with some arbitrary, but unique, numbers.
183 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700184 ssrc_stats.rtcp_stats.packets_lost = offset;
185 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000186 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
187 ssrc_stats.rtcp_stats.jitter = offset + 3;
188 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
189 }
asapersson35151f32016-05-02 23:44:01 -0700190 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000191 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000192
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000193 // Add statistics with some arbitrary, but unique, numbers.
194 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700195 ssrc_stats.rtcp_stats.packets_lost = offset;
196 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000197 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
198 ssrc_stats.rtcp_stats.jitter = offset + 3;
199 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
200 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000201 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000202 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000203}
204
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000205TEST_F(SendStatisticsProxyTest, Suspended) {
206 // Verify that the value is false by default.
207 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
208
209 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200210 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000211 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
212
213 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200214 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000215 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
216}
217
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000218TEST_F(SendStatisticsProxyTest, FrameCounts) {
219 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700220 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000221 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000222 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
223 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000224 FrameCounts frame_counts;
225 frame_counts.key_frames = offset;
226 frame_counts.delta_frames = offset + 1;
227 stats.frame_counts = frame_counts;
228 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000229 }
asapersson35151f32016-05-02 23:44:01 -0700230 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000231 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000232 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
233 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000234 FrameCounts frame_counts;
235 frame_counts.key_frames = offset;
236 frame_counts.delta_frames = offset + 1;
237 stats.frame_counts = frame_counts;
238 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000239 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000240
241 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000242 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000243}
244
245TEST_F(SendStatisticsProxyTest, DataCounters) {
246 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700247 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000248 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
249 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000250 size_t offset = ssrc * sizeof(StreamDataCounters);
251 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000252 counters.transmitted.payload_bytes = offset;
253 counters.transmitted.header_bytes = offset + 1;
254 counters.fec.packets = offset_uint32 + 2;
255 counters.transmitted.padding_bytes = offset + 3;
256 counters.retransmitted.packets = offset_uint32 + 4;
257 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000258 callback->DataCountersUpdated(counters, ssrc);
259 }
asapersson35151f32016-05-02 23:44:01 -0700260 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000261 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
262 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000263 size_t offset = ssrc * sizeof(StreamDataCounters);
264 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000265 counters.transmitted.payload_bytes = offset;
266 counters.transmitted.header_bytes = offset + 1;
267 counters.fec.packets = offset_uint32 + 2;
268 counters.transmitted.padding_bytes = offset + 3;
269 counters.retransmitted.packets = offset_uint32 + 4;
270 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000271 callback->DataCountersUpdated(counters, ssrc);
272 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000273
274 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000275 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000276}
277
278TEST_F(SendStatisticsProxyTest, Bitrate) {
279 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700280 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000281 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200282 uint32_t total = ssrc;
283 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000284 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700285 expected_.substreams[ssrc].total_bitrate_bps = total;
286 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000287 }
asapersson35151f32016-05-02 23:44:01 -0700288 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000289 // Use ssrc as bitrate_bps to get a unique value for each stream.
Åsa Persson90719572021-04-08 19:05:30 +0200290 uint32_t total = ssrc;
291 uint32_t retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000292 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700293 expected_.substreams[ssrc].total_bitrate_bps = total;
294 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000295 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000296
297 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000298 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000299}
300
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000301TEST_F(SendStatisticsProxyTest, SendSideDelay) {
302 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700303 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000304 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
305 // stream.
306 int avg_delay_ms = ssrc;
307 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200308 uint64_t total_packet_send_delay_ms = ssrc + 2;
309 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
310 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000311 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
312 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200313 expected_.substreams[ssrc].total_packet_send_delay_ms =
314 total_packet_send_delay_ms;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000315 }
asapersson35151f32016-05-02 23:44:01 -0700316 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000317 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
318 // stream.
319 int avg_delay_ms = ssrc;
320 int max_delay_ms = ssrc + 1;
Henrik Boström9fe18342019-05-16 18:38:20 +0200321 uint64_t total_packet_send_delay_ms = ssrc + 2;
322 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms,
323 total_packet_send_delay_ms, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000324 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
325 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
Henrik Boström9fe18342019-05-16 18:38:20 +0200326 expected_.substreams[ssrc].total_packet_send_delay_ms =
327 total_packet_send_delay_ms;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000328 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000329 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000330 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000331}
332
Peter Boströme4499152016-02-05 11:13:28 +0100333TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800334 const int kEncodeTimeMs = 11;
Niels Möller213618e2018-07-24 09:29:58 +0200335 int encode_usage_percent = 80;
336 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
337 encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800338
339 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
340 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Niels Möller213618e2018-07-24 09:29:58 +0200341 EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800342}
343
Henrik Boström5684af52019-04-02 15:05:21 +0200344TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
345 const int kEncodeUsagePercent = 0; // Don't care for this test.
346 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
347 statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
348 EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
349 statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
350 EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
351}
352
sakal43536c32016-10-24 01:46:43 -0700353TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
354 EncodedImage encoded_image;
355 CodecSpecificInfo codec_info;
356 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
357 for (uint32_t i = 1; i <= 3; ++i) {
358 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
359 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
360 }
361}
362
sakal87da4042016-10-31 06:53:47 -0700363TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
364 EncodedImage encoded_image;
365 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200366 auto ssrc = config_.rtp.ssrcs[0];
367 EXPECT_EQ(absl::nullopt,
368 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700369 encoded_image.qp_ = 3;
370 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200371 EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700372 encoded_image.qp_ = 127;
373 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200374 EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700375}
376
377TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
378 EncodedImage encoded_image;
379 CodecSpecificInfo codec_info;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200380 auto ssrc = config_.rtp.ssrcs[0];
sakal87da4042016-10-31 06:53:47 -0700381 encoded_image.qp_ = -1;
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200382 EXPECT_EQ(absl::nullopt,
383 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700384 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200385 EXPECT_EQ(absl::nullopt,
386 statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
sakal87da4042016-10-31 06:53:47 -0700387}
388
Henrik Boström23aff9b2019-05-20 15:15:38 +0200389TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
390 const uint32_t kTargetBytesPerSecond = 100000;
391 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
392 EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
393
394 EncodedImage encoded_image;
395 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
396 // On the first frame we don't know the frame rate yet, calculation yields
397 // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
398 // increment by a full |kTargetBytesPerSecond|.
399 EXPECT_EQ(kTargetBytesPerSecond,
400 statistics_proxy_->GetStats().total_encoded_bytes_target);
401}
402
403TEST_F(SendStatisticsProxyTest,
404 TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
405 const uint32_t kTargetBytesPerSecond = 100000;
406 const int kInterframeDelayMs = 100;
407
408 // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
409 // |fake_clock_| for testing, but the RateTracker relies on a global clock.
410 // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
411 // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
412 // this test can stop relying on rtc::ScopedFakeClock.
413 rtc::ScopedFakeClock fake_global_clock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100414 fake_global_clock.SetTime(
415 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200416
417 statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
418 EncodedImage encoded_image;
419
420 // First frame
421 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
422 uint64_t first_total_encoded_bytes_target =
423 statistics_proxy_->GetStats().total_encoded_bytes_target;
424 // Second frame
425 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100426 fake_global_clock.SetTime(
427 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
Henrik Boström23aff9b2019-05-20 15:15:38 +0200428 encoded_image.SetTimestamp(encoded_image.Timestamp() +
429 90 * kInterframeDelayMs);
430 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
431
432 auto stats = statistics_proxy_->GetStats();
433 // By the time the second frame arrives, one frame has previously arrived
434 // during a |kInterframeDelayMs| interval. The estimated encode frame rate at
435 // the second frame's arrival should be 10 FPS.
436 uint64_t delta_encoded_bytes_target =
437 stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
438 EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
439}
440
Henrik Boströma0ff50c2020-05-05 15:54:46 +0200441TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
442 const int kInterframeDelayMs = 100;
443 auto ssrc = config_.rtp.ssrcs[0];
444 rtc::ScopedFakeClock fake_global_clock;
445 fake_global_clock.SetTime(
446 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
447
448 EncodedImage encoded_image;
449
450 // First frame
451 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
452 // Second frame
453 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
454 fake_global_clock.SetTime(
455 Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
456 encoded_image.SetTimestamp(encoded_image.Timestamp() +
457 90 * kInterframeDelayMs);
458 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
459
460 auto stats = statistics_proxy_->GetStats();
461 EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
462}
463
asapersson09f05612017-05-15 23:40:18 -0700464TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200465 VideoAdaptationCounters cpu_counts;
466 VideoAdaptationCounters quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700467 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700468 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200469 cpu_counts.fps_adaptations = 1;
470 cpu_counts.resolution_adaptations = 0;
471 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200472 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
473 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700474 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700475 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200476 cpu_counts.fps_adaptations = 0;
477 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200478 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
479 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700480 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700481 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200482 cpu_counts.fps_adaptations = 1;
483 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
484 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200485 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
486 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700487 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700488 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200489 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
490 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200491 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
492 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700493 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
494 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
495}
496
497TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200498 VideoAdaptationCounters cpu_counts;
499 VideoAdaptationCounters 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);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200502 quality_counts.fps_adaptations = 1;
503 quality_counts.resolution_adaptations = 0;
504 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200505 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
506 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700507 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
508 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200509 quality_counts.fps_adaptations = 0;
510 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200511 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
512 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700513 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
514 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200515 quality_counts.fps_adaptations = 1;
516 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
517 kResolutionScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200518 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
519 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700520 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
521 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200522 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
523 kScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200524 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
525 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700526 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
527 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
528}
529
530TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200531 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
532 VideoAdaptationCounters cpu_counts;
533 VideoAdaptationCounters quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700534 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
535
Evan Shrubsoledff79252020-04-16 11:34:32 +0200536 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200537 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
538 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700539 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700540 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
541 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
542
Evan Shrubsoledff79252020-04-16 11:34:32 +0200543 cpu_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200544 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
545 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700546 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
547 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700548 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700549 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700550}
551
asapersson09f05612017-05-15 23:40:18 -0700552TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
Evan Shrubsoledff79252020-04-16 11:34:32 +0200553 VideoAdaptationCounters cpu_counts;
554 VideoAdaptationCounters quality_counts;
555 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonfab67072017-04-04 05:51:49 -0700556 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
557
Evan Shrubsoledff79252020-04-16 11:34:32 +0200558 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200559 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
560 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700561 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
562 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700563 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
564
Evan Shrubsoledff79252020-04-16 11:34:32 +0200565 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200566 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
567 cpu_counts, quality_counts);
asapersson09f05612017-05-15 23:40:18 -0700568 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700569 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700570 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
571 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700572}
573
Evan Shrubsoledff79252020-04-16 11:34:32 +0200574TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
575 VideoAdaptationCounters cpu_counts;
576 VideoAdaptationCounters quality_counts;
577 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
578 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
579 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
580
581 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200582 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
583 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200584 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200585 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
586 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200587 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200588 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
589 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200590 cpu_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200591 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
592 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200593 // We have 1 fps and resolution reduction for both cpu and quality
594 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
595 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
596 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
597 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
598 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
599 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
600
601 // Disable quality scaling. Expect quality scaling not limited.
602 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
603 kScalingDisabled);
604 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
605 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
606 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
607 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
608 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
609 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
610
611 // Disable framerate scaling.
612 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
613 kFramerateScalingDisabled);
614 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
615 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
616 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
617 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
618 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
619 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
620
621 // Disable resolution scaling.
622 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
623 kResolutionScalingDisabled);
624 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
625 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
626 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
627 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
628 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
629 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
630
631 // Enable all
632 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
633 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
634 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
635 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
636 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
637 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
638 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
639}
640
asapersson09f05612017-05-15 23:40:18 -0700641TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700642 // First RTP packet sent.
643 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700644 // Min runtime has passed.
645 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
646 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100647 EXPECT_METRIC_EQ(
648 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
649 EXPECT_METRIC_EQ(
650 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700651}
652
653TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700654 // First RTP packet sent.
655 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700656 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200657 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700658 // Min runtime has not passed.
659 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
660 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100661 EXPECT_METRIC_EQ(
662 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
663 EXPECT_METRIC_EQ(
664 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -0700665}
666
asapersson09f05612017-05-15 23:40:18 -0700667TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700668 // First RTP packet sent.
669 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700670 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200671 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -0700672 // Min runtime has passed.
673 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
674 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100675 EXPECT_METRIC_EQ(
676 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
677 EXPECT_METRIC_EQ(
678 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
679 EXPECT_METRIC_EQ(
680 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
681 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700682 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
683}
684
685TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700686 // First RTP packet sent.
687 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700688 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200689 VideoAdaptationCounters cpu_counts;
690 VideoAdaptationCounters quality_counts;
691 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700692 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200693 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
694 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700695 fake_clock_.AdvanceTimeMilliseconds(10000);
696 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100697 EXPECT_METRIC_EQ(
698 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
699 EXPECT_METRIC_EQ(
700 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson6eca98b2017-04-04 23:40:50 -0700701}
702
Åsa Persson875841d2018-01-08 08:49:53 +0100703TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
704 // First RTP packet sent.
705 UpdateDataCounters(kFirstSsrc);
706 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200707 VideoAdaptationCounters cpu_counts;
708 VideoAdaptationCounters quality_counts;
709 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100710 // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200711 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
712 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100713 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
714 fake_clock_.AdvanceTimeMilliseconds(10000);
715 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100716 EXPECT_METRIC_EQ(
717 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
718 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100719 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
720}
721
722TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
723 // First RTP packet sent.
724 UpdateDataCounters(kFirstSsrc);
725 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200726 VideoAdaptationCounters cpu_counts;
727 VideoAdaptationCounters quality_counts;
728 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100729 // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200730 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200731 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
732 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100733 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200734 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200735 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
736 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100737 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200738 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200739 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
740 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100741 fake_clock_.AdvanceTimeMilliseconds(10000);
742 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100743 EXPECT_METRIC_EQ(
744 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
745 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100746 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
747}
748
749TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
750 // First RTP packet sent.
751 UpdateDataCounters(kFirstSsrc);
752 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200753 VideoAdaptationCounters cpu_counts;
754 VideoAdaptationCounters quality_counts;
755 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Åsa Persson875841d2018-01-08 08:49:53 +0100756 // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200757 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
758 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100759 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
760 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
761 fake_clock_.AdvanceTimeMilliseconds(10000);
762 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100763 EXPECT_METRIC_EQ(
764 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
765 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100766 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
767}
768
769TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
770 // First RTP packet sent.
771 UpdateDataCounters(kFirstSsrc);
772 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200773 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
774 VideoAdaptationCounters cpu_counts;
775 VideoAdaptationCounters quality_counts;
776 statistics_proxy_->ClearAdaptationStats();
Åsa Persson875841d2018-01-08 08:49:53 +0100777 // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200778 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200779 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
780 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100781 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200782 quality_counts.resolution_adaptations = 2;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200783 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
784 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100785 statistics_proxy_->OnInitialQualityResolutionAdaptDown();
Evan Shrubsoledff79252020-04-16 11:34:32 +0200786 quality_counts.resolution_adaptations = 3;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200787 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
788 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200789 quality_counts.fps_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200790 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
791 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200792 quality_counts.fps_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200793 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
794 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200795 quality_counts.resolution_adaptations = 2; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200796 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
797 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200798 quality_counts.resolution_adaptations = 1; // Initial resolution up.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200799 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
800 cpu_counts, quality_counts);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200801 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200802 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
803 cpu_counts, quality_counts);
Åsa Persson875841d2018-01-08 08:49:53 +0100804
805 fake_clock_.AdvanceTimeMilliseconds(10000);
806 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100807 EXPECT_METRIC_EQ(
808 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
809 EXPECT_METRIC_EQ(
Åsa Persson875841d2018-01-08 08:49:53 +0100810 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
811}
812
asapersson6eca98b2017-04-04 23:40:50 -0700813TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700814 // First RTP packet sent.
815 UpdateDataCounters(kFirstSsrc);
816
asapersson09f05612017-05-15 23:40:18 -0700817 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200818 VideoAdaptationCounters cpu_counts;
819 VideoAdaptationCounters quality_counts;
820 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
821 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700822 fake_clock_.AdvanceTimeMilliseconds(10000);
823
asapersson09f05612017-05-15 23:40:18 -0700824 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700825 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200826 quality_counts.fps_adaptations = 0;
827 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
828 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700829 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200830 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
831 kResolutionScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700832 fake_clock_.AdvanceTimeMilliseconds(9000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200833 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
834 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700835 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200836 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
837 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700838
asapersson09f05612017-05-15 23:40:18 -0700839 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200840 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
841 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700842 fake_clock_.AdvanceTimeMilliseconds(30000);
843
asapersson09f05612017-05-15 23:40:18 -0700844 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700845 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200846 quality_counts.resolution_adaptations = 0;
847 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
848 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200849 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
850 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700851 fake_clock_.AdvanceTimeMilliseconds(10000);
852
asapersson09f05612017-05-15 23:40:18 -0700853 // Disable quality adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200854 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
855 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700856 fake_clock_.AdvanceTimeMilliseconds(5000);
Evan Shrubsoledff79252020-04-16 11:34:32 +0200857 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
858 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -0700859 fake_clock_.AdvanceTimeMilliseconds(20000);
860
asapersson0944a802017-04-07 00:57:58 -0700861 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700862 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100863 EXPECT_METRIC_EQ(
864 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
865 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -0700866 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
867}
868
asapersson0944a802017-04-07 00:57:58 -0700869TEST_F(SendStatisticsProxyTest,
870 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
871 // First RTP packet sent.
872 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700873
asapersson0944a802017-04-07 00:57:58 -0700874 // Suspend and resume video.
875 statistics_proxy_->OnSuspendChange(true);
876 fake_clock_.AdvanceTimeMilliseconds(5000);
877 statistics_proxy_->OnSuspendChange(false);
878
879 // Min runtime has passed but scaling not enabled.
880 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
881 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100882 EXPECT_METRIC_EQ(
883 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
884 EXPECT_METRIC_EQ(
885 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson0944a802017-04-07 00:57:58 -0700886}
887
888TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
889 // First RTP packet sent.
890 UpdateDataCounters(kFirstSsrc);
891
asapersson09f05612017-05-15 23:40:18 -0700892 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200893 VideoAdaptationCounters cpu_counts;
894 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700895 // Adapt changes: 2, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200896 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700897 fake_clock_.AdvanceTimeMilliseconds(20000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200898 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
899 cpu_counts, quality_counts);
900 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
901 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700902
903 // Suspend and resume video.
904 statistics_proxy_->OnSuspendChange(true);
905 fake_clock_.AdvanceTimeMilliseconds(30000);
906 statistics_proxy_->OnSuspendChange(false);
907
908 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200909 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
910 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700911 fake_clock_.AdvanceTimeMilliseconds(10000);
912
913 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
914 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100915 EXPECT_METRIC_EQ(
916 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
917 EXPECT_METRIC_EQ(
asapersson0944a802017-04-07 00:57:58 -0700918 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
919}
920
921TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
922 // First RTP packet sent.
923 UpdateDataCounters(kFirstSsrc);
924
925 // Video not suspended.
926 statistics_proxy_->OnSuspendChange(false);
927 fake_clock_.AdvanceTimeMilliseconds(30000);
928
asapersson09f05612017-05-15 23:40:18 -0700929 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200930 VideoAdaptationCounters cpu_counts;
931 VideoAdaptationCounters quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700932 // Adapt changes: 1, elapsed time: 20 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200933 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700934 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200935 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
936 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700937
938 // Video not suspended, stats time already started.
939 statistics_proxy_->OnSuspendChange(false);
940 fake_clock_.AdvanceTimeMilliseconds(10000);
941
asapersson09f05612017-05-15 23:40:18 -0700942 // Disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200943 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
944 kScalingDisabled);
asapersson0944a802017-04-07 00:57:58 -0700945 fake_clock_.AdvanceTimeMilliseconds(30000);
946
947 // Suspend and resume video, stats time not started when scaling not enabled.
948 statistics_proxy_->OnSuspendChange(true);
949 fake_clock_.AdvanceTimeMilliseconds(30000);
950 statistics_proxy_->OnSuspendChange(false);
951 fake_clock_.AdvanceTimeMilliseconds(30000);
952
asapersson09f05612017-05-15 23:40:18 -0700953 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700954 // Adapt changes: 1, elapsed time: 10 sec.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200955 cpu_counts.fps_adaptations = 0;
956 cpu_counts.resolution_adaptations = 0;
957 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700958 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200959 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
960 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700961
962 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
963 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100964 EXPECT_METRIC_EQ(
965 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
966 EXPECT_METRIC_EQ(
967 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
asapersson0944a802017-04-07 00:57:58 -0700968}
969
970TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
971 // First RTP packet sent.
972 UpdateDataCounters(kFirstSsrc);
973
974 // Video suspended.
975 statistics_proxy_->OnSuspendChange(true);
976
asapersson09f05612017-05-15 23:40:18 -0700977 // Enable adaptation, stats time not started when suspended.
Evan Shrubsoledff79252020-04-16 11:34:32 +0200978 VideoAdaptationCounters cpu_counts;
979 VideoAdaptationCounters quality_counts;
980 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson0944a802017-04-07 00:57:58 -0700981 fake_clock_.AdvanceTimeMilliseconds(10000);
982
983 // Resume video, stats time started.
984 // Adapt changes: 1, elapsed time: 10 sec.
985 statistics_proxy_->OnSuspendChange(false);
986 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +0200987 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
988 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700989
990 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
991 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +0100992 EXPECT_METRIC_EQ(
993 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
994 EXPECT_METRIC_EQ(
995 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
asapersson0944a802017-04-07 00:57:58 -0700996}
997
998TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700999 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -07001000 // Elapsed time before first packet is sent should be excluded.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001001 VideoAdaptationCounters cpu_counts;
1002 VideoAdaptationCounters quality_counts;
1003 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001004 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001005 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001006
asapersson0944a802017-04-07 00:57:58 -07001007 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001008 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001009 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1010 cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -07001011 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001012
asapersson0944a802017-04-07 00:57:58 -07001013 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001014 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001015 EXPECT_METRIC_EQ(
1016 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1017 EXPECT_METRIC_EQ(
asapersson6eca98b2017-04-04 23:40:50 -07001018 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1019}
1020
1021TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -07001022 // Enable and disable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001023 VideoAdaptationCounters cpu_counts;
1024 VideoAdaptationCounters quality_counts;
1025 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson6eca98b2017-04-04 23:40:50 -07001026 fake_clock_.AdvanceTimeMilliseconds(60000);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001027 statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1028 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001029
1030 // Send first packet, scaling disabled.
1031 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -07001032 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001033 fake_clock_.AdvanceTimeMilliseconds(60000);
1034
asapersson09f05612017-05-15 23:40:18 -07001035 // Enable adaptation.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001036 cpu_counts.resolution_adaptations = 0;
1037 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1038 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001039 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -07001040 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -07001041
asapersson0944a802017-04-07 00:57:58 -07001042 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -07001043 fake_clock_.AdvanceTimeMilliseconds(10000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001044 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1045 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001046
asapersson0944a802017-04-07 00:57:58 -07001047 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -07001048 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001049 EXPECT_METRIC_EQ(
1050 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1051 EXPECT_METRIC_EQ(
1052 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
asapersson6eca98b2017-04-04 23:40:50 -07001053}
1054
1055TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -07001056 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -07001057 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001058 VideoAdaptationCounters cpu_counts;
1059 VideoAdaptationCounters quality_counts;
1060 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1061 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001062
asapersson0944a802017-04-07 00:57:58 -07001063 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001064 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1065 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001066 fake_clock_.AdvanceTimeMilliseconds(6000);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001067 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1068 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001069 fake_clock_.AdvanceTimeMilliseconds(9000);
1070
1071 // Switch content type, real-time stats should be updated.
1072 VideoEncoderConfig config;
1073 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001074 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001075 EXPECT_METRIC_EQ(
1076 1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1077 EXPECT_METRIC_EQ(
1078 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1079 EXPECT_METRIC_EQ(
1080 0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001081
asapersson0944a802017-04-07 00:57:58 -07001082 // First RTP packet sent, scaling enabled.
1083 UpdateDataCounters(kFirstSsrc);
Evan Shrubsoledff79252020-04-16 11:34:32 +02001084 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1085 kScalingDisabled);
asapersson6eca98b2017-04-04 23:40:50 -07001086
asapersson0944a802017-04-07 00:57:58 -07001087 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001088 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1089 cpu_counts, quality_counts);
1090 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1091 cpu_counts, quality_counts);
1092 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1093 cpu_counts, quality_counts);
1094 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1095 cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -07001096 fake_clock_.AdvanceTimeMilliseconds(120000);
1097
1098 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001099 EXPECT_METRIC_EQ(1,
1100 metrics::NumSamples(
1101 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1102 EXPECT_METRIC_EQ(
1103 1, metrics::NumEvents(
1104 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1105 EXPECT_METRIC_EQ(
1106 0, metrics::NumSamples(
1107 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
asapersson6eca98b2017-04-04 23:40:50 -07001108}
1109
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001110TEST_F(SendStatisticsProxyTest,
1111 QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001112 VideoAdaptationCounters cpu_counts;
1113 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001114
Evan Shrubsoledff79252020-04-16 11:34:32 +02001115 cpu_counts.resolution_adaptations = 1;
1116 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001117 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1118 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001119
1120 EXPECT_EQ(QualityLimitationReason::kCpu,
1121 statistics_proxy_->GetStats().quality_limitation_reason);
1122}
1123
1124TEST_F(SendStatisticsProxyTest,
1125 QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001126 VideoAdaptationCounters cpu_counts;
1127 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001128
Evan Shrubsoledff79252020-04-16 11:34:32 +02001129 cpu_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001130
Evan Shrubsoledff79252020-04-16 11:34:32 +02001131 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001132 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1133 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001134
1135 EXPECT_EQ(QualityLimitationReason::kCpu,
1136 statistics_proxy_->GetStats().quality_limitation_reason);
1137}
1138
1139TEST_F(SendStatisticsProxyTest,
1140 QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001141 VideoAdaptationCounters cpu_counts;
1142 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001143
Evan Shrubsoledff79252020-04-16 11:34:32 +02001144 quality_counts.resolution_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001145
Evan Shrubsoledff79252020-04-16 11:34:32 +02001146 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001147 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1148 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001149
1150 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1151 statistics_proxy_->GetStats().quality_limitation_reason);
1152}
1153
1154TEST_F(SendStatisticsProxyTest,
1155 QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001156 VideoAdaptationCounters cpu_counts;
1157 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001158
Evan Shrubsoledff79252020-04-16 11:34:32 +02001159 quality_counts.fps_adaptations = 1;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001160
Evan Shrubsoledff79252020-04-16 11:34:32 +02001161 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001162 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1163 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001164
1165 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1166 statistics_proxy_->GetStats().quality_limitation_reason);
1167}
1168
1169TEST_F(SendStatisticsProxyTest,
1170 QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001171 VideoAdaptationCounters cpu_counts;
1172 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001173
Evan Shrubsoledff79252020-04-16 11:34:32 +02001174 cpu_counts.resolution_adaptations = 1;
1175 quality_counts.resolution_adaptations = 1;
1176 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001177
1178 // Even if the last adaptation reason is kCpu, if the counters indicate being
1179 // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001180 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1181 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001182
1183 EXPECT_EQ(QualityLimitationReason::kBandwidth,
1184 statistics_proxy_->GetStats().quality_limitation_reason);
1185}
1186
1187TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001188 VideoAdaptationCounters cpu_counts;
1189 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001190
1191 // Observe a limitation due to CPU. This makes sure the test doesn't pass
1192 // due to "none" being the default value.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001193 cpu_counts.resolution_adaptations = 1;
1194 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001195 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1196 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001197 // Go back to not being limited.
Evan Shrubsoledff79252020-04-16 11:34:32 +02001198 cpu_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001199 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1200 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001201
1202 EXPECT_EQ(QualityLimitationReason::kNone,
1203 statistics_proxy_->GetStats().quality_limitation_reason);
1204}
1205
1206TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001207 VideoAdaptationCounters cpu_counts;
1208 VideoAdaptationCounters quality_counts;
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001209
Evan Shrubsoledff79252020-04-16 11:34:32 +02001210 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001211 // Not limited for 3000 ms
1212 fake_clock_.AdvanceTimeMilliseconds(3000);
1213 // CPU limited for 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001214 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001215 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1216 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001217 fake_clock_.AdvanceTimeMilliseconds(2000);
1218 // Bandwidth limited for 1000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001219 cpu_counts.resolution_adaptations = 0;
1220 quality_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001221 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1222 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001223 fake_clock_.AdvanceTimeMilliseconds(1000);
1224 // CPU limited for another 2000 ms
Evan Shrubsoledff79252020-04-16 11:34:32 +02001225 cpu_counts.resolution_adaptations = 1;
1226 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001227 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1228 cpu_counts, quality_counts);
Henrik Boströmce33b6a2019-05-28 17:42:38 +02001229 fake_clock_.AdvanceTimeMilliseconds(2000);
1230
1231 auto quality_limitation_durations_ms =
1232 statistics_proxy_->GetStats().quality_limitation_durations_ms;
1233
1234 EXPECT_EQ(3000,
1235 quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1236 EXPECT_EQ(4000,
1237 quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1238 EXPECT_EQ(
1239 1000,
1240 quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1241 EXPECT_EQ(0,
1242 quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1243}
1244
Evan Shrubsolecc62b162019-09-09 11:26:45 +02001245TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1246 EXPECT_EQ(
1247 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1248}
1249
1250TEST_F(SendStatisticsProxyTest,
1251 QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1252 VideoCodec codec;
1253 VideoBitrateAllocation allocation;
1254 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1255 EXPECT_EQ(
1256 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1257}
1258
1259TEST_F(SendStatisticsProxyTest,
1260 QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1261 VideoCodec codec;
1262 codec.simulcastStream[0].active = true;
1263 codec.simulcastStream[1].active = true;
1264 codec.simulcastStream[2].active = true;
1265 VideoBitrateAllocation allocation;
1266 allocation.SetBitrate(0, 0, 100);
1267 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1268 EXPECT_EQ(
1269 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1270}
1271
1272TEST_F(SendStatisticsProxyTest,
1273 QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1274 VideoCodec codec;
1275 codec.simulcastStream[0].active = true;
1276 codec.simulcastStream[1].active = true;
1277 codec.simulcastStream[2].active = true;
1278 VideoBitrateAllocation allocation;
1279 allocation.SetBitrate(0, 0, 100);
1280 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1281 allocation.SetBitrate(1, 0, 100);
1282 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1283 EXPECT_EQ(
1284 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1285}
1286
1287TEST_F(SendStatisticsProxyTest,
1288 QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1289 VideoCodec codec;
1290 codec.simulcastStream[0].active = true;
1291 VideoBitrateAllocation allocation;
1292 allocation.SetBitrate(0, 0, 100);
1293 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1294 // Layer 0 got more bandwidth, but still only one layer on
1295 allocation.SetBitrate(0, 0, 200);
1296 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1297 EXPECT_EQ(
1298 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1299}
1300
1301TEST_F(SendStatisticsProxyTest,
1302 QualityLimitationResolutionChangesWithTogglingLayers) {
1303 VideoCodec codec;
1304 codec.simulcastStream[0].active = true;
1305 codec.simulcastStream[1].active = true;
1306 codec.simulcastStream[2].active = true;
1307 VideoBitrateAllocation allocation;
1308 allocation.SetBitrate(0, 0, 100);
1309 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1310 EXPECT_EQ(
1311 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1312 allocation.SetBitrate(1, 0, 300);
1313 allocation.SetBitrate(2, 0, 500);
1314 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1315 EXPECT_EQ(
1316 1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1317 // Layer 2 off
1318 allocation.SetBitrate(2, 0, 0);
1319 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1320 EXPECT_EQ(
1321 2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1322 // Layer 2 back on
1323 allocation.SetBitrate(2, 0, 500);
1324 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1325 EXPECT_EQ(
1326 3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1327 allocation.SetBitrate(0, 0, 0);
1328 allocation.SetBitrate(1, 0, 0);
1329 allocation.SetBitrate(2, 0, 0);
1330 // All layers off
1331 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1332 EXPECT_EQ(
1333 4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1334}
1335
1336TEST_F(SendStatisticsProxyTest,
1337 QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1338 VideoCodec codec;
1339 // 3 layers
1340 codec.simulcastStream[0].active = true;
1341 codec.simulcastStream[1].active = true;
1342 codec.simulcastStream[2].active = true;
1343 VideoBitrateAllocation allocation;
1344 allocation.SetBitrate(0, 0, 500);
1345 allocation.SetBitrate(1, 0, 500);
1346 allocation.SetBitrate(2, 0, 500);
1347 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1348 EXPECT_EQ(
1349 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1350
1351 // Down to one layer now, triggered by a config change
1352 codec.numberOfSimulcastStreams = 1;
1353 codec.simulcastStream[1].active = false;
1354 codec.simulcastStream[2].active = false;
1355 allocation.SetBitrate(0, 0, 100);
1356 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1357 EXPECT_EQ(
1358 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1359
1360 // Up to 3 layers again.
1361 codec.numberOfSimulcastStreams = 3;
1362 codec.simulcastStream[1].active = true;
1363 codec.simulcastStream[2].active = true;
1364 allocation.SetBitrate(0, 0, 500);
1365 allocation.SetBitrate(1, 0, 500);
1366 allocation.SetBitrate(2, 0, 500);
1367 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1368 EXPECT_EQ(
1369 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1370}
1371
1372TEST_F(SendStatisticsProxyTest,
1373 QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1374 VideoCodec codec;
1375 codec.simulcastStream[0].active = true;
1376 codec.spatialLayers[0].active = true;
1377 codec.spatialLayers[1].active = true;
1378 codec.spatialLayers[2].active = true;
1379 VideoBitrateAllocation allocation;
1380 allocation.SetBitrate(0, 0, 500);
1381 allocation.SetBitrate(1, 0, 500);
1382 allocation.SetBitrate(2, 0, 500);
1383 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1384 EXPECT_EQ(
1385 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1386
1387 // Down to one layer now, triggered by a config change
1388 codec.spatialLayers[1].active = false;
1389 codec.spatialLayers[2].active = false;
1390 allocation.SetBitrate(0, 0, 100);
1391 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1392 EXPECT_EQ(
1393 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1394
1395 // Up to 3 layers again.
1396 codec.spatialLayers[1].active = true;
1397 codec.spatialLayers[2].active = true;
1398 allocation.SetBitrate(0, 0, 500);
1399 allocation.SetBitrate(1, 0, 500);
1400 allocation.SetBitrate(2, 0, 500);
1401 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1402 EXPECT_EQ(
1403 0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1404}
1405
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02001406TEST_F(SendStatisticsProxyTest,
1407 QualityLimitationReasonsAreCorrectForContentType) {
1408 // Realtime case.
1409 // Configure two streams.
1410 VideoEncoderConfig config;
1411 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1412 config.number_of_streams = 2;
1413 VideoStream stream1;
1414 stream1.width = kWidth / 2;
1415 stream1.height = kHeight / 2;
1416 VideoStream stream2;
1417 stream2.width = kWidth;
1418 stream2.height = kHeight;
1419 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1420 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1421 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1422 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1423 QualityLimitationReason::kNone);
1424 // Bw disabled one layer.
1425 VideoCodec codec;
1426 codec.numberOfSimulcastStreams = 2;
1427 codec.simulcastStream[0].active = true;
1428 codec.simulcastStream[1].active = true;
1429 VideoBitrateAllocation allocation;
1430 // Some positive bitrate only on the first stream.
1431 allocation.SetBitrate(0, 0, 10000);
1432 allocation.SetBitrate(1, 0, 0);
1433 allocation.set_bw_limited(true);
1434 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1435 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1436 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1437 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1438 QualityLimitationReason::kBandwidth);
1439 // Bw enabled all layers.
1440 allocation.SetBitrate(1, 0, 10000);
1441 allocation.set_bw_limited(false);
1442 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1443 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1444 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1445 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1446 QualityLimitationReason::kNone);
1447
1448 // Screencast case
1449 // Configure two streams.
1450 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1451 config.number_of_streams = 2;
1452 stream1.width = kWidth;
1453 stream1.height = kHeight;
1454 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1455 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1456 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1457 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1458 QualityLimitationReason::kNone);
1459 // Bw disabled one layer.
1460 // Some positive bitrate only on the second stream.
1461 allocation.SetBitrate(0, 0, 10000);
1462 allocation.SetBitrate(1, 0, 0);
1463 allocation.set_bw_limited(true);
1464 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1465 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1466 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1467 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1468 QualityLimitationReason::kBandwidth);
1469 // Bw enabled all layers.
1470 allocation.SetBitrate(1, 0, 10000);
1471 allocation.set_bw_limited(false);
1472 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1473 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1474 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1475 EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1476 QualityLimitationReason::kNone);
1477}
1478
asapersson59bac1a2016-01-07 23:36:00 -08001479TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -07001480 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -08001481 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1482
Pera48ddb72016-09-29 11:48:50 +02001483 // No switch, stats should not be updated.
1484 VideoEncoderConfig config;
1485 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Niels Möller97e04882018-05-25 09:43:26 +02001486 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001487 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001488
1489 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +02001490 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02001491 statistics_proxy_->OnEncoderReconfigured(config, {});
Ying Wangef3998f2019-12-09 13:06:53 +01001492 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -08001493}
1494
asapersson320e45a2016-11-29 01:40:35 -08001495TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1496 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1497 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -07001498
asapersson320e45a2016-11-29 01:40:35 -08001499 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001500 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1501 EXPECT_METRIC_EQ(
1502 1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1503 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1504 EXPECT_METRIC_EQ(
1505 1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001506}
1507
1508TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
Åsa Persson0122e842017-10-16 12:19:23 +02001509 const int64_t kMaxEncodedFrameWindowMs = 800;
Åsa Persson20317f92018-08-15 08:57:54 +02001510 const int kFps = 5;
Åsa Persson0122e842017-10-16 12:19:23 +02001511 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1512 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1513 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
asapersson320e45a2016-11-29 01:40:35 -08001514 EncodedImage encoded_image;
Åsa Persson0122e842017-10-16 12:19:23 +02001515
1516 // Not enough samples, stats should not be updated.
1517 for (int i = 0; i < kMinSamples - 1; ++i) {
1518 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001519 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
asapersson320e45a2016-11-29 01:40:35 -08001520 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1521 }
Åsa Persson0122e842017-10-16 12:19:23 +02001522 SetUp(); // Reset stats proxy also causes histograms to be reported.
Ying Wangef3998f2019-12-09 13:06:53 +01001523 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1524 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
Åsa Persson0122e842017-10-16 12:19:23 +02001525
1526 // Enough samples, max resolution per frame should be reported.
Niels Möller23775882018-08-16 10:24:12 +02001527 encoded_image.SetTimestamp(0xffff0000); // Will wrap.
Åsa Persson0122e842017-10-16 12:19:23 +02001528 for (int i = 0; i < kMinSamples; ++i) {
1529 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001530 encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
Åsa Persson0122e842017-10-16 12:19:23 +02001531 encoded_image._encodedWidth = kWidth;
1532 encoded_image._encodedHeight = kHeight;
1533 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1534 encoded_image._encodedWidth = kWidth / 2;
1535 encoded_image._encodedHeight = kHeight / 2;
1536 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1537 }
1538
asapersson320e45a2016-11-29 01:40:35 -08001539 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001540 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1541 EXPECT_METRIC_EQ(
1542 1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1543 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1544 EXPECT_METRIC_EQ(
1545 1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
asapersson320e45a2016-11-29 01:40:35 -08001546}
1547
1548TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1549 const int kFps = 20;
1550 const int kMinPeriodicSamples = 6;
1551 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1552 for (int i = 0; i <= frames; ++i) {
1553 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1554 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1555 }
1556 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001557 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1558 EXPECT_METRIC_EQ(
1559 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001560}
1561
1562TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1563 EncodedImage encoded_image;
1564 const int kFps = 20;
1565 const int kMinPeriodicSamples = 6;
1566 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
Åsa Persson0122e842017-10-16 12:19:23 +02001567 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001568 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001569 encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
Åsa Persson0122e842017-10-16 12:19:23 +02001570 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1571 // Frame with same timestamp should not be counted.
asapersson320e45a2016-11-29 01:40:35 -08001572 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1573 }
1574 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001575 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1576 EXPECT_METRIC_EQ(
1577 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001578}
1579
1580TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1581 const int kFps = 20;
1582 const int kSuspendTimeMs = 10000;
1583 const int kMinPeriodicSamples = 6;
1584 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1585 for (int i = 0; i < frames; ++i) {
1586 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1587 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1588 }
1589 // Suspend.
1590 statistics_proxy_->OnSuspendChange(true);
1591 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1592
1593 for (int i = 0; i < frames; ++i) {
1594 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1595 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1596 }
1597 // Suspended time interval should not affect the framerate.
1598 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001599 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1600 EXPECT_METRIC_EQ(
1601 1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001602}
1603
1604TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1605 EncodedImage encoded_image;
1606 const int kFps = 20;
1607 const int kSuspendTimeMs = 10000;
1608 const int kMinPeriodicSamples = 6;
1609 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
Åsa Persson0122e842017-10-16 12:19:23 +02001610 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001611 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001612 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001613 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1614 }
1615 // Suspend.
1616 statistics_proxy_->OnSuspendChange(true);
1617 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1618
Åsa Persson0122e842017-10-16 12:19:23 +02001619 for (int i = 0; i < frames; ++i) {
asapersson320e45a2016-11-29 01:40:35 -08001620 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001621 encoded_image.SetTimestamp(i + 1);
asapersson320e45a2016-11-29 01:40:35 -08001622 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1623 }
1624 // Suspended time interval should not affect the framerate.
1625 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001626 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1627 EXPECT_METRIC_EQ(
1628 1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
asapersson320e45a2016-11-29 01:40:35 -08001629}
1630
asaperssonf4e44af2017-04-19 02:01:06 -07001631TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001632 statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1633 kResolutionScalingDisabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001634
1635 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1636 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1637
1638 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001639 EXPECT_METRIC_EQ(
1640 0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
asaperssonf4e44af2017-04-19 02:01:06 -07001641}
1642
1643TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02001644 VideoAdaptationCounters cpu_counts;
1645 VideoAdaptationCounters quality_counts;
1646 cpu_counts.resolution_adaptations = 0;
1647 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asaperssonf4e44af2017-04-19 02:01:06 -07001648
perkj803d97f2016-11-01 11:45:46 -07001649 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1650 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1651
Evan Shrubsoledff79252020-04-16 11:34:32 +02001652 cpu_counts.resolution_adaptations = 1;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02001653 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1654 cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -07001655
1656 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1657 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1658
1659 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001660 EXPECT_METRIC_EQ(
1661 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1662 EXPECT_METRIC_EQ(
perkj803d97f2016-11-01 11:45:46 -07001663 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1664}
1665
asapersson4374a092016-07-27 00:39:09 -07001666TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1667 const int64_t kTimeSec = 3;
1668 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1669 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001670 EXPECT_METRIC_EQ(
1671 1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1672 EXPECT_METRIC_EQ(
1673 1,
1674 metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
asapersson4374a092016-07-27 00:39:09 -07001675}
1676
1677TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1678 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1679 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001680 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
asapersson4374a092016-07-27 00:39:09 -07001681}
1682
asapersson66d4b372016-12-19 06:50:53 -08001683TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1684 // First RTP packet sent.
1685 UpdateDataCounters(kFirstSsrc);
1686
1687 // Min runtime has passed.
1688 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1689 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001690 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1691 EXPECT_METRIC_EQ(1,
1692 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
asapersson66d4b372016-12-19 06:50:53 -08001693}
1694
1695TEST_F(SendStatisticsProxyTest,
1696 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1697 // First RTP packet sent.
1698 UpdateDataCounters(kFirstSsrc);
1699
1700 // Min runtime has not passed.
1701 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1702 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001703 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1704 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001705}
1706
1707TEST_F(SendStatisticsProxyTest,
1708 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1709 // First RTP packet not sent.
1710 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1711 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001712 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
asapersson66d4b372016-12-19 06:50:53 -08001713}
1714
1715TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1716 // First RTP packet sent and min runtime passed.
1717 UpdateDataCounters(kFirstSsrc);
1718
1719 // No change. Video: 10000 ms, paused: 0 ms (0%).
1720 statistics_proxy_->OnSetEncoderTargetRate(50000);
1721 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1722 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1723
1724 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001725 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1726 EXPECT_METRIC_EQ(1,
1727 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1728 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1729 EXPECT_METRIC_EQ(1,
1730 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
asapersson66d4b372016-12-19 06:50:53 -08001731}
1732
1733TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1734 // First RTP packet sent and min runtime passed.
1735 UpdateDataCounters(kFirstSsrc);
1736
1737 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1738 statistics_proxy_->OnSetEncoderTargetRate(50000);
1739 fake_clock_.AdvanceTimeMilliseconds(7000);
1740 statistics_proxy_->OnSetEncoderTargetRate(0);
1741 fake_clock_.AdvanceTimeMilliseconds(3000);
1742 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1743
1744 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001745 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1746 EXPECT_METRIC_EQ(1,
1747 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1748 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1749 EXPECT_METRIC_EQ(1,
1750 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
asapersson66d4b372016-12-19 06:50:53 -08001751}
1752
1753TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1754 // First RTP packet sent.
1755 UpdateDataCounters(kFirstSsrc);
1756
1757 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1758 statistics_proxy_->OnSetEncoderTargetRate(0);
1759 fake_clock_.AdvanceTimeMilliseconds(1000);
1760 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1761 fake_clock_.AdvanceTimeMilliseconds(7000);
1762 statistics_proxy_->OnSetEncoderTargetRate(60000);
1763 fake_clock_.AdvanceTimeMilliseconds(3000);
1764 statistics_proxy_->OnSetEncoderTargetRate(0);
1765 fake_clock_.AdvanceTimeMilliseconds(250);
1766 statistics_proxy_->OnSetEncoderTargetRate(0);
1767 fake_clock_.AdvanceTimeMilliseconds(750);
1768 statistics_proxy_->OnSetEncoderTargetRate(60000);
1769 fake_clock_.AdvanceTimeMilliseconds(5000);
1770 statistics_proxy_->OnSetEncoderTargetRate(50000);
1771 fake_clock_.AdvanceTimeMilliseconds(4000);
1772 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1773
1774 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001775 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1776 EXPECT_METRIC_EQ(1,
1777 metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1778 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1779 EXPECT_METRIC_EQ(1,
1780 metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
asapersson66d4b372016-12-19 06:50:53 -08001781}
1782
1783TEST_F(SendStatisticsProxyTest,
1784 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1785 // First RTP packet sent.
1786 UpdateDataCounters(kFirstSsrc);
1787 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1788
1789 // Min runtime has not passed.
1790 statistics_proxy_->OnSetEncoderTargetRate(50000);
1791 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1792 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1793
1794 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001795 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
asapersson66d4b372016-12-19 06:50:53 -08001796}
1797
asapersson118ef002016-03-31 00:00:19 -07001798TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001799 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001800 CodecSpecificInfo codec_info;
1801 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001802
perkj803d97f2016-11-01 11:45:46 -07001803 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001804 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001805 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001806 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001807 encoded_image.SetSpatialIndex(1);
asapersson118ef002016-03-31 00:00:19 -07001808 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001809 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001810 }
1811 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001812 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1813 EXPECT_METRIC_EQ(
1814 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1815 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1816 EXPECT_METRIC_EQ(
1817 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001818}
1819
1820TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1821 VideoSendStream::Config config(nullptr);
1822 config.rtp.ssrcs.push_back(kFirstSsrc);
1823 statistics_proxy_.reset(new SendStatisticsProxy(
1824 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1825
asapersson118ef002016-03-31 00:00:19 -07001826 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001827 CodecSpecificInfo codec_info;
1828 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001829
perkj803d97f2016-11-01 11:45:46 -07001830 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001831 encoded_image.SetSpatialIndex(0);
asapersson118ef002016-03-31 00:00:19 -07001832 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001833 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001834 }
1835 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001836 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1837 EXPECT_METRIC_EQ(1,
1838 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001839}
1840
asapersson5265fed2016-04-18 02:58:47 -07001841TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001842 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001843 CodecSpecificInfo codec_info;
1844 codec_info.codecType = kVideoCodecVP9;
1845 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001846
perkj803d97f2016-11-01 11:45:46 -07001847 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001848 encoded_image.qp_ = kQpIdx0;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001849 encoded_image.SetSpatialIndex(0);
kjellander02b3d272016-04-20 05:05:54 -07001850 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001851 encoded_image.qp_ = kQpIdx1;
Niels Möllerd3b8c632018-08-27 15:33:42 +02001852 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07001853 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001854 }
1855 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001856 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1857 EXPECT_METRIC_EQ(
1858 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1859 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1860 EXPECT_METRIC_EQ(
1861 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001862}
1863
1864TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1865 VideoSendStream::Config config(nullptr);
1866 config.rtp.ssrcs.push_back(kFirstSsrc);
1867 statistics_proxy_.reset(new SendStatisticsProxy(
1868 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1869
asapersson5265fed2016-04-18 02:58:47 -07001870 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001871 CodecSpecificInfo codec_info;
1872 codec_info.codecType = kVideoCodecVP9;
1873 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001874
perkj803d97f2016-11-01 11:45:46 -07001875 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001876 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001877 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001878 }
1879 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001880 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1881 EXPECT_METRIC_EQ(1,
1882 metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001883}
1884
asapersson827cab32016-11-02 09:08:47 -07001885TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1886 EncodedImage encoded_image;
1887 CodecSpecificInfo codec_info;
1888 codec_info.codecType = kVideoCodecH264;
1889
1890 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02001891 encoded_image.SetSpatialIndex(0);
asapersson827cab32016-11-02 09:08:47 -07001892 encoded_image.qp_ = kQpIdx0;
1893 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02001894 encoded_image.SetSpatialIndex(1);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001895 encoded_image.qp_ = kQpIdx1;
1896 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson827cab32016-11-02 09:08:47 -07001897 }
1898 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001899 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
1900 EXPECT_METRIC_EQ(
1901 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
1902 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
1903 EXPECT_METRIC_EQ(
1904 1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
asapersson827cab32016-11-02 09:08:47 -07001905}
1906
asapersson4ee70462016-10-31 04:05:12 -07001907TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001908 BandwidthLimitedHistogramsNotUpdatedForOneStream) {
1909 // Configure one stream.
1910 VideoEncoderConfig config;
1911 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1912 VideoStream stream1;
1913 stream1.width = kWidth;
1914 stream1.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001915 statistics_proxy_->OnEncoderReconfigured(config, {stream1});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001916
1917 const int64_t kMaxEncodedFrameWindowMs = 800;
1918 const int kFps = 20;
1919 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1920 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1921 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1922
1923 // Stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07001924 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001925 encoded_image._encodedWidth = kWidth;
1926 encoded_image._encodedHeight = kHeight;
1927 for (int i = 0; i < kMinSamples; ++i) {
1928 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001929 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1930 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07001931 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001932 }
asapersson4ee70462016-10-31 04:05:12 -07001933
1934 // Histograms are updated when the statistics_proxy_ is deleted.
1935 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001936 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1937 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1938 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1939 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001940}
1941
1942TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001943 BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
1944 // Configure two streams.
1945 VideoEncoderConfig config;
1946 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1947 VideoStream stream1;
1948 stream1.width = kWidth / 2;
1949 stream1.height = kHeight / 2;
1950 VideoStream stream2;
1951 stream2.width = kWidth;
1952 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001953 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001954
1955 const int64_t kMaxEncodedFrameWindowMs = 800;
1956 const int kFps = 20;
1957 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1958 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
1959 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1960
1961 // Two streams encoded.
asapersson4ee70462016-10-31 04:05:12 -07001962 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01001963 for (int i = 0; i < kMinSamples; ++i) {
1964 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02001965 encoded_image.SetTimestamp(encoded_image.Timestamp() +
1966 (kRtpClockRateHz / kFps));
Åsa Perssonaa329e72017-12-15 15:54:44 +01001967 encoded_image._encodedWidth = kWidth;
1968 encoded_image._encodedHeight = kHeight;
asapersson4ee70462016-10-31 04:05:12 -07001969 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01001970 encoded_image._encodedWidth = kWidth / 2;
1971 encoded_image._encodedHeight = kHeight / 2;
1972 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1973 }
asapersson4ee70462016-10-31 04:05:12 -07001974
1975 // Histograms are updated when the statistics_proxy_ is deleted.
1976 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01001977 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1978 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1979 EXPECT_METRIC_EQ(
1980 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
1981 0));
asapersson4ee70462016-10-31 04:05:12 -07001982 // No resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01001983 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1984 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
asapersson4ee70462016-10-31 04:05:12 -07001985}
1986
1987TEST_F(SendStatisticsProxyTest,
Åsa Perssonaa329e72017-12-15 15:54:44 +01001988 BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
1989 // Configure two streams.
1990 VideoEncoderConfig config;
1991 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1992 VideoStream stream1;
1993 stream1.width = kWidth / 2;
1994 stream1.height = kHeight / 2;
1995 VideoStream stream2;
1996 stream2.width = kWidth;
1997 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02001998 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01001999
2000 const int64_t kMaxEncodedFrameWindowMs = 800;
2001 const int kFps = 20;
2002 const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2003 const int kMinSamples = // Sample added when removed from EncodedFrameMap.
2004 SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2005
2006 // One stream encoded.
asapersson4ee70462016-10-31 04:05:12 -07002007 EncodedImage encoded_image;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002008 encoded_image._encodedWidth = kWidth / 2;
2009 encoded_image._encodedHeight = kHeight / 2;
2010 for (int i = 0; i < kMinSamples; ++i) {
2011 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
Niels Möller23775882018-08-16 10:24:12 +02002012 encoded_image.SetTimestamp(encoded_image.Timestamp() +
2013 (kRtpClockRateHz / kFps));
asapersson4ee70462016-10-31 04:05:12 -07002014 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
Åsa Perssonaa329e72017-12-15 15:54:44 +01002015 }
asapersson4ee70462016-10-31 04:05:12 -07002016
2017 // Histograms are updated when the statistics_proxy_ is deleted.
2018 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002019 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2020 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2021 EXPECT_METRIC_EQ(
2022 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2023 100));
Åsa Perssonaa329e72017-12-15 15:54:44 +01002024 // One resolution disabled.
Ying Wangef3998f2019-12-09 13:06:53 +01002025 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2026 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2027 EXPECT_METRIC_EQ(
2028 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2029 1));
asapersson4ee70462016-10-31 04:05:12 -07002030}
2031
2032TEST_F(SendStatisticsProxyTest,
2033 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002034 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2035 kScalingDisabled);
asapersson4ee70462016-10-31 04:05:12 -07002036 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002037 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002038 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002039 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002040
2041 // Histograms are updated when the statistics_proxy_ is deleted.
2042 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002043 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002044 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002045 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2046 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002047}
2048
2049TEST_F(SendStatisticsProxyTest,
2050 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
Evan Shrubsoledff79252020-04-16 11:34:32 +02002051 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
asapersson4ee70462016-10-31 04:05:12 -07002052 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002053 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002054 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002055 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002056
2057 // Histograms are updated when the statistics_proxy_ is deleted.
2058 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002059 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002060 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002061 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2062 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
asapersson4ee70462016-10-31 04:05:12 -07002063 // No resolution downscale.
Ying Wangef3998f2019-12-09 13:06:53 +01002064 EXPECT_METRIC_EQ(0, metrics::NumSamples(
2065 "WebRTC.Video.QualityLimitedResolutionDownscales"));
asapersson4ee70462016-10-31 04:05:12 -07002066}
2067
2068TEST_F(SendStatisticsProxyTest,
2069 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2070 const int kDownscales = 2;
Evan Shrubsoledff79252020-04-16 11:34:32 +02002071 VideoAdaptationCounters cpu_counts;
2072 VideoAdaptationCounters quality_counts;
2073 quality_counts.resolution_adaptations = kDownscales;
2074 statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002075 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2076 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002077 EncodedImage encoded_image;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002078 encoded_image.SetSpatialIndex(0);
perkj803d97f2016-11-01 11:45:46 -07002079 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08002080 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07002081 // Histograms are updated when the statistics_proxy_ is deleted.
2082 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002083 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002084 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
Ying Wangef3998f2019-12-09 13:06:53 +01002085 EXPECT_METRIC_EQ(
2086 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2087 100));
asapersson4ee70462016-10-31 04:05:12 -07002088 // Resolution downscales.
Ying Wangef3998f2019-12-09 13:06:53 +01002089 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2090 "WebRTC.Video.QualityLimitedResolutionDownscales"));
2091 EXPECT_METRIC_EQ(
asapersson4ee70462016-10-31 04:05:12 -07002092 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2093 kDownscales));
2094}
2095
2096TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2097 // Initially false.
2098 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
Åsa Persson59283e42017-12-12 14:14:42 +01002099
Åsa Perssonaa329e72017-12-15 15:54:44 +01002100 // Configure two streams.
2101 VideoEncoderConfig config;
2102 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002103 config.number_of_streams = 2;
Åsa Perssonaa329e72017-12-15 15:54:44 +01002104 VideoStream stream1;
2105 stream1.width = kWidth / 2;
2106 stream1.height = kHeight / 2;
2107 VideoStream stream2;
2108 stream2.width = kWidth;
2109 stream2.height = kHeight;
Niels Möller97e04882018-05-25 09:43:26 +02002110 statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
Åsa Perssonaa329e72017-12-15 15:54:44 +01002111
Åsa Perssonaa329e72017-12-15 15:54:44 +01002112 // One stream encoded.
2113 EncodedImage encoded_image;
2114 encoded_image._encodedWidth = kWidth / 2;
2115 encoded_image._encodedHeight = kHeight / 2;
kthelgason0cd27ba2016-12-19 06:32:16 -08002116
2117 // Resolution scaled due to quality.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002118 VideoAdaptationCounters cpu_counts;
2119 VideoAdaptationCounters quality_counts;
2120 quality_counts.resolution_adaptations = 1;
2121 statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2122 kFramerateScalingDisabled);
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002123 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2124 cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07002125 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2126 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002127
2128 // Adapt up.
Evan Shrubsoledff79252020-04-16 11:34:32 +02002129 quality_counts.resolution_adaptations = 0;
Evan Shrubsolece0a11d2020-04-16 11:36:55 +02002130 statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2131 cpu_counts, quality_counts);
Ilya Nikolaevskiy5963c7c2019-10-09 18:06:58 +02002132 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2133 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2134
2135 // Bw disabled one layer.
2136 VideoCodec codec;
2137 codec.numberOfSimulcastStreams = 2;
2138 codec.simulcastStream[0].active = true;
2139 codec.simulcastStream[1].active = true;
2140 VideoBitrateAllocation allocation;
2141 // Some positive bitrate only on the second stream.
2142 allocation.SetBitrate(1, 0, 10000);
2143 allocation.set_bw_limited(true);
2144 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2145 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
Ilya Nikolaevskiyeac08bf2020-03-10 09:50:26 +00002146
2147 // Revert for the next test.
2148 allocation.set_bw_limited(false);
2149 statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2150 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2151
2152 // Internal encoder scaler reduced resolution.
2153 statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2154 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson4ee70462016-10-31 04:05:12 -07002155}
2156
asapersson66d4b372016-12-19 06:50:53 -08002157TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2158 // Initially zero.
2159 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2160
2161 const int kBitrate = 100000;
2162 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2163 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2164
2165 statistics_proxy_->OnSetEncoderTargetRate(0);
2166 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2167}
2168
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002169TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002170 uint32_t excluded_ssrc =
Steve Antonbd631a02019-03-28 10:51:27 -07002171 std::max(*absl::c_max_element(config_.rtp.ssrcs),
2172 *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00002173 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002174 // From RtcpStatisticsCallback.
2175 RtcpStatistics rtcp_stats;
2176 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002177 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002178
2179 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07002180 uint32_t total = 0;
2181 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002182 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002183 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002184
2185 // From FrameCountObserver.
2186 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002187 FrameCounts frame_counts;
2188 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00002189 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002190
2191 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2192 EXPECT_TRUE(stats.substreams.empty());
2193}
2194
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002195TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2196 static const int kEncodedWidth = 123;
2197 static const int kEncodedHeight = 81;
2198 EncodedImage encoded_image;
2199 encoded_image._encodedWidth = kEncodedWidth;
2200 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002201 encoded_image.SetSpatialIndex(0);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002202
kjellander02b3d272016-04-20 05:05:54 -07002203 CodecSpecificInfo codec_info;
2204 codec_info.codecType = kVideoCodecVP8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002205
kjellander02b3d272016-04-20 05:05:54 -07002206 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002207 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002208 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002209
2210 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002211 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2212 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2213 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2214 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002215
2216 // Forward almost to timeout, this should not have removed stats.
2217 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2218 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002219 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2220 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002221
2222 // Update the first SSRC with bogus RTCP stats to make sure that encoded
2223 // resolution still times out (no global timeout for all stats).
2224 RtcpStatistics rtcp_statistics;
2225 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
2226 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
2227
2228 // Report stats for second SSRC to make sure it's not outdated along with the
2229 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07002230 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002231
2232 // Forward 1 ms, reach timeout, substream 0 should have no resolution
2233 // reported, but substream 1 should.
2234 fake_clock_.AdvanceTimeMilliseconds(1);
2235 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002236 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2237 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2238 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2239 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002240}
2241
Peter Boström20f3f942015-05-15 11:33:39 +02002242TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2243 static const int kEncodedWidth = 123;
2244 static const int kEncodedHeight = 81;
2245 EncodedImage encoded_image;
2246 encoded_image._encodedWidth = kEncodedWidth;
2247 encoded_image._encodedHeight = kEncodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002248 encoded_image.SetSpatialIndex(0);
Peter Boström20f3f942015-05-15 11:33:39 +02002249
kjellander02b3d272016-04-20 05:05:54 -07002250 CodecSpecificInfo codec_info;
2251 codec_info.codecType = kVideoCodecVP8;
Peter Boström20f3f942015-05-15 11:33:39 +02002252
kjellander02b3d272016-04-20 05:05:54 -07002253 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Niels Möllerd3b8c632018-08-27 15:33:42 +02002254 encoded_image.SetSpatialIndex(1);
kjellander02b3d272016-04-20 05:05:54 -07002255 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02002256
2257 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2258 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2259 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2260 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2261 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2262 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2263}
2264
2265TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07002266 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02002267 BitrateStatisticsObserver* observer = statistics_proxy_.get();
2268 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2269 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2270
2271 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2272
2273 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07002274 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002275 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07002276 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02002277 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2278 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2279 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2280}
2281
sprang07fb9be2016-02-24 07:55:00 -08002282TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2283 RtcpPacketTypeCounterObserver* proxy =
2284 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2285 RtcpPacketTypeCounter counters;
2286 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2287 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2288 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2289
2290 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2291
2292 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2293 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2294 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2295 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2296 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2297
2298 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2299 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2300
2301 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002302 VideoEncoderConfig config;
2303 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002304 statistics_proxy_->OnEncoderReconfigured(config, {});
sprang07fb9be2016-02-24 07:55:00 -08002305
Ying Wangef3998f2019-12-09 13:06:53 +01002306 EXPECT_METRIC_EQ(
2307 1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2308 EXPECT_METRIC_EQ(
2309 1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2310 EXPECT_METRIC_EQ(
2311 1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2312 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2313 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
sprang07fb9be2016-02-24 07:55:00 -08002314
2315 const int kRate = 60 * 2; // Packets per minute with two streams.
2316
Ying Wangef3998f2019-12-09 13:06:53 +01002317 EXPECT_METRIC_EQ(
2318 1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2319 1 * kRate));
2320 EXPECT_METRIC_EQ(
2321 1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2322 2 * kRate));
2323 EXPECT_METRIC_EQ(
2324 1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2325 3 * kRate));
2326 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002327 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2328 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002329
2330 // New start time but same counter values.
2331 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2332 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2333
2334 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2335
2336 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2337 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2338 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2339 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2340 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2341
2342 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2343 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2344
2345 SetUp(); // Reset stats proxy also causes histograms to be reported.
2346
Ying Wangef3998f2019-12-09 13:06:53 +01002347 EXPECT_METRIC_EQ(
2348 1, metrics::NumSamples(
2349 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2350 EXPECT_METRIC_EQ(1,
2351 metrics::NumSamples(
2352 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2353 EXPECT_METRIC_EQ(1,
2354 metrics::NumSamples(
2355 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2356 EXPECT_METRIC_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002357 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08002358 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2359
Ying Wangef3998f2019-12-09 13:06:53 +01002360 EXPECT_METRIC_EQ(
2361 1,
2362 metrics::NumEvents(
2363 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2364 EXPECT_METRIC_EQ(
2365 1,
2366 metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2367 2 * kRate));
2368 EXPECT_METRIC_EQ(
2369 1,
2370 metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2371 3 * kRate));
2372 EXPECT_METRIC_EQ(
2373 1, metrics::NumEvents(
2374 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2375 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08002376}
2377
Henrik Boströmf45ca372020-03-24 13:30:50 +01002378TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2379 StreamDataCountersCallback* proxy =
2380 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2381 StreamDataCounters counters;
2382 proxy->DataCountersUpdated(counters, kFirstSsrc);
2383 proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2384
2385 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2386 VideoSendStream::StreamStats::StreamType::kRtx);
2387 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2388 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2389 VideoSendStream::StreamStats::StreamType::kRtx);
2390 EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2391}
2392
asaperssona6a699a2016-11-25 03:52:46 -08002393TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2394 statistics_proxy_.reset(
2395 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2396 VideoEncoderConfig::ContentType::kRealtimeVideo));
2397
2398 StreamDataCountersCallback* proxy =
2399 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2400 StreamDataCounters counters;
2401 proxy->DataCountersUpdated(counters, kFirstSsrc);
2402 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2403
Henrik Boströmf45ca372020-03-24 13:30:50 +01002404 EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2405 VideoSendStream::StreamStats::StreamType::kFlexfec);
2406 EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2407 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2408 VideoSendStream::StreamStats::StreamType::kFlexfec);
2409 EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
asaperssona6a699a2016-11-25 03:52:46 -08002410}
2411
2412TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2413 statistics_proxy_.reset(
2414 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
2415 VideoEncoderConfig::ContentType::kRealtimeVideo));
2416
2417 StreamDataCountersCallback* proxy =
2418 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08002419 StreamDataCounters counters;
2420 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08002421
asapersson93e1e232017-02-06 05:18:35 -08002422 const int kMinRequiredPeriodSamples = 8;
2423 const int kPeriodIntervalMs = 2000;
2424 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2425 counters.transmitted.packets += 20;
2426 counters.transmitted.header_bytes += 500;
2427 counters.transmitted.padding_bytes += 1000;
2428 counters.transmitted.payload_bytes += 2000;
2429 counters.retransmitted.packets += 2;
2430 counters.retransmitted.header_bytes += 25;
2431 counters.retransmitted.padding_bytes += 100;
2432 counters.retransmitted.payload_bytes += 250;
2433 counters.fec = counters.retransmitted;
2434 rtx_counters.transmitted = counters.transmitted;
2435 // Advance one interval and update counters.
2436 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2437 proxy->DataCountersUpdated(counters, kFirstSsrc);
2438 proxy->DataCountersUpdated(counters, kSecondSsrc);
2439 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2440 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2441 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2442 }
asaperssona6a699a2016-11-25 03:52:46 -08002443
asaperssona6a699a2016-11-25 03:52:46 -08002444 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08002445 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002446 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2447 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002448 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002449 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2450 EXPECT_METRIC_EQ(1,
2451 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002452 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002453 EXPECT_METRIC_EQ(1,
2454 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2455 EXPECT_METRIC_EQ(
2456 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002457 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002458 EXPECT_METRIC_EQ(
2459 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2460 EXPECT_METRIC_EQ(
2461 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002462 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002463 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2464 EXPECT_METRIC_EQ(1,
2465 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002466 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002467 EXPECT_METRIC_EQ(
2468 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2469 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002470 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08002471}
2472
Erik Språng22c2b482016-03-01 09:40:42 +01002473TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2474 StreamDataCountersCallback* proxy =
2475 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2476 StreamDataCounters counters;
2477 StreamDataCounters rtx_counters;
2478 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01002479
asapersson93e1e232017-02-06 05:18:35 -08002480 const int kMinRequiredPeriodSamples = 8;
2481 const int kPeriodIntervalMs = 2000;
2482 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2483 counters.transmitted.packets += 20;
2484 counters.transmitted.header_bytes += 500;
2485 counters.transmitted.padding_bytes += 1000;
2486 counters.transmitted.payload_bytes += 2000;
2487 counters.retransmitted.packets += 2;
2488 counters.retransmitted.header_bytes += 25;
2489 counters.retransmitted.padding_bytes += 100;
2490 counters.retransmitted.payload_bytes += 250;
2491 counters.fec = counters.retransmitted;
2492 rtx_counters.transmitted = counters.transmitted;
2493 // Advance one interval and update counters.
2494 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2495 proxy->DataCountersUpdated(counters, kFirstSsrc);
2496 proxy->DataCountersUpdated(counters, kSecondSsrc);
2497 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2498 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2499 }
Erik Språng22c2b482016-03-01 09:40:42 +01002500
2501 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02002502 VideoEncoderConfig config;
2503 config.content_type = VideoEncoderConfig::ContentType::kScreen;
Niels Möller97e04882018-05-25 09:43:26 +02002504 statistics_proxy_->OnEncoderReconfigured(config, {});
Erik Språng22c2b482016-03-01 09:40:42 +01002505
asapersson93e1e232017-02-06 05:18:35 -08002506 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002507 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2508 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
asapersson93e1e232017-02-06 05:18:35 -08002509 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002510 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2511 EXPECT_METRIC_EQ(1,
2512 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002513 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002514 EXPECT_METRIC_EQ(1,
2515 metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2516 EXPECT_METRIC_EQ(
2517 1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
asapersson93e1e232017-02-06 05:18:35 -08002518 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002519 EXPECT_METRIC_EQ(
2520 1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2521 EXPECT_METRIC_EQ(
2522 1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
asapersson93e1e232017-02-06 05:18:35 -08002523 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002524 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2525 EXPECT_METRIC_EQ(1,
2526 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002527 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002528 EXPECT_METRIC_EQ(
2529 1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2530 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002531 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01002532
asapersson93e1e232017-02-06 05:18:35 -08002533 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01002534 // Double counter values, this should result in the same counts as before but
2535 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08002536 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2537 counters.transmitted.packets += 20;
2538 counters.transmitted.header_bytes += 500;
2539 counters.transmitted.padding_bytes += 1000;
2540 counters.transmitted.payload_bytes += 2000;
2541 counters.retransmitted.packets += 2;
2542 counters.retransmitted.header_bytes += 25;
2543 counters.retransmitted.padding_bytes += 100;
2544 counters.retransmitted.payload_bytes += 250;
2545 counters.fec = counters.retransmitted;
2546 rtx_counters.transmitted = counters.transmitted;
2547 // Advance one interval and update counters.
2548 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2549 proxy->DataCountersUpdated(counters, kFirstSsrc);
2550 proxy->DataCountersUpdated(counters, kSecondSsrc);
2551 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2552 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2553 }
Erik Språng22c2b482016-03-01 09:40:42 +01002554
asapersson93e1e232017-02-06 05:18:35 -08002555 // Reset stats proxy also causes histograms to be reported.
2556 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01002557
asapersson93e1e232017-02-06 05:18:35 -08002558 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002559 EXPECT_METRIC_EQ(
2560 1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2561 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002562 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2563 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002564 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002565 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002566 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2567 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
asapersson93e1e232017-02-06 05:18:35 -08002568 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002569 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2570 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2571 EXPECT_METRIC_EQ(
2572 1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2573 12));
asapersson93e1e232017-02-06 05:18:35 -08002574 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002575 EXPECT_METRIC_EQ(1, metrics::NumSamples(
2576 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2577 EXPECT_METRIC_EQ(
2578 1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2579 16));
asapersson93e1e232017-02-06 05:18:35 -08002580 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002581 EXPECT_METRIC_EQ(
asapersson93e1e232017-02-06 05:18:35 -08002582 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
Ying Wangef3998f2019-12-09 13:06:53 +01002583 EXPECT_METRIC_EQ(1, metrics::NumEvents(
2584 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002585 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Ying Wangef3998f2019-12-09 13:06:53 +01002586 EXPECT_METRIC_EQ(
2587 1, metrics::NumSamples(
2588 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2589 EXPECT_METRIC_EQ(
2590 1, metrics::NumEvents(
2591 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
asapersson93e1e232017-02-06 05:18:35 -08002592}
Erik Språng22c2b482016-03-01 09:40:42 +01002593
asapersson93e1e232017-02-06 05:18:35 -08002594TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2595 StreamDataCountersCallback* proxy =
2596 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2597 StreamDataCounters counters;
2598 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01002599
asapersson93e1e232017-02-06 05:18:35 -08002600 const int kMinRequiredPeriodSamples = 8;
2601 const int kPeriodIntervalMs = 2000;
2602 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2603 counters.transmitted.packets += 20;
2604 counters.transmitted.header_bytes += 500;
2605 counters.transmitted.payload_bytes += 2000;
2606 counters.fec = counters.retransmitted;
2607 // Advance one interval and update counters.
2608 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2609 proxy->DataCountersUpdated(counters, kFirstSsrc);
2610 }
2611
2612 // RTX enabled. No data sent over RTX.
2613 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002614 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2615 EXPECT_METRIC_EQ(1,
2616 metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002617}
2618
2619TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2620 VideoSendStream::Config config(nullptr);
2621 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
2622 statistics_proxy_.reset(new SendStatisticsProxy(
2623 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2624
2625 StreamDataCountersCallback* proxy =
2626 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2627 StreamDataCounters counters;
2628
2629 const int kMinRequiredPeriodSamples = 8;
2630 const int kPeriodIntervalMs = 2000;
2631 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2632 counters.transmitted.packets += 20;
2633 counters.transmitted.header_bytes += 500;
2634 counters.transmitted.payload_bytes += 2000;
2635 counters.fec = counters.retransmitted;
2636 // Advance one interval and update counters.
2637 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2638 proxy->DataCountersUpdated(counters, kFirstSsrc);
2639 }
2640
2641 // RTX not enabled.
2642 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002643 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08002644}
2645
2646TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2647 StreamDataCountersCallback* proxy =
2648 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2649 StreamDataCounters counters;
2650 StreamDataCounters rtx_counters;
2651
2652 const int kMinRequiredPeriodSamples = 8;
2653 const int kPeriodIntervalMs = 2000;
2654 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2655 counters.transmitted.packets += 20;
2656 counters.transmitted.header_bytes += 500;
2657 counters.transmitted.payload_bytes += 2000;
2658 // Advance one interval and update counters.
2659 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2660 proxy->DataCountersUpdated(counters, kFirstSsrc);
2661 }
2662
2663 // FEC enabled. No FEC data sent.
2664 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002665 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2666 EXPECT_METRIC_EQ(1,
2667 metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
asapersson93e1e232017-02-06 05:18:35 -08002668}
2669
2670TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2671 VideoSendStream::Config config(nullptr);
2672 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
2673 statistics_proxy_.reset(new SendStatisticsProxy(
2674 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
2675
2676 StreamDataCountersCallback* proxy =
2677 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2678 StreamDataCounters counters;
2679
2680 const int kMinRequiredPeriodSamples = 8;
2681 const int kPeriodIntervalMs = 2000;
2682 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2683 counters.transmitted.packets += 20;
2684 counters.transmitted.header_bytes += 500;
2685 counters.transmitted.payload_bytes += 2000;
2686 counters.fec = counters.retransmitted;
2687 // Advance one interval and update counters.
2688 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2689 proxy->DataCountersUpdated(counters, kFirstSsrc);
2690 }
2691
2692 // FEC not enabled.
2693 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002694 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01002695}
2696
asapersson8d75ac72017-09-15 06:41:15 -07002697TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002698 const std::string kName = "encoderName";
2699 statistics_proxy_->OnEncoderImplementationChanged(kName);
2700 EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
asapersson8d75ac72017-09-15 06:41:15 -07002701}
2702
Sergey Silkinbb081a62018-09-04 18:34:22 +02002703TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2704 static const int kEncodedWidth = 123;
2705 static const int kEncodedHeight = 81;
2706 EncodedImage encoded_image;
2707 encoded_image._encodedWidth = kEncodedWidth;
2708 encoded_image._encodedHeight = kEncodedHeight;
2709 encoded_image.SetSpatialIndex(0);
2710
2711 CodecSpecificInfo codec_info;
2712 codec_info.codecType = kVideoCodecVP9;
2713
2714 // For first picture, it is expected that low layer updates resolution.
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002715 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002716 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2717 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2718 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2719 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2720
2721 // Top layer updates resolution.
2722 encoded_image._encodedWidth = kEncodedWidth * 2;
2723 encoded_image._encodedHeight = kEncodedHeight * 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002724 codec_info.end_of_picture = true;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002725 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2726 stats = statistics_proxy_->GetStats();
2727 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2728 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2729
2730 // Low layer of next frame doesn't update resolution.
2731 encoded_image._encodedWidth = kEncodedWidth;
2732 encoded_image._encodedHeight = kEncodedHeight;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +01002733 codec_info.end_of_picture = false;
Sergey Silkinbb081a62018-09-04 18:34:22 +02002734 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2735 stats = statistics_proxy_->GetStats();
2736 EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2737 EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2738}
2739
asapersson8d75ac72017-09-15 06:41:15 -07002740class ForcedFallbackTest : public SendStatisticsProxyTest {
2741 public:
2742 explicit ForcedFallbackTest(const std::string& field_trials)
2743 : SendStatisticsProxyTest(field_trials) {
2744 codec_info_.codecType = kVideoCodecVP8;
asapersson8d75ac72017-09-15 06:41:15 -07002745 codec_info_.codecSpecific.VP8.temporalIdx = 0;
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002746 encoded_image_._encodedWidth = kWidth;
2747 encoded_image_._encodedHeight = kHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +02002748 encoded_image_.SetSpatialIndex(0);
asapersson8d75ac72017-09-15 06:41:15 -07002749 }
2750
2751 ~ForcedFallbackTest() override {}
2752
2753 protected:
2754 void InsertEncodedFrames(int num_frames, int interval_ms) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002755 statistics_proxy_->OnEncoderImplementationChanged(codec_name_);
2756
asapersson8d75ac72017-09-15 06:41:15 -07002757 // First frame is not updating stats, insert initial frame.
2758 if (statistics_proxy_->GetStats().frames_encoded == 0) {
2759 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2760 }
2761 for (int i = 0; i < num_frames; ++i) {
2762 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2763 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2764 }
2765 // Add frame to include last time interval.
2766 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2767 }
2768
2769 EncodedImage encoded_image_;
2770 CodecSpecificInfo codec_info_;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002771 std::string codec_name_;
asapersson8d75ac72017-09-15 06:41:15 -07002772 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2773 const int kFrameIntervalMs = 1000;
2774 const int kMinFrames = 20; // Min run time 20 sec.
2775};
2776
2777class ForcedFallbackDisabled : public ForcedFallbackTest {
2778 public:
2779 ForcedFallbackDisabled()
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002780 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2781 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002782};
2783
2784class ForcedFallbackEnabled : public ForcedFallbackTest {
2785 public:
2786 ForcedFallbackEnabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002787 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2788 std::to_string(kWidth * kHeight) + ",3/") {}
asapersson8d75ac72017-09-15 06:41:15 -07002789};
2790
2791TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2792 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2793 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002794 EXPECT_METRIC_EQ(0,
2795 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2796 EXPECT_METRIC_EQ(
2797 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002798}
2799
2800TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2801 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002802 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002803 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002804 EXPECT_METRIC_EQ(1,
2805 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2806 EXPECT_METRIC_EQ(
2807 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2808 EXPECT_METRIC_EQ(
2809 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2810 EXPECT_METRIC_EQ(
2811 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
asapersson8d75ac72017-09-15 06:41:15 -07002812}
2813
2814TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2815 codec_info_.codecType = kVideoCodecVP9;
2816 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2817 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002818 EXPECT_METRIC_EQ(0,
2819 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2820 EXPECT_METRIC_EQ(
2821 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002822}
2823
2824TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2825 codec_info_.codecSpecific.VP8.temporalIdx = 1;
2826 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2827 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002828 EXPECT_METRIC_EQ(0,
2829 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2830 EXPECT_METRIC_EQ(
2831 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002832}
2833
2834TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
Niels Möllerd3b8c632018-08-27 15:33:42 +02002835 encoded_image_.SetSpatialIndex(1);
asapersson8d75ac72017-09-15 06:41:15 -07002836 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2837 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002838 EXPECT_METRIC_EQ(0,
2839 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2840 EXPECT_METRIC_EQ(
2841 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002842}
2843
2844TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2845 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2846 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002847 EXPECT_METRIC_EQ(0,
2848 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2849 EXPECT_METRIC_EQ(
2850 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002851}
2852
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002853TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2854 InsertEncodedFrames(1, kFrameIntervalMs);
2855 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2856}
2857
2858TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2859 InsertEncodedFrames(1, kFrameIntervalMs);
2860 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2861}
2862
2863TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002864 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002865 InsertEncodedFrames(1, kFrameIntervalMs);
2866 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2867}
2868
2869TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2870 encoded_image_._encodedWidth = kWidth + 1;
2871 InsertEncodedFrames(1, kFrameIntervalMs);
2872 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2873}
2874
2875TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
Erik Språnge2fd86a2018-10-24 11:32:39 +02002876 codec_name_ = "libvpx";
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002877 InsertEncodedFrames(1, kFrameIntervalMs);
2878 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2879}
2880
2881TEST_F(ForcedFallbackDisabled,
2882 EnteredLowResolutionSetIfOnMinPixelLimitReached) {
2883 encoded_image_._encodedWidth = kWidth + 1;
2884 statistics_proxy_->OnMinPixelLimitReached();
2885 InsertEncodedFrames(1, kFrameIntervalMs);
2886 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2887}
2888
asapersson8d75ac72017-09-15 06:41:15 -07002889TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
2890 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002891 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002892 InsertEncodedFrames(15, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002893 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002894 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002895 InsertEncodedFrames(5, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002896 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002897
2898 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002899 EXPECT_METRIC_EQ(1,
2900 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2901 EXPECT_METRIC_EQ(
2902 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2903 EXPECT_METRIC_EQ(
2904 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2905 EXPECT_METRIC_EQ(
2906 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002907}
2908
2909TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
2910 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
2911 const int kMaxFrameDiffMs = 2000;
2912
2913 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
2914 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002915 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002916 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002917 InsertEncodedFrames(15, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002918 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002919 codec_name_ = "notlibvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002920 InsertEncodedFrames(20, 1000);
2921 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
2922 InsertEncodedFrames(10, 1000);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002923 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
Erik Språnge2fd86a2018-10-24 11:32:39 +02002924 codec_name_ = "notlibvpx2";
asapersson8d75ac72017-09-15 06:41:15 -07002925 InsertEncodedFrames(10, 500);
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002926 EXPECT_TRUE(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);
asapersson8d75ac72017-09-15 06:41:15 -07002930
2931 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002932 EXPECT_METRIC_EQ(1,
2933 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2934 EXPECT_METRIC_EQ(
2935 1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
2936 EXPECT_METRIC_EQ(
2937 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2938 EXPECT_METRIC_EQ(
2939 1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
asapersson8d75ac72017-09-15 06:41:15 -07002940}
2941
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002942TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
2943 encoded_image_._encodedWidth = kWidth + 1;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002944 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002945 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2946
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002947 EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002948 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002949 EXPECT_METRIC_EQ(0,
2950 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2951 EXPECT_METRIC_EQ(
2952 0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002953}
2954
Åsa Persson45bbc8a2017-11-13 10:16:47 +01002955TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
2956 encoded_image_._encodedWidth = kWidth;
Erik Språnge2fd86a2018-10-24 11:32:39 +02002957 codec_name_ = "libvpx";
asapersson8d75ac72017-09-15 06:41:15 -07002958 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2959
Åsa Perssonc3ed6302017-11-16 14:04:52 +01002960 EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
asapersson8d75ac72017-09-15 06:41:15 -07002961 statistics_proxy_.reset();
Ying Wangef3998f2019-12-09 13:06:53 +01002962 EXPECT_METRIC_EQ(1,
2963 metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2964 EXPECT_METRIC_EQ(
2965 1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
asapersson8d75ac72017-09-15 06:41:15 -07002966}
2967
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00002968} // namespace webrtc