blob: 3a1c97c3a9e8f65d9f441211fed4f8238ebd9f4c [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
Steve Anton40d55332019-01-07 10:21:47 -080015#include "absl/memory/memory.h"
Niels Möller4dc66c52018-10-05 14:17:58 +020016#include "api/video/encoded_image.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/video/i420_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/video_coding/utility/quality_scaler.h"
19#include "rtc_base/event.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "rtc_base/fake_clock.h"
Niels Möllere541be72017-12-13 13:03:10 +010021#include "rtc_base/random.h"
Danil Chapovalov07122bc2019-03-26 14:37:01 +010022#include "rtc_base/task_queue_for_test.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "test/gmock.h"
24#include "test/gtest.h"
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000025
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000026namespace webrtc {
perkjd52063f2016-09-07 06:32:18 -070027
Niels Möllere541be72017-12-13 13:03:10 +010028using ::testing::_;
Jonas Olssona4d87372019-07-05 19:08:33 +020029using ::testing::InvokeWithoutArgs;
perkjd52063f2016-09-07 06:32:18 -070030
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000031namespace {
Yves Gerey665174f2018-06-19 15:03:05 +020032const int kWidth = 640;
33const int kHeight = 480;
34// Corresponds to load of 15%
35const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
36const int kProcessTimeUs = 5 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000037} // namespace
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000038
sprangb1ca0732017-02-01 08:38:12 -080039class MockCpuOveruseObserver : public AdaptationObserverInterface {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000040 public:
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +000041 MockCpuOveruseObserver() {}
42 virtual ~MockCpuOveruseObserver() {}
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000043
sprangb1ca0732017-02-01 08:38:12 -080044 MOCK_METHOD1(AdaptUp, void(AdaptReason));
Åsa Perssonf5e5d252019-08-16 17:24:59 +020045 MOCK_METHOD1(AdaptDown, bool(AdaptReason));
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000046};
47
sprangb1ca0732017-02-01 08:38:12 -080048class CpuOveruseObserverImpl : public AdaptationObserverInterface {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000049 public:
Yves Gerey665174f2018-06-19 15:03:05 +020050 CpuOveruseObserverImpl() : overuse_(0), normaluse_(0) {}
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000051 virtual ~CpuOveruseObserverImpl() {}
52
Åsa Perssonf5e5d252019-08-16 17:24:59 +020053 bool AdaptDown(AdaptReason) {
54 ++overuse_;
55 return true;
56 }
sprangb1ca0732017-02-01 08:38:12 -080057 void AdaptUp(AdaptReason) { ++normaluse_; }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000058
59 int overuse_;
60 int normaluse_;
61};
62
perkjd52063f2016-09-07 06:32:18 -070063class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
64 public:
Niels Möllerd1f7eb62018-03-28 16:40:58 +020065 explicit OveruseFrameDetectorUnderTest(
66 CpuOveruseMetricsObserver* metrics_observer)
67 : OveruseFrameDetector(metrics_observer) {}
perkjd52063f2016-09-07 06:32:18 -070068 ~OveruseFrameDetectorUnderTest() {}
69
70 using OveruseFrameDetector::CheckForOveruse;
Niels Möllerd1f7eb62018-03-28 16:40:58 +020071 using OveruseFrameDetector::SetOptions;
perkjd52063f2016-09-07 06:32:18 -070072};
73
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000074class OveruseFrameDetectorTest : public ::testing::Test,
75 public CpuOveruseMetricsObserver {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000076 protected:
nisseef8b61e2016-04-29 06:09:15 -070077 void SetUp() override {
Niels Möller73f29cb2018-01-31 16:09:31 +010078 observer_ = &mock_observer_;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000079 options_.min_process_count = 0;
Karl Wiberg918f50c2018-07-05 11:40:33 +020080 overuse_detector_ = absl::make_unique<OveruseFrameDetectorUnderTest>(this);
Niels Möllerd1f7eb62018-03-28 16:40:58 +020081 // Unfortunately, we can't call SetOptions here, since that would break
82 // single-threading requirements in the RunOnTqNormalUsage test.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000083 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +000084
Peter Boströme4499152016-02-05 11:13:28 +010085 void OnEncodedFrameTimeMeasured(int encode_time_ms,
Niels Möller213618e2018-07-24 09:29:58 +020086 int encode_usage_percent) override {
87 encode_usage_percent_ = encode_usage_percent;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000088 }
89
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000090 int InitialUsage() {
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000091 return ((options_.low_encode_usage_threshold_percent +
Yves Gerey665174f2018-06-19 15:03:05 +020092 options_.high_encode_usage_threshold_percent) /
93 2.0f) +
94 0.5;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000095 }
96
Niels Möller83dbeac2017-12-14 16:39:44 +010097 virtual void InsertAndSendFramesWithInterval(int num_frames,
98 int interval_us,
99 int width,
100 int height,
101 int delay_us) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100102 VideoFrame frame =
103 VideoFrame::Builder()
104 .set_video_frame_buffer(I420Buffer::Create(width, height))
105 .set_rotation(webrtc::kVideoRotation_0)
106 .set_timestamp_us(0)
107 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100108 uint32_t timestamp = 0;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000109 while (num_frames-- > 0) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100110 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100111 int64_t capture_time_us = rtc::TimeMicros();
112 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200113 clock_.AdvanceTime(TimeDelta::us(delay_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100114 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
115 capture_time_us, delay_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200116 clock_.AdvanceTime(TimeDelta::us(interval_us - delay_us));
Niels Möller7dc26b72017-12-06 10:27:48 +0100117 timestamp += interval_us * 90 / 1000;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000118 }
119 }
120
Niels Möllerf5033ad2018-08-14 17:00:46 +0200121 virtual void InsertAndSendSimulcastFramesWithInterval(
122 int num_frames,
123 int interval_us,
124 int width,
125 int height,
126 // One element per layer
127 rtc::ArrayView<const int> delays_us) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100128 VideoFrame frame =
129 VideoFrame::Builder()
130 .set_video_frame_buffer(I420Buffer::Create(width, height))
131 .set_rotation(webrtc::kVideoRotation_0)
132 .set_timestamp_us(0)
133 .build();
Niels Möllerf5033ad2018-08-14 17:00:46 +0200134 uint32_t timestamp = 0;
135 while (num_frames-- > 0) {
136 frame.set_timestamp(timestamp);
137 int64_t capture_time_us = rtc::TimeMicros();
138 overuse_detector_->FrameCaptured(frame, capture_time_us);
139 int max_delay_us = 0;
140 for (int delay_us : delays_us) {
141 if (delay_us > max_delay_us) {
Sebastian Jansson40889f32019-04-17 12:11:20 +0200142 clock_.AdvanceTime(TimeDelta::us(delay_us - max_delay_us));
Niels Möllerf5033ad2018-08-14 17:00:46 +0200143 max_delay_us = delay_us;
144 }
145
146 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
147 capture_time_us, delay_us);
148 }
149 overuse_detector_->CheckForOveruse(observer_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200150 clock_.AdvanceTime(TimeDelta::us(interval_us - max_delay_us));
Niels Möllerf5033ad2018-08-14 17:00:46 +0200151 timestamp += interval_us * 90 / 1000;
152 }
153 }
154
Niels Möller83dbeac2017-12-14 16:39:44 +0100155 virtual void InsertAndSendFramesWithRandomInterval(int num_frames,
156 int min_interval_us,
157 int max_interval_us,
158 int width,
159 int height,
160 int delay_us) {
Niels Möllere541be72017-12-13 13:03:10 +0100161 webrtc::Random random(17);
162
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100163 VideoFrame frame =
164 VideoFrame::Builder()
165 .set_video_frame_buffer(I420Buffer::Create(width, height))
166 .set_rotation(webrtc::kVideoRotation_0)
167 .set_timestamp_us(0)
168 .build();
Niels Möllere541be72017-12-13 13:03:10 +0100169 uint32_t timestamp = 0;
170 while (num_frames-- > 0) {
171 frame.set_timestamp(timestamp);
172 int interval_us = random.Rand(min_interval_us, max_interval_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100173 int64_t capture_time_us = rtc::TimeMicros();
174 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200175 clock_.AdvanceTime(TimeDelta::us(delay_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100176 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
177 capture_time_us,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200178 absl::optional<int>(delay_us));
Niels Möllere541be72017-12-13 13:03:10 +0100179
Niels Möller73f29cb2018-01-31 16:09:31 +0100180 overuse_detector_->CheckForOveruse(observer_);
Niels Möllere541be72017-12-13 13:03:10 +0100181 // Avoid turning clock backwards.
182 if (interval_us > delay_us)
Sebastian Jansson40889f32019-04-17 12:11:20 +0200183 clock_.AdvanceTime(TimeDelta::us(interval_us - delay_us));
Niels Möllere541be72017-12-13 13:03:10 +0100184
185 timestamp += interval_us * 90 / 1000;
186 }
187 }
188
Niels Möller83dbeac2017-12-14 16:39:44 +0100189 virtual void ForceUpdate(int width, int height) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100190 // Insert one frame, wait a second and then put in another to force update
191 // the usage. From the tests where these are used, adding another sample
192 // doesn't affect the expected outcome (this is mainly to check initial
193 // values and whether the overuse detector has been reset or not).
Yves Gerey665174f2018-06-19 15:03:05 +0200194 InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec, width, height,
195 kFrameIntervalUs);
Peter Boströme4499152016-02-05 11:13:28 +0100196 }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000197 void TriggerOveruse(int num_times) {
nissee0e3bdf2017-01-18 02:16:20 -0800198 const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000199 for (int i = 0; i < num_times; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200200 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
201 kDelayUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100202 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000203 }
204 }
205
Åsa Persson746210f2015-09-08 10:52:42 +0200206 void TriggerUnderuse() {
nissee0e3bdf2017-01-18 02:16:20 -0800207 const int kDelayUs1 = 5000;
208 const int kDelayUs2 = 6000;
Yves Gerey665174f2018-06-19 15:03:05 +0200209 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
210 kDelayUs1);
211 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
212 kDelayUs2);
Niels Möller73f29cb2018-01-31 16:09:31 +0100213 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000214 }
215
Niels Möller213618e2018-07-24 09:29:58 +0200216 int UsagePercent() { return encode_usage_percent_; }
asapersson@webrtc.orgab6bf4f2014-05-27 07:43:15 +0000217
sprangfda496a2017-06-15 04:21:07 -0700218 int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
219 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
220 int64_t max_processing_time_us =
221 (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
222 return max_processing_time_us;
223 }
224
225 int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
226 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
227 int64_t max_processing_time_us =
228 (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
229 return max_processing_time_us;
230 }
231
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000232 CpuOveruseOptions options_;
nissee0e3bdf2017-01-18 02:16:20 -0800233 rtc::ScopedFakeClock clock_;
Niels Möller73f29cb2018-01-31 16:09:31 +0100234 MockCpuOveruseObserver mock_observer_;
235 AdaptationObserverInterface* observer_;
perkjd52063f2016-09-07 06:32:18 -0700236 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
Niels Möller213618e2018-07-24 09:29:58 +0200237 int encode_usage_percent_ = -1;
kthelgason876222f2016-11-29 01:44:11 -0800238
sprangb1ca0732017-02-01 08:38:12 -0800239 static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000240};
241
Åsa Persson746210f2015-09-08 10:52:42 +0200242// UsagePercent() > high_encode_usage_threshold_percent => overuse.
243// UsagePercent() < low_encode_usage_threshold_percent => underuse.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000244TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
Åsa Persson746210f2015-09-08 10:52:42 +0200245 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200246 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100247 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000248 TriggerOveruse(options_.high_threshold_consecutive_count);
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000249}
250
251TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
Åsa Persson746210f2015-09-08 10:52:42 +0200252 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200253 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100254 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000255 TriggerOveruse(options_.high_threshold_consecutive_count);
Åsa Persson746210f2015-09-08 10:52:42 +0200256 // usage < low => underuse
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200257 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000258 TriggerUnderuse();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000259}
260
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000261TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200262 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100263 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000264 TriggerOveruse(options_.high_threshold_consecutive_count);
265 TriggerOveruse(options_.high_threshold_consecutive_count);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200266 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000267 TriggerUnderuse();
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000268}
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000269
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000270TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
nissee0e3bdf2017-01-18 02:16:20 -0800271 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000272 options_.min_process_count = 1;
Peter Boström4b91bd02015-06-26 06:58:16 +0200273 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100274 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200275 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200276 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
277 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100278 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200279 EXPECT_EQ(0, overuse_observer.normaluse_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200280 clock_.AdvanceTime(TimeDelta::us(kProcessIntervalUs));
Niels Möller73f29cb2018-01-31 16:09:31 +0100281 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200282 EXPECT_EQ(1, overuse_observer.normaluse_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000283}
284
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000285TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200286 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100287 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
288 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100289 for (size_t i = 0; i < 64; ++i) {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000290 TriggerOveruse(options_.high_threshold_consecutive_count);
291 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000292}
293
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000294TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200295 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100296 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000297 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200298 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000299 TriggerOveruse(2);
300}
301
302TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200303 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100304 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000305 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200306 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000307 TriggerOveruse(1);
308}
309
Åsa Persson746210f2015-09-08 10:52:42 +0200310TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200311 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200312 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
313 kProcessTimeUs);
nissee0e3bdf2017-01-18 02:16:20 -0800314 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000315}
316
Åsa Persson746210f2015-09-08 10:52:42 +0200317TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200318 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100319 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200320 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200321 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
322 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200323 EXPECT_NE(InitialUsage(), UsagePercent());
Peter Boströme4499152016-02-05 11:13:28 +0100324 // Verify reset (with new width/height).
325 ForceUpdate(kWidth, kHeight + 1);
Åsa Persson746210f2015-09-08 10:52:42 +0200326 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000327}
328
Åsa Persson746210f2015-09-08 10:52:42 +0200329TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200330 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100331 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200332 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200333 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
334 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200335 EXPECT_NE(InitialUsage(), UsagePercent());
336 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200337 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
338 kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200339 EXPECT_NE(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000340 // Verify reset.
Åsa Persson746210f2015-09-08 10:52:42 +0200341 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200342 2,
343 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
344 kWidth, kHeight, kProcessTimeUs);
Peter Boströme4499152016-02-05 11:13:28 +0100345 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200346 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000347}
348
Niels Möller7dc26b72017-12-06 10:27:48 +0100349TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
350 options_.min_frame_samples = 40;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200351 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200352 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
353 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100354 EXPECT_EQ(InitialUsage(), UsagePercent());
355 // Pass time far enough to digest all previous samples.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200356 clock_.AdvanceTime(TimeDelta::seconds(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100357 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
358 kProcessTimeUs);
359 // The last sample has not been processed here.
360 EXPECT_EQ(InitialUsage(), UsagePercent());
361
362 // Pass time far enough to digest all previous samples, 41 in total.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200363 clock_.AdvanceTime(TimeDelta::seconds(1));
Yves Gerey665174f2018-06-19 15:03:05 +0200364 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
365 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100366 EXPECT_NE(InitialUsage(), UsagePercent());
367}
368
Åsa Persson746210f2015-09-08 10:52:42 +0200369TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200370 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100371 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200372 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000373}
374
Niels Möller7dc26b72017-12-06 10:27:48 +0100375TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200376 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200377 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100378 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
379 static const size_t kNumFramesEncodingDelay = 3;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100380 VideoFrame frame =
381 VideoFrame::Builder()
382 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
383 .set_rotation(webrtc::kVideoRotation_0)
384 .set_timestamp_us(0)
385 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100386 for (size_t i = 0; i < 1000; ++i) {
387 // Unique timestamps.
388 frame.set_timestamp(static_cast<uint32_t>(i));
Niels Möller83dbeac2017-12-14 16:39:44 +0100389 int64_t capture_time_us = rtc::TimeMicros();
390 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200391 clock_.AdvanceTime(TimeDelta::us(kIntervalUs));
Niels Möller7dc26b72017-12-06 10:27:48 +0100392 if (i > kNumFramesEncodingDelay) {
393 overuse_detector_->FrameSent(
Niels Möller83dbeac2017-12-14 16:39:44 +0100394 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
395 capture_time_us, kIntervalUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100396 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100397 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100398 }
399}
400
401TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
402 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200403 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200404 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100405 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
406 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100407 VideoFrame frame =
408 VideoFrame::Builder()
409 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
410 .set_rotation(webrtc::kVideoRotation_0)
411 .set_timestamp_us(0)
412 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100413 uint32_t timestamp = 0;
414 for (size_t i = 0; i < 1000; ++i) {
415 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100416 int64_t capture_time_us = rtc::TimeMicros();
417 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100418 // Encode and send first parts almost instantly.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200419 clock_.AdvanceTime(TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100420 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
421 rtc::kNumMicrosecsPerMillisec);
Niels Möller7dc26b72017-12-06 10:27:48 +0100422 // Encode heavier part, resulting in >85% usage total.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200423 clock_.AdvanceTime(TimeDelta::us(kDelayUs) - TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100424 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
425 kDelayUs);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200426 clock_.AdvanceTime(TimeDelta::us(kIntervalUs - kDelayUs));
Niels Möller7dc26b72017-12-06 10:27:48 +0100427 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100428 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100429 }
430}
431
perkjd52063f2016-09-07 06:32:18 -0700432TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100433 TaskQueueForTest queue("OveruseFrameDetectorTestQueue");
434
435 queue.SendTask([&] {
436 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
437 });
perkjd52063f2016-09-07 06:32:18 -0700438
Niels Möllerc572ff32018-11-07 08:43:50 +0100439 rtc::Event event;
perkjd52063f2016-09-07 06:32:18 -0700440 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
441 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100442 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
kthelgason876222f2016-11-29 01:44:11 -0800443 .WillOnce(InvokeWithoutArgs([this, &event] {
perkjd52063f2016-09-07 06:32:18 -0700444 overuse_detector_->StopCheckForOveruse();
445 event.Set();
446 }));
447
eladalon1cc5fc32017-08-23 04:15:18 -0700448 queue.PostTask([this] {
nissee0e3bdf2017-01-18 02:16:20 -0800449 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
450 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
451 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
452 kDelayUs1);
453 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
454 kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700455 });
456
457 EXPECT_TRUE(event.Wait(10000));
458}
459
Niels Möller7dc26b72017-12-06 10:27:48 +0100460TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
461 const int kCapturerMaxFrameRate = 30;
462 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
sprangfda496a2017-06-15 04:21:07 -0700463
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200464 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100465 // Trigger overuse.
466 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
467 // Processing time just below over use limit given kEncodeMaxFrameRate.
468 int64_t processing_time_us =
469 (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100470 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100471 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
472 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
473 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100474 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700475 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100476
477 // Simulate frame rate reduction and normal usage.
478 frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
479 overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
Niels Möller73f29cb2018-01-31 16:09:31 +0100480 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100481 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
482 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
483 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100484 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100485 }
486
487 // Reduce processing time to trigger underuse.
488 processing_time_us =
489 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100490 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100491 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
492 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100493 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700494}
495
Niels Möller7dc26b72017-12-06 10:27:48 +0100496TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
497 const int kMinFrameRate = 7; // Minimum fps allowed by current detector impl.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200498 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100499 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
sprangfda496a2017-06-15 04:21:07 -0700500
Niels Möller7dc26b72017-12-06 10:27:48 +0100501 // Normal usage just at the limit.
502 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
503 // Processing time just below over use limit given kEncodeMaxFrameRate.
504 int64_t processing_time_us =
505 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100506 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100507 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
508 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
509 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100510 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700511 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100512
513 // Over the limit to overuse.
514 processing_time_us =
515 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100516 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100517 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
518 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
519 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100520 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100521 }
522
523 // Reduce input frame rate. Should still trigger overuse.
524 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
Niels Möller73f29cb2018-01-31 16:09:31 +0100525 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100526 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
527 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
528 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100529 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100530 }
531}
532
533TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
534 const int kMaxFrameRate = 20;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200535 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100536 overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
537 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
538 // Maximum frame interval allowed is 35% above ideal.
539 int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
540 // Maximum processing time, without triggering overuse, allowed with the above
541 // frame interval.
542 int64_t max_processing_time_us =
543 (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
544 100;
545
546 // Processing time just below overuse limit given kMaxFrameRate.
547 int64_t processing_time_us = (98 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100548 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100549 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
550 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
551 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100552 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100553 }
554
555 // Go above limit, trigger overuse.
556 processing_time_us = (102 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100557 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100558 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
559 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
560 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100561 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100562 }
563
564 // Increase frame interval, should still trigger overuse.
565 max_frame_interval_us *= 2;
Niels Möller73f29cb2018-01-31 16:09:31 +0100566 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100567 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
568 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
569 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100570 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100571 }
sprangfda496a2017-06-15 04:21:07 -0700572}
573
Niels Möllere541be72017-12-13 13:03:10 +0100574// Models screencast, with irregular arrival of frames which are heavy
575// to encode.
576TEST_F(OveruseFrameDetectorTest, NoOveruseForLargeRandomFrameInterval) {
577 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
578 // behavior is improved in this scenario, with only AdaptUp events,
579 // and estimated load closer to the true average.
580
Niels Möller73f29cb2018-01-31 16:09:31 +0100581 // EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
582 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200583 // .Times(::testing::AtLeast(1));
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200584 overuse_detector_->SetOptions(options_);
Niels Möllere541be72017-12-13 13:03:10 +0100585
586 const int kNumFrames = 500;
587 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
588
589 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
590 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
591
592 const int kTargetFramerate = 5;
593
594 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
595
Yves Gerey665174f2018-06-19 15:03:05 +0200596 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
597 kMaxIntervalUs, kWidth, kHeight,
598 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100599 // Average usage 19%. Check that estimate is in the right ball park.
600 // EXPECT_NEAR(UsagePercent(), 20, 10);
601 EXPECT_NEAR(UsagePercent(), 20, 35);
602}
603
604// Models screencast, with irregular arrival of frames, often
605// exceeding the timeout interval.
606TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
607 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
608 // behavior is improved in this scenario, and we get AdaptUp events.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200609 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100610 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
611 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200612 // .Times(::testing::AtLeast(1));
Niels Möllere541be72017-12-13 13:03:10 +0100613
614 const int kNumFrames = 500;
615 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
616
617 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
618 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
619
620 const int kTargetFramerate = 5;
621
622 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
623
Yves Gerey665174f2018-06-19 15:03:05 +0200624 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
625 kMaxIntervalUs, kWidth, kHeight,
626 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100627
628 // Average usage 6.6%, but since the frame_timeout_interval_ms is
629 // only 1500 ms, we often reset the estimate to the initial value.
630 // Check that estimate is in the right ball park.
631 EXPECT_GE(UsagePercent(), 1);
632 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
633}
634
Niels Möllerf5033ad2018-08-14 17:00:46 +0200635// Models simulcast, with multiple encoded frames for each input frame.
636// Load estimate should be based on the maximum encode time per input frame.
637TEST_F(OveruseFrameDetectorTest, NoOveruseForSimulcast) {
638 overuse_detector_->SetOptions(options_);
639 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
640
641 constexpr int kNumFrames = 500;
642 constexpr int kEncodeTimesUs[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +0200643 10 * rtc::kNumMicrosecsPerMillisec,
644 8 * rtc::kNumMicrosecsPerMillisec,
Niels Möllerf5033ad2018-08-14 17:00:46 +0200645 12 * rtc::kNumMicrosecsPerMillisec,
646 };
647 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
648
649 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
650 kHeight, kEncodeTimesUs);
651
652 // Average usage 40%. 12 ms / 30 ms.
653 EXPECT_GE(UsagePercent(), 35);
654 EXPECT_LE(UsagePercent(), 45);
655}
656
Niels Möller83dbeac2017-12-14 16:39:44 +0100657// Tests using new cpu load estimator
658class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
659 protected:
660 void SetUp() override {
661 options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
662 OveruseFrameDetectorTest::SetUp();
663 }
664
665 void InsertAndSendFramesWithInterval(int num_frames,
666 int interval_us,
667 int width,
668 int height,
669 int delay_us) override {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100670 VideoFrame frame =
671 VideoFrame::Builder()
672 .set_video_frame_buffer(I420Buffer::Create(width, height))
673 .set_rotation(webrtc::kVideoRotation_0)
674 .set_timestamp_us(0)
675 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100676 while (num_frames-- > 0) {
677 int64_t capture_time_us = rtc::TimeMicros();
678 overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
679 overuse_detector_->FrameSent(0 /* ignored timestamp */,
680 0 /* ignored send_time_us */,
681 capture_time_us, delay_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200682 clock_.AdvanceTime(TimeDelta::us(interval_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100683 }
684 }
685
686 void InsertAndSendFramesWithRandomInterval(int num_frames,
687 int min_interval_us,
688 int max_interval_us,
689 int width,
690 int height,
691 int delay_us) override {
692 webrtc::Random random(17);
693
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100694 VideoFrame frame =
695 VideoFrame::Builder()
696 .set_video_frame_buffer(I420Buffer::Create(width, height))
697 .set_rotation(webrtc::kVideoRotation_0)
698 .set_timestamp_us(0)
699 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100700 for (int i = 0; i < num_frames; i++) {
701 int interval_us = random.Rand(min_interval_us, max_interval_us);
702 int64_t capture_time_us = rtc::TimeMicros();
703 overuse_detector_->FrameCaptured(frame, capture_time_us);
704 overuse_detector_->FrameSent(0 /* ignored timestamp */,
705 0 /* ignored send_time_us */,
706 capture_time_us, delay_us);
707
Niels Möller73f29cb2018-01-31 16:09:31 +0100708 overuse_detector_->CheckForOveruse(observer_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200709 clock_.AdvanceTime(TimeDelta::us(interval_us));
Niels Möller83dbeac2017-12-14 16:39:44 +0100710 }
711 }
712
713 void ForceUpdate(int width, int height) override {
714 // This is mainly to check initial values and whether the overuse
715 // detector has been reset or not.
716 InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
717 kFrameIntervalUs);
718 }
719};
720
721// UsagePercent() > high_encode_usage_threshold_percent => overuse.
722// UsagePercent() < low_encode_usage_threshold_percent => underuse.
723TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
724 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200725 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100726 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100727 TriggerOveruse(options_.high_threshold_consecutive_count);
728}
729
730TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
731 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200732 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100733 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100734 TriggerOveruse(options_.high_threshold_consecutive_count);
735 // usage < low => underuse
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200736 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100737 TriggerUnderuse();
738}
739
740TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200741 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100742 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
Niels Möller83dbeac2017-12-14 16:39:44 +0100743 TriggerOveruse(options_.high_threshold_consecutive_count);
744 TriggerOveruse(options_.high_threshold_consecutive_count);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200745 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100746 TriggerUnderuse();
747}
748
749TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
750 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
751 options_.min_process_count = 1;
752 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100753 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200754 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200755 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
756 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100757 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100758 EXPECT_EQ(0, overuse_observer.normaluse_);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200759 clock_.AdvanceTime(TimeDelta::us(kProcessIntervalUs));
Niels Möller73f29cb2018-01-31 16:09:31 +0100760 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100761 EXPECT_EQ(1, overuse_observer.normaluse_);
762}
763
764TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200765 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100766 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
767 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
Niels Möller83dbeac2017-12-14 16:39:44 +0100768 for (size_t i = 0; i < 64; ++i) {
769 TriggerOveruse(options_.high_threshold_consecutive_count);
770 }
771}
772
773TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100774 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100775 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200776 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100777 TriggerOveruse(2);
778}
779
780TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100781 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller83dbeac2017-12-14 16:39:44 +0100782 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200783 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100784 TriggerOveruse(1);
785}
786
787TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200788 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200789 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
790 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100791 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
792}
793
794TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200795 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100796 ForceUpdate(kWidth, kHeight);
797 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200798 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
799 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100800 EXPECT_NE(InitialUsage(), UsagePercent());
801 // Verify reset (with new width/height).
802 ForceUpdate(kWidth, kHeight + 1);
803 EXPECT_EQ(InitialUsage(), UsagePercent());
804}
805
806TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200807 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100808 ForceUpdate(kWidth, kHeight);
809 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200810 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
811 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100812 EXPECT_NE(InitialUsage(), UsagePercent());
813 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200814 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
815 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100816 EXPECT_NE(InitialUsage(), UsagePercent());
817 // Verify reset.
818 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200819 2,
820 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
821 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100822 ForceUpdate(kWidth, kHeight);
823 EXPECT_EQ(InitialUsage(), UsagePercent());
824}
825
826TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200827 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100828 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
829 kProcessTimeUs);
830 // No update for the first sample.
831 EXPECT_EQ(InitialUsage(), UsagePercent());
832
833 // Total time approximately 40 * 33ms = 1.3s, significantly less
834 // than the 5s time constant.
Yves Gerey665174f2018-06-19 15:03:05 +0200835 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
836 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100837
838 // Should have started to approach correct load of 15%, but not very far.
839 EXPECT_LT(UsagePercent(), InitialUsage());
840 EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
841
842 // Run for roughly 10s more, should now be closer.
Yves Gerey665174f2018-06-19 15:03:05 +0200843 InsertAndSendFramesWithInterval(300, kFrameIntervalUs, kWidth, kHeight,
844 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100845 EXPECT_NEAR(UsagePercent(), 20, 5);
846}
847
848TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200849 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100850 ForceUpdate(kWidth, kHeight);
851 EXPECT_EQ(InitialUsage(), UsagePercent());
852}
853
854TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200855 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200856 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100857 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
858 static const size_t kNumFramesEncodingDelay = 3;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100859 VideoFrame frame =
860 VideoFrame::Builder()
861 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
862 .set_rotation(webrtc::kVideoRotation_0)
863 .set_timestamp_us(0)
864 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100865 for (size_t i = 0; i < 1000; ++i) {
866 // Unique timestamps.
867 frame.set_timestamp(static_cast<uint32_t>(i));
868 int64_t capture_time_us = rtc::TimeMicros();
869 overuse_detector_->FrameCaptured(frame, capture_time_us);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200870 clock_.AdvanceTime(TimeDelta::us(kIntervalUs));
Niels Möller83dbeac2017-12-14 16:39:44 +0100871 if (i > kNumFramesEncodingDelay) {
872 overuse_detector_->FrameSent(
873 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
874 capture_time_us, kIntervalUs);
875 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100876 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100877 }
878}
879
880TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
881 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200882 overuse_detector_->SetOptions(options_);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200883 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100884 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
885 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100886 VideoFrame frame =
887 VideoFrame::Builder()
888 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
889 .set_rotation(webrtc::kVideoRotation_0)
890 .set_timestamp_us(0)
891 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100892 uint32_t timestamp = 0;
893 for (size_t i = 0; i < 1000; ++i) {
894 frame.set_timestamp(timestamp);
895 int64_t capture_time_us = rtc::TimeMicros();
896 overuse_detector_->FrameCaptured(frame, capture_time_us);
897 // Encode and send first parts almost instantly.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200898 clock_.AdvanceTime(TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100899 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
900 rtc::kNumMicrosecsPerMillisec);
901 // Encode heavier part, resulting in >85% usage total.
Sebastian Jansson40889f32019-04-17 12:11:20 +0200902 clock_.AdvanceTime(TimeDelta::us(kDelayUs) - TimeDelta::ms(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100903 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
904 kDelayUs);
Sebastian Jansson40889f32019-04-17 12:11:20 +0200905 clock_.AdvanceTime(TimeDelta::us(kIntervalUs - kDelayUs));
Niels Möller83dbeac2017-12-14 16:39:44 +0100906 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100907 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100908 }
909}
910
911TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100912 TaskQueueForTest queue("OveruseFrameDetectorTestQueue");
913
914 queue.SendTask([&] {
915 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
916 });
Niels Möller83dbeac2017-12-14 16:39:44 +0100917
Niels Möllerc572ff32018-11-07 08:43:50 +0100918 rtc::Event event;
Niels Möller83dbeac2017-12-14 16:39:44 +0100919 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
920 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100921 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100922 .WillOnce(InvokeWithoutArgs([this, &event] {
923 overuse_detector_->StopCheckForOveruse();
924 event.Set();
925 }));
926
927 queue.PostTask([this] {
928 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
929 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
930 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
931 kDelayUs1);
932 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
933 kDelayUs2);
934 });
935
936 EXPECT_TRUE(event.Wait(10000));
937}
938
939// Models screencast, with irregular arrival of frames which are heavy
940// to encode.
941TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200942 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100943 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200944 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100945
946 const int kNumFrames = 500;
947 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
948
949 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
950 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
951
Yves Gerey665174f2018-06-19 15:03:05 +0200952 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
953 kMaxIntervalUs, kWidth, kHeight,
954 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100955 // Average usage 19%. Check that estimate is in the right ball park.
956 EXPECT_NEAR(UsagePercent(), 20, 10);
957}
958
959// Models screencast, with irregular arrival of frames, often
960// exceeding the timeout interval.
961TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200962 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100963 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200964 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100965
966 const int kNumFrames = 500;
967 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
968
969 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
970 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
971
Yves Gerey665174f2018-06-19 15:03:05 +0200972 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
973 kMaxIntervalUs, kWidth, kHeight,
974 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100975
976 // Average usage 6.6%, but since the frame_timeout_interval_ms is
977 // only 1500 ms, we often reset the estimate to the initial value.
978 // Check that estimate is in the right ball park.
979 EXPECT_GE(UsagePercent(), 1);
980 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
981}
982
Niels Möller58d2a5e2018-08-07 16:37:18 +0200983TEST_F(OveruseFrameDetectorTest2, ToleratesOutOfOrderFrames) {
984 overuse_detector_->SetOptions(options_);
985 // Represents a cpu utilization close to 100%. First input frame results in
986 // three encoded frames, and the last of those isn't finished until after the
987 // first encoded frame corresponding to the next input frame.
988 const int kEncodeTimeUs = 30 * rtc::kNumMicrosecsPerMillisec;
Jonas Olssona4d87372019-07-05 19:08:33 +0200989 const int kCaptureTimesMs[] = {33, 33, 66, 33};
Niels Möller58d2a5e2018-08-07 16:37:18 +0200990
991 for (int capture_time_ms : kCaptureTimesMs) {
992 overuse_detector_->FrameSent(
993 0, 0, capture_time_ms * rtc::kNumMicrosecsPerMillisec, kEncodeTimeUs);
994 }
995 EXPECT_GE(UsagePercent(), InitialUsage());
996}
997
Niels Möllerf5033ad2018-08-14 17:00:46 +0200998// Models simulcast, with multiple encoded frames for each input frame.
999// Load estimate should be based on the maximum encode time per input frame.
1000TEST_F(OveruseFrameDetectorTest2, NoOveruseForSimulcast) {
1001 overuse_detector_->SetOptions(options_);
1002 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
1003
1004 constexpr int kNumFrames = 500;
1005 constexpr int kEncodeTimesUs[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +02001006 10 * rtc::kNumMicrosecsPerMillisec,
1007 8 * rtc::kNumMicrosecsPerMillisec,
Niels Möllerf5033ad2018-08-14 17:00:46 +02001008 12 * rtc::kNumMicrosecsPerMillisec,
1009 };
1010 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
1011
1012 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
1013 kHeight, kEncodeTimesUs);
1014
1015 // Average usage 40%. 12 ms / 30 ms.
1016 EXPECT_GE(UsagePercent(), 35);
1017 EXPECT_LE(UsagePercent(), 45);
1018}
1019
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +00001020} // namespace webrtc