blob: fac56b9d1ddc9044756e9eeb986c04a82aea5e21 [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
434 queue.SendTask([&] {
435 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
436 });
perkjd52063f2016-09-07 06:32:18 -0700437
Niels Möllerc572ff32018-11-07 08:43:50 +0100438 rtc::Event event;
perkjd52063f2016-09-07 06:32:18 -0700439 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
440 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100441 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
kthelgason876222f2016-11-29 01:44:11 -0800442 .WillOnce(InvokeWithoutArgs([this, &event] {
perkjd52063f2016-09-07 06:32:18 -0700443 overuse_detector_->StopCheckForOveruse();
444 event.Set();
445 }));
446
eladalon1cc5fc32017-08-23 04:15:18 -0700447 queue.PostTask([this] {
nissee0e3bdf2017-01-18 02:16:20 -0800448 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
449 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
450 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
451 kDelayUs1);
452 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
453 kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700454 });
455
456 EXPECT_TRUE(event.Wait(10000));
457}
458
Niels Möller7dc26b72017-12-06 10:27:48 +0100459TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
460 const int kCapturerMaxFrameRate = 30;
461 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
sprangfda496a2017-06-15 04:21:07 -0700462
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200463 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100464 // Trigger overuse.
465 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
466 // Processing time just below over use limit given kEncodeMaxFrameRate.
467 int64_t processing_time_us =
468 (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100469 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100470 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
471 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
472 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100473 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700474 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100475
476 // Simulate frame rate reduction and normal usage.
477 frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
478 overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
Niels Möller73f29cb2018-01-31 16:09:31 +0100479 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100480 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
481 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
482 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100483 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100484 }
485
486 // Reduce processing time to trigger underuse.
487 processing_time_us =
488 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100489 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100490 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
491 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100492 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700493}
494
Niels Möller7dc26b72017-12-06 10:27:48 +0100495TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
496 const int kMinFrameRate = 7; // Minimum fps allowed by current detector impl.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200497 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100498 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
sprangfda496a2017-06-15 04:21:07 -0700499
Niels Möller7dc26b72017-12-06 10:27:48 +0100500 // Normal usage just at the limit.
501 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
502 // Processing time just below over use limit given kEncodeMaxFrameRate.
503 int64_t processing_time_us =
504 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100505 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100506 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
507 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
508 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100509 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700510 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100511
512 // Over the limit to overuse.
513 processing_time_us =
514 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100515 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100516 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
517 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
518 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100519 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100520 }
521
522 // Reduce input frame rate. Should still trigger overuse.
523 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
Niels Möller73f29cb2018-01-31 16:09:31 +0100524 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100525 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
526 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
527 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100528 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100529 }
530}
531
532TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
533 const int kMaxFrameRate = 20;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200534 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100535 overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
536 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
537 // Maximum frame interval allowed is 35% above ideal.
538 int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
539 // Maximum processing time, without triggering overuse, allowed with the above
540 // frame interval.
541 int64_t max_processing_time_us =
542 (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
543 100;
544
545 // Processing time just below overuse limit given kMaxFrameRate.
546 int64_t processing_time_us = (98 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100547 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100548 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
549 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
550 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100551 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100552 }
553
554 // Go above limit, trigger overuse.
555 processing_time_us = (102 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100556 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100557 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
558 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
559 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100560 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100561 }
562
563 // Increase frame interval, should still trigger overuse.
564 max_frame_interval_us *= 2;
Niels Möller73f29cb2018-01-31 16:09:31 +0100565 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100566 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
567 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
568 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100569 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100570 }
sprangfda496a2017-06-15 04:21:07 -0700571}
572
Niels Möllere541be72017-12-13 13:03:10 +0100573// Models screencast, with irregular arrival of frames which are heavy
574// to encode.
575TEST_F(OveruseFrameDetectorTest, NoOveruseForLargeRandomFrameInterval) {
576 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
577 // behavior is improved in this scenario, with only AdaptUp events,
578 // and estimated load closer to the true average.
579
Niels Möller73f29cb2018-01-31 16:09:31 +0100580 // EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
581 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200582 // .Times(::testing::AtLeast(1));
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200583 overuse_detector_->SetOptions(options_);
Niels Möllere541be72017-12-13 13:03:10 +0100584
585 const int kNumFrames = 500;
586 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
587
588 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
589 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
590
591 const int kTargetFramerate = 5;
592
593 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
594
Yves Gerey665174f2018-06-19 15:03:05 +0200595 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
596 kMaxIntervalUs, kWidth, kHeight,
597 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100598 // Average usage 19%. Check that estimate is in the right ball park.
599 // EXPECT_NEAR(UsagePercent(), 20, 10);
600 EXPECT_NEAR(UsagePercent(), 20, 35);
601}
602
603// Models screencast, with irregular arrival of frames, often
604// exceeding the timeout interval.
605TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
606 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
607 // behavior is improved in this scenario, and we get AdaptUp events.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200608 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100609 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
610 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200611 // .Times(::testing::AtLeast(1));
Niels Möllere541be72017-12-13 13:03:10 +0100612
613 const int kNumFrames = 500;
614 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
615
616 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
617 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
618
619 const int kTargetFramerate = 5;
620
621 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
622
Yves Gerey665174f2018-06-19 15:03:05 +0200623 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
624 kMaxIntervalUs, kWidth, kHeight,
625 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100626
627 // Average usage 6.6%, but since the frame_timeout_interval_ms is
628 // only 1500 ms, we often reset the estimate to the initial value.
629 // Check that estimate is in the right ball park.
630 EXPECT_GE(UsagePercent(), 1);
631 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
632}
633
Niels Möllerf5033ad2018-08-14 17:00:46 +0200634// Models simulcast, with multiple encoded frames for each input frame.
635// Load estimate should be based on the maximum encode time per input frame.
636TEST_F(OveruseFrameDetectorTest, NoOveruseForSimulcast) {
637 overuse_detector_->SetOptions(options_);
638 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
639
640 constexpr int kNumFrames = 500;
641 constexpr int kEncodeTimesUs[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +0200642 10 * rtc::kNumMicrosecsPerMillisec,
643 8 * rtc::kNumMicrosecsPerMillisec,
Niels Möllerf5033ad2018-08-14 17:00:46 +0200644 12 * rtc::kNumMicrosecsPerMillisec,
645 };
646 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
647
648 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
649 kHeight, kEncodeTimesUs);
650
651 // Average usage 40%. 12 ms / 30 ms.
652 EXPECT_GE(UsagePercent(), 35);
653 EXPECT_LE(UsagePercent(), 45);
654}
655
Niels Möller83dbeac2017-12-14 16:39:44 +0100656// Tests using new cpu load estimator
657class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
658 protected:
659 void SetUp() override {
660 options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
661 OveruseFrameDetectorTest::SetUp();
662 }
663
664 void InsertAndSendFramesWithInterval(int num_frames,
665 int interval_us,
666 int width,
667 int height,
668 int delay_us) override {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100669 VideoFrame frame =
670 VideoFrame::Builder()
671 .set_video_frame_buffer(I420Buffer::Create(width, height))
672 .set_rotation(webrtc::kVideoRotation_0)
673 .set_timestamp_us(0)
674 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100675 while (num_frames-- > 0) {
676 int64_t capture_time_us = rtc::TimeMicros();
677 overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
678 overuse_detector_->FrameSent(0 /* ignored timestamp */,
679 0 /* ignored send_time_us */,
680 capture_time_us, delay_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200681 clock_.AdvanceTime(TimeDelta::us(interval_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100682 }
683 }
684
685 void InsertAndSendFramesWithRandomInterval(int num_frames,
686 int min_interval_us,
687 int max_interval_us,
688 int width,
689 int height,
690 int delay_us) override {
691 webrtc::Random random(17);
692
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100693 VideoFrame frame =
694 VideoFrame::Builder()
695 .set_video_frame_buffer(I420Buffer::Create(width, height))
696 .set_rotation(webrtc::kVideoRotation_0)
697 .set_timestamp_us(0)
698 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100699 for (int i = 0; i < num_frames; i++) {
700 int interval_us = random.Rand(min_interval_us, max_interval_us);
701 int64_t capture_time_us = rtc::TimeMicros();
702 overuse_detector_->FrameCaptured(frame, capture_time_us);
703 overuse_detector_->FrameSent(0 /* ignored timestamp */,
704 0 /* ignored send_time_us */,
705 capture_time_us, delay_us);
706
Niels Möller73f29cb2018-01-31 16:09:31 +0100707 overuse_detector_->CheckForOveruse(observer_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200708 clock_.AdvanceTime(TimeDelta::us(interval_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100709 }
710 }
711
712 void ForceUpdate(int width, int height) override {
713 // This is mainly to check initial values and whether the overuse
714 // detector has been reset or not.
715 InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
716 kFrameIntervalUs);
717 }
718};
719
720// UsagePercent() > high_encode_usage_threshold_percent => overuse.
721// UsagePercent() < low_encode_usage_threshold_percent => underuse.
722TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
723 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200724 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100725 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100726 TriggerOveruse(options_.high_threshold_consecutive_count);
727}
728
729TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
730 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200731 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100732 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100733 TriggerOveruse(options_.high_threshold_consecutive_count);
734 // usage < low => underuse
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200735 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100736 TriggerUnderuse();
737}
738
739TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200740 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100741 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
Niels Möller83dbeac2017-12-14 16:39:44 +0100742 TriggerOveruse(options_.high_threshold_consecutive_count);
743 TriggerOveruse(options_.high_threshold_consecutive_count);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200744 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100745 TriggerUnderuse();
746}
747
748TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
749 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
750 options_.min_process_count = 1;
751 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100752 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200753 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200754 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
755 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100756 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100757 EXPECT_EQ(0, overuse_observer.normaluse_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200758 clock_.AdvanceTime(TimeDelta::us(kProcessIntervalUs));
Niels Möller73f29cb2018-01-31 16:09:31 +0100759 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100760 EXPECT_EQ(1, overuse_observer.normaluse_);
761}
762
763TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200764 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100765 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
766 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
Niels Möller83dbeac2017-12-14 16:39:44 +0100767 for (size_t i = 0; i < 64; ++i) {
768 TriggerOveruse(options_.high_threshold_consecutive_count);
769 }
770}
771
772TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100773 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100774 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200775 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100776 TriggerOveruse(2);
777}
778
779TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100780 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller83dbeac2017-12-14 16:39:44 +0100781 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200782 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100783 TriggerOveruse(1);
784}
785
786TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200787 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200788 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
789 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100790 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
791}
792
793TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200794 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100795 ForceUpdate(kWidth, kHeight);
796 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200797 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
798 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100799 EXPECT_NE(InitialUsage(), UsagePercent());
800 // Verify reset (with new width/height).
801 ForceUpdate(kWidth, kHeight + 1);
802 EXPECT_EQ(InitialUsage(), UsagePercent());
803}
804
805TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200806 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100807 ForceUpdate(kWidth, kHeight);
808 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200809 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
810 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100811 EXPECT_NE(InitialUsage(), UsagePercent());
812 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200813 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
814 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100815 EXPECT_NE(InitialUsage(), UsagePercent());
816 // Verify reset.
817 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200818 2,
819 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
820 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100821 ForceUpdate(kWidth, kHeight);
822 EXPECT_EQ(InitialUsage(), UsagePercent());
823}
824
825TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200826 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100827 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
828 kProcessTimeUs);
829 // No update for the first sample.
830 EXPECT_EQ(InitialUsage(), UsagePercent());
831
832 // Total time approximately 40 * 33ms = 1.3s, significantly less
833 // than the 5s time constant.
Yves Gerey665174f2018-06-19 15:03:05 +0200834 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
835 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100836
837 // Should have started to approach correct load of 15%, but not very far.
838 EXPECT_LT(UsagePercent(), InitialUsage());
839 EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
840
841 // Run for roughly 10s more, should now be closer.
Yves Gerey665174f2018-06-19 15:03:05 +0200842 InsertAndSendFramesWithInterval(300, kFrameIntervalUs, kWidth, kHeight,
843 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100844 EXPECT_NEAR(UsagePercent(), 20, 5);
845}
846
847TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200848 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100849 ForceUpdate(kWidth, kHeight);
850 EXPECT_EQ(InitialUsage(), UsagePercent());
851}
852
853TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200854 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200855 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100856 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
857 static const size_t kNumFramesEncodingDelay = 3;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100858 VideoFrame frame =
859 VideoFrame::Builder()
860 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
861 .set_rotation(webrtc::kVideoRotation_0)
862 .set_timestamp_us(0)
863 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100864 for (size_t i = 0; i < 1000; ++i) {
865 // Unique timestamps.
866 frame.set_timestamp(static_cast<uint32_t>(i));
867 int64_t capture_time_us = rtc::TimeMicros();
868 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200869 clock_.AdvanceTime(TimeDelta::us(kIntervalUs));
Niels Möller83dbeac2017-12-14 16:39:44 +0100870 if (i > kNumFramesEncodingDelay) {
871 overuse_detector_->FrameSent(
872 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
873 capture_time_us, kIntervalUs);
874 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100875 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100876 }
877}
878
879TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
880 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200881 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200882 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100883 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
884 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100885 VideoFrame frame =
886 VideoFrame::Builder()
887 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
888 .set_rotation(webrtc::kVideoRotation_0)
889 .set_timestamp_us(0)
890 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100891 uint32_t timestamp = 0;
892 for (size_t i = 0; i < 1000; ++i) {
893 frame.set_timestamp(timestamp);
894 int64_t capture_time_us = rtc::TimeMicros();
895 overuse_detector_->FrameCaptured(frame, capture_time_us);
896 // Encode and send first parts almost instantly.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200897 clock_.AdvanceTime(TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100898 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
899 rtc::kNumMicrosecsPerMillisec);
900 // Encode heavier part, resulting in >85% usage total.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200901 clock_.AdvanceTime(TimeDelta::us(kDelayUs) - TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100902 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
903 kDelayUs);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200904 clock_.AdvanceTime(TimeDelta::us(kIntervalUs - kDelayUs));
Niels Möller83dbeac2017-12-14 16:39:44 +0100905 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100906 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100907 }
908}
909
910TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100911 TaskQueueForTest queue("OveruseFrameDetectorTestQueue");
912
913 queue.SendTask([&] {
914 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
915 });
Niels Möller83dbeac2017-12-14 16:39:44 +0100916
Niels Möllerc572ff32018-11-07 08:43:50 +0100917 rtc::Event event;
Niels Möller83dbeac2017-12-14 16:39:44 +0100918 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
919 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100920 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100921 .WillOnce(InvokeWithoutArgs([this, &event] {
922 overuse_detector_->StopCheckForOveruse();
923 event.Set();
924 }));
925
926 queue.PostTask([this] {
927 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
928 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
929 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
930 kDelayUs1);
931 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
932 kDelayUs2);
933 });
934
935 EXPECT_TRUE(event.Wait(10000));
936}
937
938// Models screencast, with irregular arrival of frames which are heavy
939// to encode.
940TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200941 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100942 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200943 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100944
945 const int kNumFrames = 500;
946 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
947
948 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
949 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
950
Yves Gerey665174f2018-06-19 15:03:05 +0200951 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
952 kMaxIntervalUs, kWidth, kHeight,
953 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100954 // Average usage 19%. Check that estimate is in the right ball park.
955 EXPECT_NEAR(UsagePercent(), 20, 10);
956}
957
958// Models screencast, with irregular arrival of frames, often
959// exceeding the timeout interval.
960TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200961 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100962 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200963 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100964
965 const int kNumFrames = 500;
966 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
967
968 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
969 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
970
Yves Gerey665174f2018-06-19 15:03:05 +0200971 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
972 kMaxIntervalUs, kWidth, kHeight,
973 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100974
975 // Average usage 6.6%, but since the frame_timeout_interval_ms is
976 // only 1500 ms, we often reset the estimate to the initial value.
977 // Check that estimate is in the right ball park.
978 EXPECT_GE(UsagePercent(), 1);
979 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
980}
981
Niels Möller58d2a5e2018-08-07 16:37:18 +0200982TEST_F(OveruseFrameDetectorTest2, ToleratesOutOfOrderFrames) {
983 overuse_detector_->SetOptions(options_);
984 // Represents a cpu utilization close to 100%. First input frame results in
985 // three encoded frames, and the last of those isn't finished until after the
986 // first encoded frame corresponding to the next input frame.
987 const int kEncodeTimeUs = 30 * rtc::kNumMicrosecsPerMillisec;
Jonas Olssona4d87372019-07-05 19:08:33 +0200988 const int kCaptureTimesMs[] = {33, 33, 66, 33};
Niels Möller58d2a5e2018-08-07 16:37:18 +0200989
990 for (int capture_time_ms : kCaptureTimesMs) {
991 overuse_detector_->FrameSent(
992 0, 0, capture_time_ms * rtc::kNumMicrosecsPerMillisec, kEncodeTimeUs);
993 }
994 EXPECT_GE(UsagePercent(), InitialUsage());
995}
996
Niels Möllerf5033ad2018-08-14 17:00:46 +0200997// Models simulcast, with multiple encoded frames for each input frame.
998// Load estimate should be based on the maximum encode time per input frame.
999TEST_F(OveruseFrameDetectorTest2, NoOveruseForSimulcast) {
1000 overuse_detector_->SetOptions(options_);
1001 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
1002
1003 constexpr int kNumFrames = 500;
1004 constexpr int kEncodeTimesUs[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +02001005 10 * rtc::kNumMicrosecsPerMillisec,
1006 8 * rtc::kNumMicrosecsPerMillisec,
Niels Möllerf5033ad2018-08-14 17:00:46 +02001007 12 * rtc::kNumMicrosecsPerMillisec,
1008 };
1009 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
1010
1011 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
1012 kHeight, kEncodeTimesUs);
1013
1014 // Average usage 40%. 12 ms / 30 ms.
1015 EXPECT_GE(UsagePercent(), 35);
1016 EXPECT_LE(UsagePercent(), 45);
1017}
1018
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +00001019} // namespace webrtc