blob: 7d8217ccf9eade73d67bd562c50ee340dc007c6b [file] [log] [blame]
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "video/overuse_frame_detector.h"
12
kwiberg27f982b2016-03-01 11:52:33 -080013#include <memory>
14
Niels Möller4dc66c52018-10-05 14:17:58 +020015#include "api/video/encoded_image.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "api/video/i420_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/video_coding/utility/quality_scaler.h"
18#include "rtc_base/event.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "rtc_base/fake_clock.h"
Niels Möllere541be72017-12-13 13:03:10 +010020#include "rtc_base/random.h"
Danil Chapovalov07122bc2019-03-26 14:37:01 +010021#include "rtc_base/task_queue_for_test.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gmock.h"
23#include "test/gtest.h"
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000024
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000025namespace webrtc {
perkjd52063f2016-09-07 06:32:18 -070026
Niels Möllere541be72017-12-13 13:03:10 +010027using ::testing::_;
Jonas Olssona4d87372019-07-05 19:08:33 +020028using ::testing::InvokeWithoutArgs;
perkjd52063f2016-09-07 06:32:18 -070029
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000030namespace {
Yves Gerey665174f2018-06-19 15:03:05 +020031const int kWidth = 640;
32const int kHeight = 480;
33// Corresponds to load of 15%
34const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
35const int kProcessTimeUs = 5 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000036} // namespace
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000037
sprangb1ca0732017-02-01 08:38:12 -080038class MockCpuOveruseObserver : public AdaptationObserverInterface {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000039 public:
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +000040 MockCpuOveruseObserver() {}
41 virtual ~MockCpuOveruseObserver() {}
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000042
sprangb1ca0732017-02-01 08:38:12 -080043 MOCK_METHOD1(AdaptUp, void(AdaptReason));
Åsa Perssonf5e5d252019-08-16 17:24:59 +020044 MOCK_METHOD1(AdaptDown, bool(AdaptReason));
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000045};
46
sprangb1ca0732017-02-01 08:38:12 -080047class CpuOveruseObserverImpl : public AdaptationObserverInterface {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000048 public:
Yves Gerey665174f2018-06-19 15:03:05 +020049 CpuOveruseObserverImpl() : overuse_(0), normaluse_(0) {}
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000050 virtual ~CpuOveruseObserverImpl() {}
51
Åsa Perssonf5e5d252019-08-16 17:24:59 +020052 bool AdaptDown(AdaptReason) {
53 ++overuse_;
54 return true;
55 }
sprangb1ca0732017-02-01 08:38:12 -080056 void AdaptUp(AdaptReason) { ++normaluse_; }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000057
58 int overuse_;
59 int normaluse_;
60};
61
perkjd52063f2016-09-07 06:32:18 -070062class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
63 public:
Niels Möllerd1f7eb62018-03-28 16:40:58 +020064 explicit OveruseFrameDetectorUnderTest(
65 CpuOveruseMetricsObserver* metrics_observer)
66 : OveruseFrameDetector(metrics_observer) {}
perkjd52063f2016-09-07 06:32:18 -070067 ~OveruseFrameDetectorUnderTest() {}
68
69 using OveruseFrameDetector::CheckForOveruse;
Niels Möllerd1f7eb62018-03-28 16:40:58 +020070 using OveruseFrameDetector::SetOptions;
perkjd52063f2016-09-07 06:32:18 -070071};
72
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000073class OveruseFrameDetectorTest : public ::testing::Test,
74 public CpuOveruseMetricsObserver {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000075 protected:
nisseef8b61e2016-04-29 06:09:15 -070076 void SetUp() override {
Niels Möller73f29cb2018-01-31 16:09:31 +010077 observer_ = &mock_observer_;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000078 options_.min_process_count = 0;
Mirko Bonadei317a1f02019-09-17 17:06:18 +020079 overuse_detector_ = std::make_unique<OveruseFrameDetectorUnderTest>(this);
Niels Möllerd1f7eb62018-03-28 16:40:58 +020080 // Unfortunately, we can't call SetOptions here, since that would break
81 // single-threading requirements in the RunOnTqNormalUsage test.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000082 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +000083
Peter Boströme4499152016-02-05 11:13:28 +010084 void OnEncodedFrameTimeMeasured(int encode_time_ms,
Niels Möller213618e2018-07-24 09:29:58 +020085 int encode_usage_percent) override {
86 encode_usage_percent_ = encode_usage_percent;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000087 }
88
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000089 int InitialUsage() {
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000090 return ((options_.low_encode_usage_threshold_percent +
Yves Gerey665174f2018-06-19 15:03:05 +020091 options_.high_encode_usage_threshold_percent) /
92 2.0f) +
93 0.5;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000094 }
95
Niels Möller83dbeac2017-12-14 16:39:44 +010096 virtual void InsertAndSendFramesWithInterval(int num_frames,
97 int interval_us,
98 int width,
99 int height,
100 int delay_us) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100101 VideoFrame frame =
102 VideoFrame::Builder()
103 .set_video_frame_buffer(I420Buffer::Create(width, height))
104 .set_rotation(webrtc::kVideoRotation_0)
105 .set_timestamp_us(0)
106 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100107 uint32_t timestamp = 0;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000108 while (num_frames-- > 0) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100109 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100110 int64_t capture_time_us = rtc::TimeMicros();
111 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200112 clock_.AdvanceTime(TimeDelta::us(delay_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100113 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
114 capture_time_us, delay_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200115 clock_.AdvanceTime(TimeDelta::us(interval_us - delay_us));
Niels Möller7dc26b72017-12-06 10:27:48 +0100116 timestamp += interval_us * 90 / 1000;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000117 }
118 }
119
Niels Möllerf5033ad2018-08-14 17:00:46 +0200120 virtual void InsertAndSendSimulcastFramesWithInterval(
121 int num_frames,
122 int interval_us,
123 int width,
124 int height,
125 // One element per layer
126 rtc::ArrayView<const int> delays_us) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100127 VideoFrame frame =
128 VideoFrame::Builder()
129 .set_video_frame_buffer(I420Buffer::Create(width, height))
130 .set_rotation(webrtc::kVideoRotation_0)
131 .set_timestamp_us(0)
132 .build();
Niels Möllerf5033ad2018-08-14 17:00:46 +0200133 uint32_t timestamp = 0;
134 while (num_frames-- > 0) {
135 frame.set_timestamp(timestamp);
136 int64_t capture_time_us = rtc::TimeMicros();
137 overuse_detector_->FrameCaptured(frame, capture_time_us);
138 int max_delay_us = 0;
139 for (int delay_us : delays_us) {
140 if (delay_us > max_delay_us) {
Sebastian Jansson40889f32019-04-17 12:11:20 +0200141 clock_.AdvanceTime(TimeDelta::us(delay_us - max_delay_us));
Niels Möllerf5033ad2018-08-14 17:00:46 +0200142 max_delay_us = delay_us;
143 }
144
145 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
146 capture_time_us, delay_us);
147 }
148 overuse_detector_->CheckForOveruse(observer_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200149 clock_.AdvanceTime(TimeDelta::us(interval_us - max_delay_us));
Niels Möllerf5033ad2018-08-14 17:00:46 +0200150 timestamp += interval_us * 90 / 1000;
151 }
152 }
153
Niels Möller83dbeac2017-12-14 16:39:44 +0100154 virtual void InsertAndSendFramesWithRandomInterval(int num_frames,
155 int min_interval_us,
156 int max_interval_us,
157 int width,
158 int height,
159 int delay_us) {
Niels Möllere541be72017-12-13 13:03:10 +0100160 webrtc::Random random(17);
161
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100162 VideoFrame frame =
163 VideoFrame::Builder()
164 .set_video_frame_buffer(I420Buffer::Create(width, height))
165 .set_rotation(webrtc::kVideoRotation_0)
166 .set_timestamp_us(0)
167 .build();
Niels Möllere541be72017-12-13 13:03:10 +0100168 uint32_t timestamp = 0;
169 while (num_frames-- > 0) {
170 frame.set_timestamp(timestamp);
171 int interval_us = random.Rand(min_interval_us, max_interval_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100172 int64_t capture_time_us = rtc::TimeMicros();
173 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200174 clock_.AdvanceTime(TimeDelta::us(delay_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100175 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
176 capture_time_us,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200177 absl::optional<int>(delay_us));
Niels Möllere541be72017-12-13 13:03:10 +0100178
Niels Möller73f29cb2018-01-31 16:09:31 +0100179 overuse_detector_->CheckForOveruse(observer_);
Niels Möllere541be72017-12-13 13:03:10 +0100180 // Avoid turning clock backwards.
181 if (interval_us > delay_us)
Sebastian Jansson40889f32019-04-17 12:11:20 +0200182 clock_.AdvanceTime(TimeDelta::us(interval_us - delay_us));
Niels Möllere541be72017-12-13 13:03:10 +0100183
184 timestamp += interval_us * 90 / 1000;
185 }
186 }
187
Niels Möller83dbeac2017-12-14 16:39:44 +0100188 virtual void ForceUpdate(int width, int height) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100189 // Insert one frame, wait a second and then put in another to force update
190 // the usage. From the tests where these are used, adding another sample
191 // doesn't affect the expected outcome (this is mainly to check initial
192 // values and whether the overuse detector has been reset or not).
Yves Gerey665174f2018-06-19 15:03:05 +0200193 InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec, width, height,
194 kFrameIntervalUs);
Peter Boströme4499152016-02-05 11:13:28 +0100195 }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000196 void TriggerOveruse(int num_times) {
nissee0e3bdf2017-01-18 02:16:20 -0800197 const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000198 for (int i = 0; i < num_times; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200199 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
200 kDelayUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100201 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000202 }
203 }
204
Åsa Persson746210f2015-09-08 10:52:42 +0200205 void TriggerUnderuse() {
nissee0e3bdf2017-01-18 02:16:20 -0800206 const int kDelayUs1 = 5000;
207 const int kDelayUs2 = 6000;
Yves Gerey665174f2018-06-19 15:03:05 +0200208 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
209 kDelayUs1);
210 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
211 kDelayUs2);
Niels Möller73f29cb2018-01-31 16:09:31 +0100212 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000213 }
214
Niels Möller213618e2018-07-24 09:29:58 +0200215 int UsagePercent() { return encode_usage_percent_; }
asapersson@webrtc.orgab6bf4f2014-05-27 07:43:15 +0000216
sprangfda496a2017-06-15 04:21:07 -0700217 int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
218 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
219 int64_t max_processing_time_us =
220 (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
221 return max_processing_time_us;
222 }
223
224 int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
225 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
226 int64_t max_processing_time_us =
227 (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
228 return max_processing_time_us;
229 }
230
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000231 CpuOveruseOptions options_;
nissee0e3bdf2017-01-18 02:16:20 -0800232 rtc::ScopedFakeClock clock_;
Niels Möller73f29cb2018-01-31 16:09:31 +0100233 MockCpuOveruseObserver mock_observer_;
234 AdaptationObserverInterface* observer_;
perkjd52063f2016-09-07 06:32:18 -0700235 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
Niels Möller213618e2018-07-24 09:29:58 +0200236 int encode_usage_percent_ = -1;
kthelgason876222f2016-11-29 01:44:11 -0800237
sprangb1ca0732017-02-01 08:38:12 -0800238 static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000239};
240
Åsa Persson746210f2015-09-08 10:52:42 +0200241// UsagePercent() > high_encode_usage_threshold_percent => overuse.
242// UsagePercent() < low_encode_usage_threshold_percent => underuse.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000243TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
Åsa Persson746210f2015-09-08 10:52:42 +0200244 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200245 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100246 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000247 TriggerOveruse(options_.high_threshold_consecutive_count);
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000248}
249
250TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
Åsa Persson746210f2015-09-08 10:52:42 +0200251 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200252 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100253 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000254 TriggerOveruse(options_.high_threshold_consecutive_count);
Åsa Persson746210f2015-09-08 10:52:42 +0200255 // usage < low => underuse
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200256 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000257 TriggerUnderuse();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000258}
259
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000260TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200261 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100262 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000263 TriggerOveruse(options_.high_threshold_consecutive_count);
264 TriggerOveruse(options_.high_threshold_consecutive_count);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200265 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000266 TriggerUnderuse();
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000267}
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000268
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000269TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
nissee0e3bdf2017-01-18 02:16:20 -0800270 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000271 options_.min_process_count = 1;
Peter Boström4b91bd02015-06-26 06:58:16 +0200272 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100273 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200274 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200275 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
276 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100277 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200278 EXPECT_EQ(0, overuse_observer.normaluse_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200279 clock_.AdvanceTime(TimeDelta::us(kProcessIntervalUs));
Niels Möller73f29cb2018-01-31 16:09:31 +0100280 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200281 EXPECT_EQ(1, overuse_observer.normaluse_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000282}
283
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000284TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200285 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100286 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
287 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100288 for (size_t i = 0; i < 64; ++i) {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000289 TriggerOveruse(options_.high_threshold_consecutive_count);
290 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000291}
292
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000293TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200294 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100295 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000296 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200297 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000298 TriggerOveruse(2);
299}
300
301TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200302 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100303 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000304 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200305 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000306 TriggerOveruse(1);
307}
308
Åsa Persson746210f2015-09-08 10:52:42 +0200309TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200310 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200311 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
312 kProcessTimeUs);
nissee0e3bdf2017-01-18 02:16:20 -0800313 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000314}
315
Åsa Persson746210f2015-09-08 10:52:42 +0200316TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200317 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100318 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200319 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200320 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
321 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200322 EXPECT_NE(InitialUsage(), UsagePercent());
Peter Boströme4499152016-02-05 11:13:28 +0100323 // Verify reset (with new width/height).
324 ForceUpdate(kWidth, kHeight + 1);
Åsa Persson746210f2015-09-08 10:52:42 +0200325 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000326}
327
Åsa Persson746210f2015-09-08 10:52:42 +0200328TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200329 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100330 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200331 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200332 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
333 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200334 EXPECT_NE(InitialUsage(), UsagePercent());
335 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200336 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
337 kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200338 EXPECT_NE(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000339 // Verify reset.
Åsa Persson746210f2015-09-08 10:52:42 +0200340 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200341 2,
342 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
343 kWidth, kHeight, kProcessTimeUs);
Peter Boströme4499152016-02-05 11:13:28 +0100344 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200345 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000346}
347
Niels Möller7dc26b72017-12-06 10:27:48 +0100348TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
349 options_.min_frame_samples = 40;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200350 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200351 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
352 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100353 EXPECT_EQ(InitialUsage(), UsagePercent());
354 // Pass time far enough to digest all previous samples.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200355 clock_.AdvanceTime(TimeDelta::seconds(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100356 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
357 kProcessTimeUs);
358 // The last sample has not been processed here.
359 EXPECT_EQ(InitialUsage(), UsagePercent());
360
361 // Pass time far enough to digest all previous samples, 41 in total.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200362 clock_.AdvanceTime(TimeDelta::seconds(1));
Yves Gerey665174f2018-06-19 15:03:05 +0200363 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
364 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100365 EXPECT_NE(InitialUsage(), UsagePercent());
366}
367
Åsa Persson746210f2015-09-08 10:52:42 +0200368TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200369 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100370 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200371 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000372}
373
Niels Möller7dc26b72017-12-06 10:27:48 +0100374TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200375 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200376 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100377 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
378 static const size_t kNumFramesEncodingDelay = 3;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100379 VideoFrame frame =
380 VideoFrame::Builder()
381 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
382 .set_rotation(webrtc::kVideoRotation_0)
383 .set_timestamp_us(0)
384 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100385 for (size_t i = 0; i < 1000; ++i) {
386 // Unique timestamps.
387 frame.set_timestamp(static_cast<uint32_t>(i));
Niels Möller83dbeac2017-12-14 16:39:44 +0100388 int64_t capture_time_us = rtc::TimeMicros();
389 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200390 clock_.AdvanceTime(TimeDelta::us(kIntervalUs));
Niels Möller7dc26b72017-12-06 10:27:48 +0100391 if (i > kNumFramesEncodingDelay) {
392 overuse_detector_->FrameSent(
Niels Möller83dbeac2017-12-14 16:39:44 +0100393 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
394 capture_time_us, kIntervalUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100395 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100396 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100397 }
398}
399
400TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
401 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200402 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200403 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100404 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
405 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100406 VideoFrame frame =
407 VideoFrame::Builder()
408 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
409 .set_rotation(webrtc::kVideoRotation_0)
410 .set_timestamp_us(0)
411 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100412 uint32_t timestamp = 0;
413 for (size_t i = 0; i < 1000; ++i) {
414 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100415 int64_t capture_time_us = rtc::TimeMicros();
416 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100417 // Encode and send first parts almost instantly.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200418 clock_.AdvanceTime(TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100419 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
420 rtc::kNumMicrosecsPerMillisec);
Niels Möller7dc26b72017-12-06 10:27:48 +0100421 // Encode heavier part, resulting in >85% usage total.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200422 clock_.AdvanceTime(TimeDelta::us(kDelayUs) - TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100423 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
424 kDelayUs);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200425 clock_.AdvanceTime(TimeDelta::us(kIntervalUs - kDelayUs));
Niels Möller7dc26b72017-12-06 10:27:48 +0100426 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100427 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100428 }
429}
430
perkjd52063f2016-09-07 06:32:18 -0700431TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100432 TaskQueueForTest queue("OveruseFrameDetectorTestQueue");
433
Danil Chapovaloveb90e6f2019-10-15 10:04:57 +0200434 queue.SendTask(
435 [&] {
436 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
437 },
438 RTC_FROM_HERE);
perkjd52063f2016-09-07 06:32:18 -0700439
Niels Möllerc572ff32018-11-07 08:43:50 +0100440 rtc::Event event;
perkjd52063f2016-09-07 06:32:18 -0700441 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
442 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100443 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
kthelgason876222f2016-11-29 01:44:11 -0800444 .WillOnce(InvokeWithoutArgs([this, &event] {
perkjd52063f2016-09-07 06:32:18 -0700445 overuse_detector_->StopCheckForOveruse();
446 event.Set();
447 }));
448
eladalon1cc5fc32017-08-23 04:15:18 -0700449 queue.PostTask([this] {
nissee0e3bdf2017-01-18 02:16:20 -0800450 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
451 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
452 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
453 kDelayUs1);
454 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
455 kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700456 });
457
458 EXPECT_TRUE(event.Wait(10000));
459}
460
Niels Möller7dc26b72017-12-06 10:27:48 +0100461TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
462 const int kCapturerMaxFrameRate = 30;
463 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
sprangfda496a2017-06-15 04:21:07 -0700464
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200465 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100466 // Trigger overuse.
467 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
468 // Processing time just below over use limit given kEncodeMaxFrameRate.
469 int64_t processing_time_us =
470 (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100471 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100472 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
473 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
474 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100475 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700476 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100477
478 // Simulate frame rate reduction and normal usage.
479 frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
480 overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
Niels Möller73f29cb2018-01-31 16:09:31 +0100481 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100482 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
483 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
484 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100485 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100486 }
487
488 // Reduce processing time to trigger underuse.
489 processing_time_us =
490 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100491 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100492 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
493 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100494 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700495}
496
Niels Möller7dc26b72017-12-06 10:27:48 +0100497TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
498 const int kMinFrameRate = 7; // Minimum fps allowed by current detector impl.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200499 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100500 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
sprangfda496a2017-06-15 04:21:07 -0700501
Niels Möller7dc26b72017-12-06 10:27:48 +0100502 // Normal usage just at the limit.
503 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
504 // Processing time just below over use limit given kEncodeMaxFrameRate.
505 int64_t processing_time_us =
506 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100507 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100508 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
509 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
510 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100511 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700512 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100513
514 // Over the limit to overuse.
515 processing_time_us =
516 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100517 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100518 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
519 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
520 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100521 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100522 }
523
524 // Reduce input frame rate. Should still trigger overuse.
525 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
Niels Möller73f29cb2018-01-31 16:09:31 +0100526 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100527 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
528 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
529 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100530 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100531 }
532}
533
534TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
535 const int kMaxFrameRate = 20;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200536 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100537 overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
538 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
539 // Maximum frame interval allowed is 35% above ideal.
540 int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
541 // Maximum processing time, without triggering overuse, allowed with the above
542 // frame interval.
543 int64_t max_processing_time_us =
544 (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
545 100;
546
547 // Processing time just below overuse limit given kMaxFrameRate.
548 int64_t processing_time_us = (98 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100549 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100550 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
551 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
552 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100553 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100554 }
555
556 // Go above limit, trigger overuse.
557 processing_time_us = (102 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100558 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100559 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
560 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
561 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100562 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100563 }
564
565 // Increase frame interval, should still trigger overuse.
566 max_frame_interval_us *= 2;
Niels Möller73f29cb2018-01-31 16:09:31 +0100567 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100568 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
569 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
570 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100571 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100572 }
sprangfda496a2017-06-15 04:21:07 -0700573}
574
Niels Möllere541be72017-12-13 13:03:10 +0100575// Models screencast, with irregular arrival of frames which are heavy
576// to encode.
577TEST_F(OveruseFrameDetectorTest, NoOveruseForLargeRandomFrameInterval) {
578 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
579 // behavior is improved in this scenario, with only AdaptUp events,
580 // and estimated load closer to the true average.
581
Niels Möller73f29cb2018-01-31 16:09:31 +0100582 // EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
583 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200584 // .Times(::testing::AtLeast(1));
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200585 overuse_detector_->SetOptions(options_);
Niels Möllere541be72017-12-13 13:03:10 +0100586
587 const int kNumFrames = 500;
588 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
589
590 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
591 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
592
593 const int kTargetFramerate = 5;
594
595 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
596
Yves Gerey665174f2018-06-19 15:03:05 +0200597 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
598 kMaxIntervalUs, kWidth, kHeight,
599 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100600 // Average usage 19%. Check that estimate is in the right ball park.
601 // EXPECT_NEAR(UsagePercent(), 20, 10);
602 EXPECT_NEAR(UsagePercent(), 20, 35);
603}
604
605// Models screencast, with irregular arrival of frames, often
606// exceeding the timeout interval.
607TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
608 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
609 // behavior is improved in this scenario, and we get AdaptUp events.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200610 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100611 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
612 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200613 // .Times(::testing::AtLeast(1));
Niels Möllere541be72017-12-13 13:03:10 +0100614
615 const int kNumFrames = 500;
616 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
617
618 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
619 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
620
621 const int kTargetFramerate = 5;
622
623 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
624
Yves Gerey665174f2018-06-19 15:03:05 +0200625 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
626 kMaxIntervalUs, kWidth, kHeight,
627 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100628
629 // Average usage 6.6%, but since the frame_timeout_interval_ms is
630 // only 1500 ms, we often reset the estimate to the initial value.
631 // Check that estimate is in the right ball park.
632 EXPECT_GE(UsagePercent(), 1);
633 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
634}
635
Niels Möllerf5033ad2018-08-14 17:00:46 +0200636// Models simulcast, with multiple encoded frames for each input frame.
637// Load estimate should be based on the maximum encode time per input frame.
638TEST_F(OveruseFrameDetectorTest, NoOveruseForSimulcast) {
639 overuse_detector_->SetOptions(options_);
640 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
641
642 constexpr int kNumFrames = 500;
643 constexpr int kEncodeTimesUs[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +0200644 10 * rtc::kNumMicrosecsPerMillisec,
645 8 * rtc::kNumMicrosecsPerMillisec,
Niels Möllerf5033ad2018-08-14 17:00:46 +0200646 12 * rtc::kNumMicrosecsPerMillisec,
647 };
648 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
649
650 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
651 kHeight, kEncodeTimesUs);
652
653 // Average usage 40%. 12 ms / 30 ms.
654 EXPECT_GE(UsagePercent(), 35);
655 EXPECT_LE(UsagePercent(), 45);
656}
657
Niels Möller83dbeac2017-12-14 16:39:44 +0100658// Tests using new cpu load estimator
659class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
660 protected:
661 void SetUp() override {
662 options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
663 OveruseFrameDetectorTest::SetUp();
664 }
665
666 void InsertAndSendFramesWithInterval(int num_frames,
667 int interval_us,
668 int width,
669 int height,
670 int delay_us) override {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100671 VideoFrame frame =
672 VideoFrame::Builder()
673 .set_video_frame_buffer(I420Buffer::Create(width, height))
674 .set_rotation(webrtc::kVideoRotation_0)
675 .set_timestamp_us(0)
676 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100677 while (num_frames-- > 0) {
678 int64_t capture_time_us = rtc::TimeMicros();
679 overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
680 overuse_detector_->FrameSent(0 /* ignored timestamp */,
681 0 /* ignored send_time_us */,
682 capture_time_us, delay_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200683 clock_.AdvanceTime(TimeDelta::us(interval_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100684 }
685 }
686
687 void InsertAndSendFramesWithRandomInterval(int num_frames,
688 int min_interval_us,
689 int max_interval_us,
690 int width,
691 int height,
692 int delay_us) override {
693 webrtc::Random random(17);
694
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100695 VideoFrame frame =
696 VideoFrame::Builder()
697 .set_video_frame_buffer(I420Buffer::Create(width, height))
698 .set_rotation(webrtc::kVideoRotation_0)
699 .set_timestamp_us(0)
700 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100701 for (int i = 0; i < num_frames; i++) {
702 int interval_us = random.Rand(min_interval_us, max_interval_us);
703 int64_t capture_time_us = rtc::TimeMicros();
704 overuse_detector_->FrameCaptured(frame, capture_time_us);
705 overuse_detector_->FrameSent(0 /* ignored timestamp */,
706 0 /* ignored send_time_us */,
707 capture_time_us, delay_us);
708
Niels Möller73f29cb2018-01-31 16:09:31 +0100709 overuse_detector_->CheckForOveruse(observer_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200710 clock_.AdvanceTime(TimeDelta::us(interval_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100711 }
712 }
713
714 void ForceUpdate(int width, int height) override {
715 // This is mainly to check initial values and whether the overuse
716 // detector has been reset or not.
717 InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
718 kFrameIntervalUs);
719 }
720};
721
722// UsagePercent() > high_encode_usage_threshold_percent => overuse.
723// UsagePercent() < low_encode_usage_threshold_percent => underuse.
724TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
725 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200726 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100727 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100728 TriggerOveruse(options_.high_threshold_consecutive_count);
729}
730
731TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
732 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200733 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100734 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100735 TriggerOveruse(options_.high_threshold_consecutive_count);
736 // usage < low => underuse
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200737 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100738 TriggerUnderuse();
739}
740
741TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200742 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100743 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
Niels Möller83dbeac2017-12-14 16:39:44 +0100744 TriggerOveruse(options_.high_threshold_consecutive_count);
745 TriggerOveruse(options_.high_threshold_consecutive_count);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200746 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100747 TriggerUnderuse();
748}
749
750TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
751 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
752 options_.min_process_count = 1;
753 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100754 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200755 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200756 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
757 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100758 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100759 EXPECT_EQ(0, overuse_observer.normaluse_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200760 clock_.AdvanceTime(TimeDelta::us(kProcessIntervalUs));
Niels Möller73f29cb2018-01-31 16:09:31 +0100761 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100762 EXPECT_EQ(1, overuse_observer.normaluse_);
763}
764
765TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200766 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100767 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
768 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
Niels Möller83dbeac2017-12-14 16:39:44 +0100769 for (size_t i = 0; i < 64; ++i) {
770 TriggerOveruse(options_.high_threshold_consecutive_count);
771 }
772}
773
774TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100775 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100776 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200777 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100778 TriggerOveruse(2);
779}
780
781TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100782 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller83dbeac2017-12-14 16:39:44 +0100783 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200784 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100785 TriggerOveruse(1);
786}
787
788TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200789 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200790 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
791 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100792 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
793}
794
795TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200796 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100797 ForceUpdate(kWidth, kHeight);
798 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200799 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
800 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100801 EXPECT_NE(InitialUsage(), UsagePercent());
802 // Verify reset (with new width/height).
803 ForceUpdate(kWidth, kHeight + 1);
804 EXPECT_EQ(InitialUsage(), UsagePercent());
805}
806
807TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200808 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100809 ForceUpdate(kWidth, kHeight);
810 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200811 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
812 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100813 EXPECT_NE(InitialUsage(), UsagePercent());
814 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200815 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
816 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100817 EXPECT_NE(InitialUsage(), UsagePercent());
818 // Verify reset.
819 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200820 2,
821 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
822 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100823 ForceUpdate(kWidth, kHeight);
824 EXPECT_EQ(InitialUsage(), UsagePercent());
825}
826
827TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200828 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100829 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
830 kProcessTimeUs);
831 // No update for the first sample.
832 EXPECT_EQ(InitialUsage(), UsagePercent());
833
834 // Total time approximately 40 * 33ms = 1.3s, significantly less
835 // than the 5s time constant.
Yves Gerey665174f2018-06-19 15:03:05 +0200836 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
837 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100838
839 // Should have started to approach correct load of 15%, but not very far.
840 EXPECT_LT(UsagePercent(), InitialUsage());
841 EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
842
843 // Run for roughly 10s more, should now be closer.
Yves Gerey665174f2018-06-19 15:03:05 +0200844 InsertAndSendFramesWithInterval(300, kFrameIntervalUs, kWidth, kHeight,
845 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100846 EXPECT_NEAR(UsagePercent(), 20, 5);
847}
848
849TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200850 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100851 ForceUpdate(kWidth, kHeight);
852 EXPECT_EQ(InitialUsage(), UsagePercent());
853}
854
855TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200856 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200857 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100858 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
859 static const size_t kNumFramesEncodingDelay = 3;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100860 VideoFrame frame =
861 VideoFrame::Builder()
862 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
863 .set_rotation(webrtc::kVideoRotation_0)
864 .set_timestamp_us(0)
865 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100866 for (size_t i = 0; i < 1000; ++i) {
867 // Unique timestamps.
868 frame.set_timestamp(static_cast<uint32_t>(i));
869 int64_t capture_time_us = rtc::TimeMicros();
870 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200871 clock_.AdvanceTime(TimeDelta::us(kIntervalUs));
Niels Möller83dbeac2017-12-14 16:39:44 +0100872 if (i > kNumFramesEncodingDelay) {
873 overuse_detector_->FrameSent(
874 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
875 capture_time_us, kIntervalUs);
876 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100877 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100878 }
879}
880
881TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
882 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200883 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200884 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100885 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
886 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100887 VideoFrame frame =
888 VideoFrame::Builder()
889 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
890 .set_rotation(webrtc::kVideoRotation_0)
891 .set_timestamp_us(0)
892 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100893 uint32_t timestamp = 0;
894 for (size_t i = 0; i < 1000; ++i) {
895 frame.set_timestamp(timestamp);
896 int64_t capture_time_us = rtc::TimeMicros();
897 overuse_detector_->FrameCaptured(frame, capture_time_us);
898 // Encode and send first parts almost instantly.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200899 clock_.AdvanceTime(TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100900 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
901 rtc::kNumMicrosecsPerMillisec);
902 // Encode heavier part, resulting in >85% usage total.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200903 clock_.AdvanceTime(TimeDelta::us(kDelayUs) - TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100904 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
905 kDelayUs);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200906 clock_.AdvanceTime(TimeDelta::us(kIntervalUs - kDelayUs));
Niels Möller83dbeac2017-12-14 16:39:44 +0100907 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100908 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100909 }
910}
911
912TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100913 TaskQueueForTest queue("OveruseFrameDetectorTestQueue");
914
Danil Chapovaloveb90e6f2019-10-15 10:04:57 +0200915 queue.SendTask(
916 [&] {
917 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
918 },
919 RTC_FROM_HERE);
Niels Möller83dbeac2017-12-14 16:39:44 +0100920
Niels Möllerc572ff32018-11-07 08:43:50 +0100921 rtc::Event event;
Niels Möller83dbeac2017-12-14 16:39:44 +0100922 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
923 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100924 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100925 .WillOnce(InvokeWithoutArgs([this, &event] {
926 overuse_detector_->StopCheckForOveruse();
927 event.Set();
928 }));
929
930 queue.PostTask([this] {
931 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
932 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
933 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
934 kDelayUs1);
935 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
936 kDelayUs2);
937 });
938
939 EXPECT_TRUE(event.Wait(10000));
940}
941
942// Models screencast, with irregular arrival of frames which are heavy
943// to encode.
944TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200945 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100946 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200947 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100948
949 const int kNumFrames = 500;
950 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
951
952 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
953 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
954
Yves Gerey665174f2018-06-19 15:03:05 +0200955 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
956 kMaxIntervalUs, kWidth, kHeight,
957 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100958 // Average usage 19%. Check that estimate is in the right ball park.
959 EXPECT_NEAR(UsagePercent(), 20, 10);
960}
961
962// Models screencast, with irregular arrival of frames, often
963// exceeding the timeout interval.
964TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200965 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100966 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200967 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100968
969 const int kNumFrames = 500;
970 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
971
972 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
973 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
974
Yves Gerey665174f2018-06-19 15:03:05 +0200975 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
976 kMaxIntervalUs, kWidth, kHeight,
977 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100978
979 // Average usage 6.6%, but since the frame_timeout_interval_ms is
980 // only 1500 ms, we often reset the estimate to the initial value.
981 // Check that estimate is in the right ball park.
982 EXPECT_GE(UsagePercent(), 1);
983 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
984}
985
Niels Möller58d2a5e2018-08-07 16:37:18 +0200986TEST_F(OveruseFrameDetectorTest2, ToleratesOutOfOrderFrames) {
987 overuse_detector_->SetOptions(options_);
988 // Represents a cpu utilization close to 100%. First input frame results in
989 // three encoded frames, and the last of those isn't finished until after the
990 // first encoded frame corresponding to the next input frame.
991 const int kEncodeTimeUs = 30 * rtc::kNumMicrosecsPerMillisec;
Jonas Olssona4d87372019-07-05 19:08:33 +0200992 const int kCaptureTimesMs[] = {33, 33, 66, 33};
Niels Möller58d2a5e2018-08-07 16:37:18 +0200993
994 for (int capture_time_ms : kCaptureTimesMs) {
995 overuse_detector_->FrameSent(
996 0, 0, capture_time_ms * rtc::kNumMicrosecsPerMillisec, kEncodeTimeUs);
997 }
998 EXPECT_GE(UsagePercent(), InitialUsage());
999}
1000
Niels Möllerf5033ad2018-08-14 17:00:46 +02001001// Models simulcast, with multiple encoded frames for each input frame.
1002// Load estimate should be based on the maximum encode time per input frame.
1003TEST_F(OveruseFrameDetectorTest2, NoOveruseForSimulcast) {
1004 overuse_detector_->SetOptions(options_);
1005 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
1006
1007 constexpr int kNumFrames = 500;
1008 constexpr int kEncodeTimesUs[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +02001009 10 * rtc::kNumMicrosecsPerMillisec,
1010 8 * rtc::kNumMicrosecsPerMillisec,
Niels Möllerf5033ad2018-08-14 17:00:46 +02001011 12 * rtc::kNumMicrosecsPerMillisec,
1012 };
1013 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
1014
1015 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
1016 kHeight, kEncodeTimesUs);
1017
1018 // Average usage 40%. 12 ms / 30 ms.
1019 EXPECT_GE(UsagePercent(), 35);
1020 EXPECT_LE(UsagePercent(), 45);
1021}
1022
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +00001023} // namespace webrtc