blob: b356d1d200c690b8815e35f64362e4b865c17132 [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
kwiberg27f982b2016-03-01 11:52:33 -080011#include <memory>
12
Steve Anton40d55332019-01-07 10:21:47 -080013#include "absl/memory/memory.h"
Niels Möller4dc66c52018-10-05 14:17:58 +020014#include "api/video/encoded_image.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/video/i420_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/video_coding/utility/quality_scaler.h"
17#include "rtc_base/event.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/fake_clock.h"
Niels Möllere541be72017-12-13 13:03:10 +010019#include "rtc_base/random.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "test/gmock.h"
21#include "test/gtest.h"
22#include "video/overuse_frame_detector.h"
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000023
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000024namespace webrtc {
perkjd52063f2016-09-07 06:32:18 -070025
kthelgason876222f2016-11-29 01:44:11 -080026using ::testing::InvokeWithoutArgs;
Niels Möllere541be72017-12-13 13:03:10 +010027using ::testing::_;
perkjd52063f2016-09-07 06:32:18 -070028
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000029namespace {
Yves Gerey665174f2018-06-19 15:03:05 +020030const int kWidth = 640;
31const int kHeight = 480;
32// Corresponds to load of 15%
33const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
34const int kProcessTimeUs = 5 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000035} // namespace
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000036
sprangb1ca0732017-02-01 08:38:12 -080037class MockCpuOveruseObserver : public AdaptationObserverInterface {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000038 public:
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +000039 MockCpuOveruseObserver() {}
40 virtual ~MockCpuOveruseObserver() {}
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000041
sprangb1ca0732017-02-01 08:38:12 -080042 MOCK_METHOD1(AdaptUp, void(AdaptReason));
43 MOCK_METHOD1(AdaptDown, void(AdaptReason));
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000044};
45
sprangb1ca0732017-02-01 08:38:12 -080046class CpuOveruseObserverImpl : public AdaptationObserverInterface {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000047 public:
Yves Gerey665174f2018-06-19 15:03:05 +020048 CpuOveruseObserverImpl() : overuse_(0), normaluse_(0) {}
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000049 virtual ~CpuOveruseObserverImpl() {}
50
sprangb1ca0732017-02-01 08:38:12 -080051 void AdaptDown(AdaptReason) { ++overuse_; }
52 void AdaptUp(AdaptReason) { ++normaluse_; }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000053
54 int overuse_;
55 int normaluse_;
56};
57
perkjd52063f2016-09-07 06:32:18 -070058class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
59 public:
Niels Möllerd1f7eb62018-03-28 16:40:58 +020060 explicit OveruseFrameDetectorUnderTest(
61 CpuOveruseMetricsObserver* metrics_observer)
62 : OveruseFrameDetector(metrics_observer) {}
perkjd52063f2016-09-07 06:32:18 -070063 ~OveruseFrameDetectorUnderTest() {}
64
65 using OveruseFrameDetector::CheckForOveruse;
Niels Möllerd1f7eb62018-03-28 16:40:58 +020066 using OveruseFrameDetector::SetOptions;
perkjd52063f2016-09-07 06:32:18 -070067};
68
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000069class OveruseFrameDetectorTest : public ::testing::Test,
70 public CpuOveruseMetricsObserver {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000071 protected:
nisseef8b61e2016-04-29 06:09:15 -070072 void SetUp() override {
Niels Möller73f29cb2018-01-31 16:09:31 +010073 observer_ = &mock_observer_;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000074 options_.min_process_count = 0;
Karl Wiberg918f50c2018-07-05 11:40:33 +020075 overuse_detector_ = absl::make_unique<OveruseFrameDetectorUnderTest>(this);
Niels Möllerd1f7eb62018-03-28 16:40:58 +020076 // Unfortunately, we can't call SetOptions here, since that would break
77 // single-threading requirements in the RunOnTqNormalUsage test.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000078 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +000079
Peter Boströme4499152016-02-05 11:13:28 +010080 void OnEncodedFrameTimeMeasured(int encode_time_ms,
Niels Möller213618e2018-07-24 09:29:58 +020081 int encode_usage_percent) override {
82 encode_usage_percent_ = encode_usage_percent;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000083 }
84
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000085 int InitialUsage() {
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000086 return ((options_.low_encode_usage_threshold_percent +
Yves Gerey665174f2018-06-19 15:03:05 +020087 options_.high_encode_usage_threshold_percent) /
88 2.0f) +
89 0.5;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000090 }
91
Niels Möller83dbeac2017-12-14 16:39:44 +010092 virtual void InsertAndSendFramesWithInterval(int num_frames,
93 int interval_us,
94 int width,
95 int height,
96 int delay_us) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +010097 VideoFrame frame =
98 VideoFrame::Builder()
99 .set_video_frame_buffer(I420Buffer::Create(width, height))
100 .set_rotation(webrtc::kVideoRotation_0)
101 .set_timestamp_us(0)
102 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100103 uint32_t timestamp = 0;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000104 while (num_frames-- > 0) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100105 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100106 int64_t capture_time_us = rtc::TimeMicros();
107 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100108 clock_.AdvanceTimeMicros(delay_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100109 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
110 capture_time_us, delay_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100111 clock_.AdvanceTimeMicros(interval_us - delay_us);
112 timestamp += interval_us * 90 / 1000;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000113 }
114 }
115
Niels Möllerf5033ad2018-08-14 17:00:46 +0200116 virtual void InsertAndSendSimulcastFramesWithInterval(
117 int num_frames,
118 int interval_us,
119 int width,
120 int height,
121 // One element per layer
122 rtc::ArrayView<const int> delays_us) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100123 VideoFrame frame =
124 VideoFrame::Builder()
125 .set_video_frame_buffer(I420Buffer::Create(width, height))
126 .set_rotation(webrtc::kVideoRotation_0)
127 .set_timestamp_us(0)
128 .build();
Niels Möllerf5033ad2018-08-14 17:00:46 +0200129 uint32_t timestamp = 0;
130 while (num_frames-- > 0) {
131 frame.set_timestamp(timestamp);
132 int64_t capture_time_us = rtc::TimeMicros();
133 overuse_detector_->FrameCaptured(frame, capture_time_us);
134 int max_delay_us = 0;
135 for (int delay_us : delays_us) {
136 if (delay_us > max_delay_us) {
137 clock_.AdvanceTimeMicros(delay_us - max_delay_us);
138 max_delay_us = delay_us;
139 }
140
141 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
142 capture_time_us, delay_us);
143 }
144 overuse_detector_->CheckForOveruse(observer_);
145 clock_.AdvanceTimeMicros(interval_us - max_delay_us);
146 timestamp += interval_us * 90 / 1000;
147 }
148 }
149
Niels Möller83dbeac2017-12-14 16:39:44 +0100150 virtual void InsertAndSendFramesWithRandomInterval(int num_frames,
151 int min_interval_us,
152 int max_interval_us,
153 int width,
154 int height,
155 int delay_us) {
Niels Möllere541be72017-12-13 13:03:10 +0100156 webrtc::Random random(17);
157
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100158 VideoFrame frame =
159 VideoFrame::Builder()
160 .set_video_frame_buffer(I420Buffer::Create(width, height))
161 .set_rotation(webrtc::kVideoRotation_0)
162 .set_timestamp_us(0)
163 .build();
Niels Möllere541be72017-12-13 13:03:10 +0100164 uint32_t timestamp = 0;
165 while (num_frames-- > 0) {
166 frame.set_timestamp(timestamp);
167 int interval_us = random.Rand(min_interval_us, max_interval_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100168 int64_t capture_time_us = rtc::TimeMicros();
169 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möllere541be72017-12-13 13:03:10 +0100170 clock_.AdvanceTimeMicros(delay_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100171 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
172 capture_time_us,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200173 absl::optional<int>(delay_us));
Niels Möllere541be72017-12-13 13:03:10 +0100174
Niels Möller73f29cb2018-01-31 16:09:31 +0100175 overuse_detector_->CheckForOveruse(observer_);
Niels Möllere541be72017-12-13 13:03:10 +0100176 // Avoid turning clock backwards.
177 if (interval_us > delay_us)
178 clock_.AdvanceTimeMicros(interval_us - delay_us);
179
180 timestamp += interval_us * 90 / 1000;
181 }
182 }
183
Niels Möller83dbeac2017-12-14 16:39:44 +0100184 virtual void ForceUpdate(int width, int height) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100185 // Insert one frame, wait a second and then put in another to force update
186 // the usage. From the tests where these are used, adding another sample
187 // doesn't affect the expected outcome (this is mainly to check initial
188 // values and whether the overuse detector has been reset or not).
Yves Gerey665174f2018-06-19 15:03:05 +0200189 InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec, width, height,
190 kFrameIntervalUs);
Peter Boströme4499152016-02-05 11:13:28 +0100191 }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000192 void TriggerOveruse(int num_times) {
nissee0e3bdf2017-01-18 02:16:20 -0800193 const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000194 for (int i = 0; i < num_times; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200195 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
196 kDelayUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100197 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000198 }
199 }
200
Åsa Persson746210f2015-09-08 10:52:42 +0200201 void TriggerUnderuse() {
nissee0e3bdf2017-01-18 02:16:20 -0800202 const int kDelayUs1 = 5000;
203 const int kDelayUs2 = 6000;
Yves Gerey665174f2018-06-19 15:03:05 +0200204 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
205 kDelayUs1);
206 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
207 kDelayUs2);
Niels Möller73f29cb2018-01-31 16:09:31 +0100208 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000209 }
210
Niels Möller213618e2018-07-24 09:29:58 +0200211 int UsagePercent() { return encode_usage_percent_; }
asapersson@webrtc.orgab6bf4f2014-05-27 07:43:15 +0000212
sprangfda496a2017-06-15 04:21:07 -0700213 int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
214 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
215 int64_t max_processing_time_us =
216 (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
217 return max_processing_time_us;
218 }
219
220 int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
221 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
222 int64_t max_processing_time_us =
223 (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
224 return max_processing_time_us;
225 }
226
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000227 CpuOveruseOptions options_;
nissee0e3bdf2017-01-18 02:16:20 -0800228 rtc::ScopedFakeClock clock_;
Niels Möller73f29cb2018-01-31 16:09:31 +0100229 MockCpuOveruseObserver mock_observer_;
230 AdaptationObserverInterface* observer_;
perkjd52063f2016-09-07 06:32:18 -0700231 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
Niels Möller213618e2018-07-24 09:29:58 +0200232 int encode_usage_percent_ = -1;
kthelgason876222f2016-11-29 01:44:11 -0800233
sprangb1ca0732017-02-01 08:38:12 -0800234 static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000235};
236
Åsa Persson746210f2015-09-08 10:52:42 +0200237// UsagePercent() > high_encode_usage_threshold_percent => overuse.
238// UsagePercent() < low_encode_usage_threshold_percent => underuse.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000239TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
Åsa Persson746210f2015-09-08 10:52:42 +0200240 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200241 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100242 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000243 TriggerOveruse(options_.high_threshold_consecutive_count);
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000244}
245
246TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
Åsa Persson746210f2015-09-08 10:52:42 +0200247 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200248 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100249 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000250 TriggerOveruse(options_.high_threshold_consecutive_count);
Åsa Persson746210f2015-09-08 10:52:42 +0200251 // usage < low => underuse
Niels Möller73f29cb2018-01-31 16:09:31 +0100252 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000253 TriggerUnderuse();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000254}
255
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000256TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200257 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100258 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000259 TriggerOveruse(options_.high_threshold_consecutive_count);
260 TriggerOveruse(options_.high_threshold_consecutive_count);
Niels Möller73f29cb2018-01-31 16:09:31 +0100261 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000262 TriggerUnderuse();
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000263}
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000264
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000265TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
nissee0e3bdf2017-01-18 02:16:20 -0800266 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000267 options_.min_process_count = 1;
Peter Boström4b91bd02015-06-26 06:58:16 +0200268 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100269 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200270 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200271 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
272 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100273 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200274 EXPECT_EQ(0, overuse_observer.normaluse_);
nissee0e3bdf2017-01-18 02:16:20 -0800275 clock_.AdvanceTimeMicros(kProcessIntervalUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100276 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200277 EXPECT_EQ(1, overuse_observer.normaluse_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000278}
279
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000280TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200281 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100282 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
283 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100284 for (size_t i = 0; i < 64; ++i) {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000285 TriggerOveruse(options_.high_threshold_consecutive_count);
286 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000287}
288
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000289TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200290 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100291 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000292 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200293 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000294 TriggerOveruse(2);
295}
296
297TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200298 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100299 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000300 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200301 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000302 TriggerOveruse(1);
303}
304
Åsa Persson746210f2015-09-08 10:52:42 +0200305TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200306 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200307 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
308 kProcessTimeUs);
nissee0e3bdf2017-01-18 02:16:20 -0800309 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000310}
311
Åsa Persson746210f2015-09-08 10:52:42 +0200312TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200313 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100314 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200315 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200316 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
317 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200318 EXPECT_NE(InitialUsage(), UsagePercent());
Peter Boströme4499152016-02-05 11:13:28 +0100319 // Verify reset (with new width/height).
320 ForceUpdate(kWidth, kHeight + 1);
Åsa Persson746210f2015-09-08 10:52:42 +0200321 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000322}
323
Åsa Persson746210f2015-09-08 10:52:42 +0200324TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200325 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100326 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200327 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200328 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
329 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200330 EXPECT_NE(InitialUsage(), UsagePercent());
331 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200332 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
333 kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200334 EXPECT_NE(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000335 // Verify reset.
Åsa Persson746210f2015-09-08 10:52:42 +0200336 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200337 2,
338 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
339 kWidth, kHeight, kProcessTimeUs);
Peter Boströme4499152016-02-05 11:13:28 +0100340 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200341 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000342}
343
Niels Möller7dc26b72017-12-06 10:27:48 +0100344TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
345 options_.min_frame_samples = 40;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200346 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200347 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
348 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100349 EXPECT_EQ(InitialUsage(), UsagePercent());
350 // Pass time far enough to digest all previous samples.
351 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
352 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
353 kProcessTimeUs);
354 // The last sample has not been processed here.
355 EXPECT_EQ(InitialUsage(), UsagePercent());
356
357 // Pass time far enough to digest all previous samples, 41 in total.
358 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
Yves Gerey665174f2018-06-19 15:03:05 +0200359 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
360 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100361 EXPECT_NE(InitialUsage(), UsagePercent());
362}
363
Åsa Persson746210f2015-09-08 10:52:42 +0200364TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200365 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100366 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200367 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000368}
369
Niels Möller7dc26b72017-12-06 10:27:48 +0100370TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200371 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200372 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100373 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
374 static const size_t kNumFramesEncodingDelay = 3;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100375 VideoFrame frame =
376 VideoFrame::Builder()
377 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
378 .set_rotation(webrtc::kVideoRotation_0)
379 .set_timestamp_us(0)
380 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100381 for (size_t i = 0; i < 1000; ++i) {
382 // Unique timestamps.
383 frame.set_timestamp(static_cast<uint32_t>(i));
Niels Möller83dbeac2017-12-14 16:39:44 +0100384 int64_t capture_time_us = rtc::TimeMicros();
385 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100386 clock_.AdvanceTimeMicros(kIntervalUs);
387 if (i > kNumFramesEncodingDelay) {
388 overuse_detector_->FrameSent(
Niels Möller83dbeac2017-12-14 16:39:44 +0100389 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
390 capture_time_us, kIntervalUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100391 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100392 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100393 }
394}
395
396TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
397 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200398 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200399 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100400 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
401 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100402 VideoFrame frame =
403 VideoFrame::Builder()
404 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
405 .set_rotation(webrtc::kVideoRotation_0)
406 .set_timestamp_us(0)
407 .build();
Niels Möller7dc26b72017-12-06 10:27:48 +0100408 uint32_t timestamp = 0;
409 for (size_t i = 0; i < 1000; ++i) {
410 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100411 int64_t capture_time_us = rtc::TimeMicros();
412 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100413 // Encode and send first parts almost instantly.
414 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100415 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
416 rtc::kNumMicrosecsPerMillisec);
Niels Möller7dc26b72017-12-06 10:27:48 +0100417 // Encode heavier part, resulting in >85% usage total.
418 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100419 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
420 kDelayUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100421 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
422 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100423 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100424 }
425}
426
perkjd52063f2016-09-07 06:32:18 -0700427TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
428 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
429
Niels Möllerc572ff32018-11-07 08:43:50 +0100430 rtc::Event event;
Sebastian Janssoncda86dd2019-03-11 17:26:36 +0100431 queue.PostTask([this, &event, &queue] {
432 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
perkjd52063f2016-09-07 06:32:18 -0700433 event.Set();
434 });
435 event.Wait(rtc::Event::kForever);
436
437 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
438 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100439 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
kthelgason876222f2016-11-29 01:44:11 -0800440 .WillOnce(InvokeWithoutArgs([this, &event] {
perkjd52063f2016-09-07 06:32:18 -0700441 overuse_detector_->StopCheckForOveruse();
442 event.Set();
443 }));
444
eladalon1cc5fc32017-08-23 04:15:18 -0700445 queue.PostTask([this] {
nissee0e3bdf2017-01-18 02:16:20 -0800446 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
447 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
448 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
449 kDelayUs1);
450 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
451 kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700452 });
453
454 EXPECT_TRUE(event.Wait(10000));
455}
456
Niels Möller7dc26b72017-12-06 10:27:48 +0100457TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
458 const int kCapturerMaxFrameRate = 30;
459 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
sprangfda496a2017-06-15 04:21:07 -0700460
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200461 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100462 // Trigger overuse.
463 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
464 // Processing time just below over use limit given kEncodeMaxFrameRate.
465 int64_t processing_time_us =
466 (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100467 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100468 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
469 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
470 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100471 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700472 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100473
474 // Simulate frame rate reduction and normal usage.
475 frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
476 overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
Niels Möller73f29cb2018-01-31 16:09:31 +0100477 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100478 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
479 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
480 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100481 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100482 }
483
484 // Reduce processing time to trigger underuse.
485 processing_time_us =
486 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100487 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100488 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
489 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100490 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700491}
492
Niels Möller7dc26b72017-12-06 10:27:48 +0100493TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
494 const int kMinFrameRate = 7; // Minimum fps allowed by current detector impl.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200495 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100496 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
sprangfda496a2017-06-15 04:21:07 -0700497
Niels Möller7dc26b72017-12-06 10:27:48 +0100498 // Normal usage just at the limit.
499 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
500 // Processing time just below over use limit given kEncodeMaxFrameRate.
501 int64_t processing_time_us =
502 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100503 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100504 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
505 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
506 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100507 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700508 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100509
510 // Over the limit to overuse.
511 processing_time_us =
512 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100513 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100514 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
515 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
516 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100517 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100518 }
519
520 // Reduce input frame rate. Should still trigger overuse.
521 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
Niels Möller73f29cb2018-01-31 16:09:31 +0100522 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100523 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
524 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
525 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100526 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100527 }
528}
529
530TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
531 const int kMaxFrameRate = 20;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200532 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100533 overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
534 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
535 // Maximum frame interval allowed is 35% above ideal.
536 int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
537 // Maximum processing time, without triggering overuse, allowed with the above
538 // frame interval.
539 int64_t max_processing_time_us =
540 (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
541 100;
542
543 // Processing time just below overuse limit given kMaxFrameRate.
544 int64_t processing_time_us = (98 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100545 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100546 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
547 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
548 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100549 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100550 }
551
552 // Go above limit, trigger overuse.
553 processing_time_us = (102 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100554 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100555 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
556 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
557 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100558 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100559 }
560
561 // Increase frame interval, should still trigger overuse.
562 max_frame_interval_us *= 2;
Niels Möller73f29cb2018-01-31 16:09:31 +0100563 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100564 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
565 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
566 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100567 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100568 }
sprangfda496a2017-06-15 04:21:07 -0700569}
570
Niels Möllere541be72017-12-13 13:03:10 +0100571// Models screencast, with irregular arrival of frames which are heavy
572// to encode.
573TEST_F(OveruseFrameDetectorTest, NoOveruseForLargeRandomFrameInterval) {
574 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
575 // behavior is improved in this scenario, with only AdaptUp events,
576 // and estimated load closer to the true average.
577
Niels Möller73f29cb2018-01-31 16:09:31 +0100578 // EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
579 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möllere541be72017-12-13 13:03:10 +0100580 // .Times(testing::AtLeast(1));
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200581 overuse_detector_->SetOptions(options_);
Niels Möllere541be72017-12-13 13:03:10 +0100582
583 const int kNumFrames = 500;
584 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
585
586 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
587 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
588
589 const int kTargetFramerate = 5;
590
591 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
592
Yves Gerey665174f2018-06-19 15:03:05 +0200593 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
594 kMaxIntervalUs, kWidth, kHeight,
595 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100596 // Average usage 19%. Check that estimate is in the right ball park.
597 // EXPECT_NEAR(UsagePercent(), 20, 10);
598 EXPECT_NEAR(UsagePercent(), 20, 35);
599}
600
601// Models screencast, with irregular arrival of frames, often
602// exceeding the timeout interval.
603TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
604 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
605 // behavior is improved in this scenario, and we get AdaptUp events.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200606 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100607 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
608 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möllere541be72017-12-13 13:03:10 +0100609 // .Times(testing::AtLeast(1));
610
611 const int kNumFrames = 500;
612 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
613
614 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
615 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
616
617 const int kTargetFramerate = 5;
618
619 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
620
Yves Gerey665174f2018-06-19 15:03:05 +0200621 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
622 kMaxIntervalUs, kWidth, kHeight,
623 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100624
625 // Average usage 6.6%, but since the frame_timeout_interval_ms is
626 // only 1500 ms, we often reset the estimate to the initial value.
627 // Check that estimate is in the right ball park.
628 EXPECT_GE(UsagePercent(), 1);
629 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
630}
631
Niels Möllerf5033ad2018-08-14 17:00:46 +0200632// Models simulcast, with multiple encoded frames for each input frame.
633// Load estimate should be based on the maximum encode time per input frame.
634TEST_F(OveruseFrameDetectorTest, NoOveruseForSimulcast) {
635 overuse_detector_->SetOptions(options_);
636 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
637
638 constexpr int kNumFrames = 500;
639 constexpr int kEncodeTimesUs[] = {
640 10 * rtc::kNumMicrosecsPerMillisec, 8 * rtc::kNumMicrosecsPerMillisec,
641 12 * rtc::kNumMicrosecsPerMillisec,
642 };
643 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
644
645 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
646 kHeight, kEncodeTimesUs);
647
648 // Average usage 40%. 12 ms / 30 ms.
649 EXPECT_GE(UsagePercent(), 35);
650 EXPECT_LE(UsagePercent(), 45);
651}
652
Niels Möller83dbeac2017-12-14 16:39:44 +0100653// Tests using new cpu load estimator
654class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
655 protected:
656 void SetUp() override {
657 options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
658 OveruseFrameDetectorTest::SetUp();
659 }
660
661 void InsertAndSendFramesWithInterval(int num_frames,
662 int interval_us,
663 int width,
664 int height,
665 int delay_us) override {
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100666 VideoFrame frame =
667 VideoFrame::Builder()
668 .set_video_frame_buffer(I420Buffer::Create(width, height))
669 .set_rotation(webrtc::kVideoRotation_0)
670 .set_timestamp_us(0)
671 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100672 while (num_frames-- > 0) {
673 int64_t capture_time_us = rtc::TimeMicros();
674 overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
675 overuse_detector_->FrameSent(0 /* ignored timestamp */,
676 0 /* ignored send_time_us */,
677 capture_time_us, delay_us);
678 clock_.AdvanceTimeMicros(interval_us);
679 }
680 }
681
682 void InsertAndSendFramesWithRandomInterval(int num_frames,
683 int min_interval_us,
684 int max_interval_us,
685 int width,
686 int height,
687 int delay_us) override {
688 webrtc::Random random(17);
689
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100690 VideoFrame frame =
691 VideoFrame::Builder()
692 .set_video_frame_buffer(I420Buffer::Create(width, height))
693 .set_rotation(webrtc::kVideoRotation_0)
694 .set_timestamp_us(0)
695 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100696 for (int i = 0; i < num_frames; i++) {
697 int interval_us = random.Rand(min_interval_us, max_interval_us);
698 int64_t capture_time_us = rtc::TimeMicros();
699 overuse_detector_->FrameCaptured(frame, capture_time_us);
700 overuse_detector_->FrameSent(0 /* ignored timestamp */,
701 0 /* ignored send_time_us */,
702 capture_time_us, delay_us);
703
Niels Möller73f29cb2018-01-31 16:09:31 +0100704 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100705 clock_.AdvanceTimeMicros(interval_us);
706 }
707 }
708
709 void ForceUpdate(int width, int height) override {
710 // This is mainly to check initial values and whether the overuse
711 // detector has been reset or not.
712 InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
713 kFrameIntervalUs);
714 }
715};
716
717// UsagePercent() > high_encode_usage_threshold_percent => overuse.
718// UsagePercent() < low_encode_usage_threshold_percent => underuse.
719TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
720 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200721 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100722 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100723 TriggerOveruse(options_.high_threshold_consecutive_count);
724}
725
726TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
727 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200728 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100729 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100730 TriggerOveruse(options_.high_threshold_consecutive_count);
731 // usage < low => underuse
Niels Möller73f29cb2018-01-31 16:09:31 +0100732 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100733 TriggerUnderuse();
734}
735
736TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200737 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100738 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
Niels Möller83dbeac2017-12-14 16:39:44 +0100739 TriggerOveruse(options_.high_threshold_consecutive_count);
740 TriggerOveruse(options_.high_threshold_consecutive_count);
Niels Möller73f29cb2018-01-31 16:09:31 +0100741 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100742 TriggerUnderuse();
743}
744
745TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
746 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
747 options_.min_process_count = 1;
748 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100749 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200750 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200751 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
752 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100753 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100754 EXPECT_EQ(0, overuse_observer.normaluse_);
755 clock_.AdvanceTimeMicros(kProcessIntervalUs);
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(1, overuse_observer.normaluse_);
758}
759
760TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200761 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100762 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
763 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
Niels Möller83dbeac2017-12-14 16:39:44 +0100764 for (size_t i = 0; i < 64; ++i) {
765 TriggerOveruse(options_.high_threshold_consecutive_count);
766 }
767}
768
769TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100770 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100771 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200772 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100773 TriggerOveruse(2);
774}
775
776TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100777 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller83dbeac2017-12-14 16:39:44 +0100778 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200779 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100780 TriggerOveruse(1);
781}
782
783TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200784 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200785 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
786 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100787 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
788}
789
790TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200791 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100792 ForceUpdate(kWidth, kHeight);
793 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200794 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
795 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100796 EXPECT_NE(InitialUsage(), UsagePercent());
797 // Verify reset (with new width/height).
798 ForceUpdate(kWidth, kHeight + 1);
799 EXPECT_EQ(InitialUsage(), UsagePercent());
800}
801
802TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200803 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100804 ForceUpdate(kWidth, kHeight);
805 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200806 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
807 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100808 EXPECT_NE(InitialUsage(), UsagePercent());
809 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200810 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
811 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100812 EXPECT_NE(InitialUsage(), UsagePercent());
813 // Verify reset.
814 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200815 2,
816 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
817 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100818 ForceUpdate(kWidth, kHeight);
819 EXPECT_EQ(InitialUsage(), UsagePercent());
820}
821
822TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200823 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100824 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
825 kProcessTimeUs);
826 // No update for the first sample.
827 EXPECT_EQ(InitialUsage(), UsagePercent());
828
829 // Total time approximately 40 * 33ms = 1.3s, significantly less
830 // than the 5s time constant.
Yves Gerey665174f2018-06-19 15:03:05 +0200831 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
832 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100833
834 // Should have started to approach correct load of 15%, but not very far.
835 EXPECT_LT(UsagePercent(), InitialUsage());
836 EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
837
838 // Run for roughly 10s more, should now be closer.
Yves Gerey665174f2018-06-19 15:03:05 +0200839 InsertAndSendFramesWithInterval(300, kFrameIntervalUs, kWidth, kHeight,
840 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100841 EXPECT_NEAR(UsagePercent(), 20, 5);
842}
843
844TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200845 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100846 ForceUpdate(kWidth, kHeight);
847 EXPECT_EQ(InitialUsage(), UsagePercent());
848}
849
850TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200851 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200852 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100853 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
854 static const size_t kNumFramesEncodingDelay = 3;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100855 VideoFrame frame =
856 VideoFrame::Builder()
857 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
858 .set_rotation(webrtc::kVideoRotation_0)
859 .set_timestamp_us(0)
860 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100861 for (size_t i = 0; i < 1000; ++i) {
862 // Unique timestamps.
863 frame.set_timestamp(static_cast<uint32_t>(i));
864 int64_t capture_time_us = rtc::TimeMicros();
865 overuse_detector_->FrameCaptured(frame, capture_time_us);
866 clock_.AdvanceTimeMicros(kIntervalUs);
867 if (i > kNumFramesEncodingDelay) {
868 overuse_detector_->FrameSent(
869 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
870 capture_time_us, kIntervalUs);
871 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100872 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100873 }
874}
875
876TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
877 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200878 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200879 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100880 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
881 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100882 VideoFrame frame =
883 VideoFrame::Builder()
884 .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
885 .set_rotation(webrtc::kVideoRotation_0)
886 .set_timestamp_us(0)
887 .build();
Niels Möller83dbeac2017-12-14 16:39:44 +0100888 uint32_t timestamp = 0;
889 for (size_t i = 0; i < 1000; ++i) {
890 frame.set_timestamp(timestamp);
891 int64_t capture_time_us = rtc::TimeMicros();
892 overuse_detector_->FrameCaptured(frame, capture_time_us);
893 // Encode and send first parts almost instantly.
894 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
895 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
896 rtc::kNumMicrosecsPerMillisec);
897 // Encode heavier part, resulting in >85% usage total.
898 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
899 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
900 kDelayUs);
901 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
902 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100903 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100904 }
905}
906
907TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
908 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
909
Niels Möllerc572ff32018-11-07 08:43:50 +0100910 rtc::Event event;
Sebastian Janssoncda86dd2019-03-11 17:26:36 +0100911 queue.PostTask([this, &event, &queue] {
912 overuse_detector_->StartCheckForOveruse(&queue, options_, observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100913 event.Set();
914 });
915 event.Wait(rtc::Event::kForever);
916
917 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
918 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100919 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100920 .WillOnce(InvokeWithoutArgs([this, &event] {
921 overuse_detector_->StopCheckForOveruse();
922 event.Set();
923 }));
924
925 queue.PostTask([this] {
926 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
927 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
928 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
929 kDelayUs1);
930 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
931 kDelayUs2);
932 });
933
934 EXPECT_TRUE(event.Wait(10000));
935}
936
937// Models screencast, with irregular arrival of frames which are heavy
938// to encode.
939TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200940 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100941 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Yves Gerey665174f2018-06-19 15:03:05 +0200942 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100943
944 const int kNumFrames = 500;
945 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
946
947 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
948 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
949
Yves Gerey665174f2018-06-19 15:03:05 +0200950 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
951 kMaxIntervalUs, kWidth, kHeight,
952 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100953 // Average usage 19%. Check that estimate is in the right ball park.
954 EXPECT_NEAR(UsagePercent(), 20, 10);
955}
956
957// Models screencast, with irregular arrival of frames, often
958// exceeding the timeout interval.
959TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200960 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100961 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Yves Gerey665174f2018-06-19 15:03:05 +0200962 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100963
964 const int kNumFrames = 500;
965 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
966
967 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
968 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
969
Yves Gerey665174f2018-06-19 15:03:05 +0200970 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
971 kMaxIntervalUs, kWidth, kHeight,
972 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100973
974 // Average usage 6.6%, but since the frame_timeout_interval_ms is
975 // only 1500 ms, we often reset the estimate to the initial value.
976 // Check that estimate is in the right ball park.
977 EXPECT_GE(UsagePercent(), 1);
978 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
979}
980
Niels Möller58d2a5e2018-08-07 16:37:18 +0200981TEST_F(OveruseFrameDetectorTest2, ToleratesOutOfOrderFrames) {
982 overuse_detector_->SetOptions(options_);
983 // Represents a cpu utilization close to 100%. First input frame results in
984 // three encoded frames, and the last of those isn't finished until after the
985 // first encoded frame corresponding to the next input frame.
986 const int kEncodeTimeUs = 30 * rtc::kNumMicrosecsPerMillisec;
987 const int kCaptureTimesMs[] = { 33, 33, 66, 33 };
988
989 for (int capture_time_ms : kCaptureTimesMs) {
990 overuse_detector_->FrameSent(
991 0, 0, capture_time_ms * rtc::kNumMicrosecsPerMillisec, kEncodeTimeUs);
992 }
993 EXPECT_GE(UsagePercent(), InitialUsage());
994}
995
Niels Möllerf5033ad2018-08-14 17:00:46 +0200996// Models simulcast, with multiple encoded frames for each input frame.
997// Load estimate should be based on the maximum encode time per input frame.
998TEST_F(OveruseFrameDetectorTest2, NoOveruseForSimulcast) {
999 overuse_detector_->SetOptions(options_);
1000 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
1001
1002 constexpr int kNumFrames = 500;
1003 constexpr int kEncodeTimesUs[] = {
1004 10 * rtc::kNumMicrosecsPerMillisec, 8 * rtc::kNumMicrosecsPerMillisec,
1005 12 * rtc::kNumMicrosecsPerMillisec,
1006 };
1007 constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
1008
1009 InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
1010 kHeight, kEncodeTimesUs);
1011
1012 // Average usage 40%. 12 ms / 30 ms.
1013 EXPECT_GE(UsagePercent(), 35);
1014 EXPECT_LE(UsagePercent(), 45);
1015}
1016
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +00001017} // namespace webrtc