blob: bce5642c18c8bb535079a7d77736dd3df1724c4e [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "api/video/i420_buffer.h"
14#include "common_video/include/video_frame.h"
15#include "modules/video_coding/utility/quality_scaler.h"
16#include "rtc_base/event.h"
17#include "rtc_base/fakeclock.h"
Niels Möllere541be72017-12-13 13:03:10 +010018#include "rtc_base/random.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "test/gmock.h"
20#include "test/gtest.h"
21#include "video/overuse_frame_detector.h"
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000022
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000023namespace webrtc {
perkjd52063f2016-09-07 06:32:18 -070024
kthelgason876222f2016-11-29 01:44:11 -080025using ::testing::InvokeWithoutArgs;
Niels Möllere541be72017-12-13 13:03:10 +010026using ::testing::_;
perkjd52063f2016-09-07 06:32:18 -070027
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000028namespace {
29 const int kWidth = 640;
30 const int kHeight = 480;
Niels Möller83dbeac2017-12-14 16:39:44 +010031 // Corresponds to load of 15%
nissee0e3bdf2017-01-18 02:16:20 -080032 const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
33 const int kProcessTimeUs = 5 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000034} // namespace
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000035
sprangb1ca0732017-02-01 08:38:12 -080036class MockCpuOveruseObserver : public AdaptationObserverInterface {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000037 public:
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +000038 MockCpuOveruseObserver() {}
39 virtual ~MockCpuOveruseObserver() {}
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000040
sprangb1ca0732017-02-01 08:38:12 -080041 MOCK_METHOD1(AdaptUp, void(AdaptReason));
42 MOCK_METHOD1(AdaptDown, void(AdaptReason));
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000043};
44
sprangb1ca0732017-02-01 08:38:12 -080045class CpuOveruseObserverImpl : public AdaptationObserverInterface {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000046 public:
47 CpuOveruseObserverImpl() :
48 overuse_(0),
49 normaluse_(0) {}
50 virtual ~CpuOveruseObserverImpl() {}
51
sprangb1ca0732017-02-01 08:38:12 -080052 void AdaptDown(AdaptReason) { ++overuse_; }
53 void AdaptUp(AdaptReason) { ++normaluse_; }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000054
55 int overuse_;
56 int normaluse_;
57};
58
perkjd52063f2016-09-07 06:32:18 -070059class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
60 public:
Niels Möllerd1f7eb62018-03-28 16:40:58 +020061 explicit OveruseFrameDetectorUnderTest(
62 CpuOveruseMetricsObserver* metrics_observer)
63 : OveruseFrameDetector(metrics_observer) {}
perkjd52063f2016-09-07 06:32:18 -070064 ~OveruseFrameDetectorUnderTest() {}
65
66 using OveruseFrameDetector::CheckForOveruse;
Niels Möllerd1f7eb62018-03-28 16:40:58 +020067 using OveruseFrameDetector::SetOptions;
perkjd52063f2016-09-07 06:32:18 -070068};
69
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000070class OveruseFrameDetectorTest : public ::testing::Test,
71 public CpuOveruseMetricsObserver {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000072 protected:
nisseef8b61e2016-04-29 06:09:15 -070073 void SetUp() override {
Niels Möller73f29cb2018-01-31 16:09:31 +010074 observer_ = &mock_observer_;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000075 options_.min_process_count = 0;
Niels Möllerd1f7eb62018-03-28 16:40:58 +020076 overuse_detector_ = rtc::MakeUnique<OveruseFrameDetectorUnderTest>(this);
77 // Unfortunately, we can't call SetOptions here, since that would break
78 // single-threading requirements in the RunOnTqNormalUsage test.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000079 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +000080
Peter Boströme4499152016-02-05 11:13:28 +010081 void OnEncodedFrameTimeMeasured(int encode_time_ms,
82 const CpuOveruseMetrics& metrics) override {
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000083 metrics_ = metrics;
84 }
85
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000086 int InitialUsage() {
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000087 return ((options_.low_encode_usage_threshold_percent +
88 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5;
89 }
90
Niels Möller83dbeac2017-12-14 16:39:44 +010091 virtual void InsertAndSendFramesWithInterval(int num_frames,
92 int interval_us,
93 int width,
94 int height,
95 int delay_us) {
Niels Möller7dc26b72017-12-06 10:27:48 +010096 VideoFrame frame(I420Buffer::Create(width, height),
97 webrtc::kVideoRotation_0, 0);
98 uint32_t timestamp = 0;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000099 while (num_frames-- > 0) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100100 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100101 int64_t capture_time_us = rtc::TimeMicros();
102 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100103 clock_.AdvanceTimeMicros(delay_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100104 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
105 capture_time_us, delay_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100106 clock_.AdvanceTimeMicros(interval_us - delay_us);
107 timestamp += interval_us * 90 / 1000;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000108 }
109 }
110
Niels Möller83dbeac2017-12-14 16:39:44 +0100111 virtual void InsertAndSendFramesWithRandomInterval(int num_frames,
112 int min_interval_us,
113 int max_interval_us,
114 int width,
115 int height,
116 int delay_us) {
Niels Möllere541be72017-12-13 13:03:10 +0100117 webrtc::Random random(17);
118
119 VideoFrame frame(I420Buffer::Create(width, height),
120 webrtc::kVideoRotation_0, 0);
121 uint32_t timestamp = 0;
122 while (num_frames-- > 0) {
123 frame.set_timestamp(timestamp);
124 int interval_us = random.Rand(min_interval_us, max_interval_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100125 int64_t capture_time_us = rtc::TimeMicros();
126 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möllere541be72017-12-13 13:03:10 +0100127 clock_.AdvanceTimeMicros(delay_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100128 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
129 capture_time_us,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200130 absl::optional<int>(delay_us));
Niels Möllere541be72017-12-13 13:03:10 +0100131
Niels Möller73f29cb2018-01-31 16:09:31 +0100132 overuse_detector_->CheckForOveruse(observer_);
Niels Möllere541be72017-12-13 13:03:10 +0100133 // Avoid turning clock backwards.
134 if (interval_us > delay_us)
135 clock_.AdvanceTimeMicros(interval_us - delay_us);
136
137 timestamp += interval_us * 90 / 1000;
138 }
139 }
140
Niels Möller83dbeac2017-12-14 16:39:44 +0100141 virtual void ForceUpdate(int width, int height) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100142 // Insert one frame, wait a second and then put in another to force update
143 // the usage. From the tests where these are used, adding another sample
144 // doesn't affect the expected outcome (this is mainly to check initial
145 // values and whether the overuse detector has been reset or not).
146 InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec,
147 width, height, kFrameIntervalUs);
Peter Boströme4499152016-02-05 11:13:28 +0100148 }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000149 void TriggerOveruse(int num_times) {
nissee0e3bdf2017-01-18 02:16:20 -0800150 const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000151 for (int i = 0; i < num_times; ++i) {
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000152 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800153 1000, kFrameIntervalUs, kWidth, kHeight, kDelayUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100154 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000155 }
156 }
157
Åsa Persson746210f2015-09-08 10:52:42 +0200158 void TriggerUnderuse() {
nissee0e3bdf2017-01-18 02:16:20 -0800159 const int kDelayUs1 = 5000;
160 const int kDelayUs2 = 6000;
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000161 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800162 1300, kFrameIntervalUs, kWidth, kHeight, kDelayUs1);
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000163 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800164 1, kFrameIntervalUs, kWidth, kHeight, kDelayUs2);
Niels Möller73f29cb2018-01-31 16:09:31 +0100165 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000166 }
167
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000168 int UsagePercent() { return metrics_.encode_usage_percent; }
asapersson@webrtc.orgab6bf4f2014-05-27 07:43:15 +0000169
sprangfda496a2017-06-15 04:21:07 -0700170 int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
171 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
172 int64_t max_processing_time_us =
173 (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
174 return max_processing_time_us;
175 }
176
177 int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
178 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
179 int64_t max_processing_time_us =
180 (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
181 return max_processing_time_us;
182 }
183
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000184 CpuOveruseOptions options_;
nissee0e3bdf2017-01-18 02:16:20 -0800185 rtc::ScopedFakeClock clock_;
Niels Möller73f29cb2018-01-31 16:09:31 +0100186 MockCpuOveruseObserver mock_observer_;
187 AdaptationObserverInterface* observer_;
perkjd52063f2016-09-07 06:32:18 -0700188 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000189 CpuOveruseMetrics metrics_;
kthelgason876222f2016-11-29 01:44:11 -0800190
sprangb1ca0732017-02-01 08:38:12 -0800191 static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000192};
193
Åsa Persson746210f2015-09-08 10:52:42 +0200194
Åsa Persson746210f2015-09-08 10:52:42 +0200195// UsagePercent() > high_encode_usage_threshold_percent => overuse.
196// UsagePercent() < low_encode_usage_threshold_percent => underuse.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000197TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
Åsa Persson746210f2015-09-08 10:52:42 +0200198 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200199 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100200 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000201 TriggerOveruse(options_.high_threshold_consecutive_count);
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000202}
203
204TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
Åsa Persson746210f2015-09-08 10:52:42 +0200205 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200206 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100207 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000208 TriggerOveruse(options_.high_threshold_consecutive_count);
Åsa Persson746210f2015-09-08 10:52:42 +0200209 // usage < low => underuse
Niels Möller73f29cb2018-01-31 16:09:31 +0100210 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000211 TriggerUnderuse();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000212}
213
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000214TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200215 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100216 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000217 TriggerOveruse(options_.high_threshold_consecutive_count);
218 TriggerOveruse(options_.high_threshold_consecutive_count);
Niels Möller73f29cb2018-01-31 16:09:31 +0100219 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000220 TriggerUnderuse();
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000221}
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000222
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000223TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
nissee0e3bdf2017-01-18 02:16:20 -0800224 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000225 options_.min_process_count = 1;
Peter Boström4b91bd02015-06-26 06:58:16 +0200226 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100227 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200228 overuse_detector_->SetOptions(options_);
Åsa Persson746210f2015-09-08 10:52:42 +0200229 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800230 1200, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100231 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200232 EXPECT_EQ(0, overuse_observer.normaluse_);
nissee0e3bdf2017-01-18 02:16:20 -0800233 clock_.AdvanceTimeMicros(kProcessIntervalUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100234 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200235 EXPECT_EQ(1, overuse_observer.normaluse_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000236}
237
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000238TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200239 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100240 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
241 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100242 for (size_t i = 0; i < 64; ++i) {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000243 TriggerOveruse(options_.high_threshold_consecutive_count);
244 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000245}
246
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000247TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
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 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200251 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000252 TriggerOveruse(2);
253}
254
255TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200256 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100257 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000258 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200259 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000260 TriggerOveruse(1);
261}
262
Åsa Persson746210f2015-09-08 10:52:42 +0200263TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200264 overuse_detector_->SetOptions(options_);
Åsa Persson746210f2015-09-08 10:52:42 +0200265 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800266 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
267 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000268}
269
Åsa Persson746210f2015-09-08 10:52:42 +0200270TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200271 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100272 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200273 EXPECT_EQ(InitialUsage(), UsagePercent());
274 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800275 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200276 EXPECT_NE(InitialUsage(), UsagePercent());
Peter Boströme4499152016-02-05 11:13:28 +0100277 // Verify reset (with new width/height).
278 ForceUpdate(kWidth, kHeight + 1);
Åsa Persson746210f2015-09-08 10:52:42 +0200279 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000280}
281
Åsa Persson746210f2015-09-08 10:52:42 +0200282TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200283 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100284 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200285 EXPECT_EQ(InitialUsage(), UsagePercent());
286 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800287 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200288 EXPECT_NE(InitialUsage(), UsagePercent());
289 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800290 2, options_.frame_timeout_interval_ms *
291 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200292 EXPECT_NE(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000293 // Verify reset.
Åsa Persson746210f2015-09-08 10:52:42 +0200294 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800295 2, (options_.frame_timeout_interval_ms + 1) *
296 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
Peter Boströme4499152016-02-05 11:13:28 +0100297 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200298 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000299}
300
Niels Möller7dc26b72017-12-06 10:27:48 +0100301TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
302 options_.min_frame_samples = 40;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200303 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100304 InsertAndSendFramesWithInterval(
305 40, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
306 EXPECT_EQ(InitialUsage(), UsagePercent());
307 // Pass time far enough to digest all previous samples.
308 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
309 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
310 kProcessTimeUs);
311 // The last sample has not been processed here.
312 EXPECT_EQ(InitialUsage(), UsagePercent());
313
314 // Pass time far enough to digest all previous samples, 41 in total.
315 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
316 InsertAndSendFramesWithInterval(
317 1, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
318 EXPECT_NE(InitialUsage(), UsagePercent());
319}
320
Åsa Persson746210f2015-09-08 10:52:42 +0200321TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200322 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100323 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200324 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000325}
326
Niels Möller7dc26b72017-12-06 10:27:48 +0100327TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200328 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100329 EXPECT_CALL(mock_observer_, AdaptDown(reason_))
Niels Möller7dc26b72017-12-06 10:27:48 +0100330 .Times(testing::AtLeast(1));
331 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
332 static const size_t kNumFramesEncodingDelay = 3;
333 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
334 webrtc::kVideoRotation_0, 0);
335 for (size_t i = 0; i < 1000; ++i) {
336 // Unique timestamps.
337 frame.set_timestamp(static_cast<uint32_t>(i));
Niels Möller83dbeac2017-12-14 16:39:44 +0100338 int64_t capture_time_us = rtc::TimeMicros();
339 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100340 clock_.AdvanceTimeMicros(kIntervalUs);
341 if (i > kNumFramesEncodingDelay) {
342 overuse_detector_->FrameSent(
Niels Möller83dbeac2017-12-14 16:39:44 +0100343 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
344 capture_time_us, kIntervalUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100345 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100346 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100347 }
348}
349
350TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
351 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200352 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100353 EXPECT_CALL(mock_observer_, AdaptDown(reason_))
Niels Möller7dc26b72017-12-06 10:27:48 +0100354 .Times(testing::AtLeast(1));
355 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
356 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
357 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
358 webrtc::kVideoRotation_0, 0);
359 uint32_t timestamp = 0;
360 for (size_t i = 0; i < 1000; ++i) {
361 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100362 int64_t capture_time_us = rtc::TimeMicros();
363 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100364 // Encode and send first parts almost instantly.
365 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100366 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
367 rtc::kNumMicrosecsPerMillisec);
Niels Möller7dc26b72017-12-06 10:27:48 +0100368 // Encode heavier part, resulting in >85% usage total.
369 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100370 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
371 kDelayUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100372 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
373 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100374 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100375 }
376}
377
perkjd52063f2016-09-07 06:32:18 -0700378TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
379 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
380
381 rtc::Event event(false, false);
382 queue.PostTask([this, &event] {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200383 overuse_detector_->StartCheckForOveruse(options_, observer_);
perkjd52063f2016-09-07 06:32:18 -0700384 event.Set();
385 });
386 event.Wait(rtc::Event::kForever);
387
388 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
389 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100390 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
kthelgason876222f2016-11-29 01:44:11 -0800391 .WillOnce(InvokeWithoutArgs([this, &event] {
perkjd52063f2016-09-07 06:32:18 -0700392 overuse_detector_->StopCheckForOveruse();
393 event.Set();
394 }));
395
eladalon1cc5fc32017-08-23 04:15:18 -0700396 queue.PostTask([this] {
nissee0e3bdf2017-01-18 02:16:20 -0800397 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
398 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
399 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
400 kDelayUs1);
401 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
402 kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700403 });
404
405 EXPECT_TRUE(event.Wait(10000));
406}
407
Niels Möller7dc26b72017-12-06 10:27:48 +0100408TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
409 const int kCapturerMaxFrameRate = 30;
410 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
sprangfda496a2017-06-15 04:21:07 -0700411
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200412 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100413 // Trigger overuse.
414 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
415 // Processing time just below over use limit given kEncodeMaxFrameRate.
416 int64_t processing_time_us =
417 (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100418 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100419 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
420 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
421 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100422 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700423 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100424
425 // Simulate frame rate reduction and normal usage.
426 frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
427 overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
Niels Möller73f29cb2018-01-31 16:09:31 +0100428 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100429 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
430 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
431 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100432 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100433 }
434
435 // Reduce processing time to trigger underuse.
436 processing_time_us =
437 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100438 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100439 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
440 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100441 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700442}
443
Niels Möller7dc26b72017-12-06 10:27:48 +0100444TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
445 const int kMinFrameRate = 7; // Minimum fps allowed by current detector impl.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200446 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100447 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
sprangfda496a2017-06-15 04:21:07 -0700448
Niels Möller7dc26b72017-12-06 10:27:48 +0100449 // Normal usage just at the limit.
450 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
451 // Processing time just below over use limit given kEncodeMaxFrameRate.
452 int64_t processing_time_us =
453 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100454 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100455 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
456 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
457 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100458 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700459 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100460
461 // Over the limit to overuse.
462 processing_time_us =
463 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100464 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100465 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
466 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
467 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100468 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100469 }
470
471 // Reduce input frame rate. Should still trigger overuse.
472 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
Niels Möller73f29cb2018-01-31 16:09:31 +0100473 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100474 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
475 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
476 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100477 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100478 }
479}
480
481TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
482 const int kMaxFrameRate = 20;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200483 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100484 overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
485 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
486 // Maximum frame interval allowed is 35% above ideal.
487 int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
488 // Maximum processing time, without triggering overuse, allowed with the above
489 // frame interval.
490 int64_t max_processing_time_us =
491 (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
492 100;
493
494 // Processing time just below overuse limit given kMaxFrameRate.
495 int64_t processing_time_us = (98 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100496 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100497 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
498 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
499 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100500 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100501 }
502
503 // Go above limit, trigger overuse.
504 processing_time_us = (102 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100505 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100506 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
507 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
508 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100509 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100510 }
511
512 // Increase frame interval, should still trigger overuse.
513 max_frame_interval_us *= 2;
Niels Möller73f29cb2018-01-31 16:09:31 +0100514 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100515 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
516 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
517 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100518 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100519 }
sprangfda496a2017-06-15 04:21:07 -0700520}
521
Niels Möllere541be72017-12-13 13:03:10 +0100522// Models screencast, with irregular arrival of frames which are heavy
523// to encode.
524TEST_F(OveruseFrameDetectorTest, NoOveruseForLargeRandomFrameInterval) {
525 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
526 // behavior is improved in this scenario, with only AdaptUp events,
527 // and estimated load closer to the true average.
528
Niels Möller73f29cb2018-01-31 16:09:31 +0100529 // EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
530 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möllere541be72017-12-13 13:03:10 +0100531 // .Times(testing::AtLeast(1));
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200532 overuse_detector_->SetOptions(options_);
Niels Möllere541be72017-12-13 13:03:10 +0100533
534 const int kNumFrames = 500;
535 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
536
537 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
538 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
539
540 const int kTargetFramerate = 5;
541
542 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
543
544 InsertAndSendFramesWithRandomInterval(kNumFrames,
545 kMinIntervalUs, kMaxIntervalUs,
546 kWidth, kHeight, kEncodeTimeUs);
547 // Average usage 19%. Check that estimate is in the right ball park.
548 // EXPECT_NEAR(UsagePercent(), 20, 10);
549 EXPECT_NEAR(UsagePercent(), 20, 35);
550}
551
552// Models screencast, with irregular arrival of frames, often
553// exceeding the timeout interval.
554TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
555 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
556 // behavior is improved in this scenario, and we get AdaptUp events.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200557 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100558 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
559 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möllere541be72017-12-13 13:03:10 +0100560 // .Times(testing::AtLeast(1));
561
562 const int kNumFrames = 500;
563 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
564
565 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
566 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
567
568 const int kTargetFramerate = 5;
569
570 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
571
572 InsertAndSendFramesWithRandomInterval(kNumFrames,
573 kMinIntervalUs, kMaxIntervalUs,
574 kWidth, kHeight, kEncodeTimeUs);
575
576 // Average usage 6.6%, but since the frame_timeout_interval_ms is
577 // only 1500 ms, we often reset the estimate to the initial value.
578 // Check that estimate is in the right ball park.
579 EXPECT_GE(UsagePercent(), 1);
580 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
581}
582
Niels Möller83dbeac2017-12-14 16:39:44 +0100583// Tests using new cpu load estimator
584class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
585 protected:
586 void SetUp() override {
587 options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
588 OveruseFrameDetectorTest::SetUp();
589 }
590
591 void InsertAndSendFramesWithInterval(int num_frames,
592 int interval_us,
593 int width,
594 int height,
595 int delay_us) override {
596 VideoFrame frame(I420Buffer::Create(width, height),
597 webrtc::kVideoRotation_0, 0);
598 while (num_frames-- > 0) {
599 int64_t capture_time_us = rtc::TimeMicros();
600 overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
601 overuse_detector_->FrameSent(0 /* ignored timestamp */,
602 0 /* ignored send_time_us */,
603 capture_time_us, delay_us);
604 clock_.AdvanceTimeMicros(interval_us);
605 }
606 }
607
608 void InsertAndSendFramesWithRandomInterval(int num_frames,
609 int min_interval_us,
610 int max_interval_us,
611 int width,
612 int height,
613 int delay_us) override {
614 webrtc::Random random(17);
615
616 VideoFrame frame(I420Buffer::Create(width, height),
617 webrtc::kVideoRotation_0, 0);
618 for (int i = 0; i < num_frames; i++) {
619 int interval_us = random.Rand(min_interval_us, max_interval_us);
620 int64_t capture_time_us = rtc::TimeMicros();
621 overuse_detector_->FrameCaptured(frame, capture_time_us);
622 overuse_detector_->FrameSent(0 /* ignored timestamp */,
623 0 /* ignored send_time_us */,
624 capture_time_us, delay_us);
625
Niels Möller73f29cb2018-01-31 16:09:31 +0100626 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100627 clock_.AdvanceTimeMicros(interval_us);
628 }
629 }
630
631 void ForceUpdate(int width, int height) override {
632 // This is mainly to check initial values and whether the overuse
633 // detector has been reset or not.
634 InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
635 kFrameIntervalUs);
636 }
637};
638
639// UsagePercent() > high_encode_usage_threshold_percent => overuse.
640// UsagePercent() < low_encode_usage_threshold_percent => underuse.
641TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
642 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200643 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100644 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100645 TriggerOveruse(options_.high_threshold_consecutive_count);
646}
647
648TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
649 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200650 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100651 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100652 TriggerOveruse(options_.high_threshold_consecutive_count);
653 // usage < low => underuse
Niels Möller73f29cb2018-01-31 16:09:31 +0100654 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100655 TriggerUnderuse();
656}
657
658TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200659 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100660 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
Niels Möller83dbeac2017-12-14 16:39:44 +0100661 TriggerOveruse(options_.high_threshold_consecutive_count);
662 TriggerOveruse(options_.high_threshold_consecutive_count);
Niels Möller73f29cb2018-01-31 16:09:31 +0100663 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100664 TriggerUnderuse();
665}
666
667TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
668 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
669 options_.min_process_count = 1;
670 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100671 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200672 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100673 InsertAndSendFramesWithInterval(
674 1200, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100675 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100676 EXPECT_EQ(0, overuse_observer.normaluse_);
677 clock_.AdvanceTimeMicros(kProcessIntervalUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100678 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100679 EXPECT_EQ(1, overuse_observer.normaluse_);
680}
681
682TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200683 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100684 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
685 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
Niels Möller83dbeac2017-12-14 16:39:44 +0100686 for (size_t i = 0; i < 64; ++i) {
687 TriggerOveruse(options_.high_threshold_consecutive_count);
688 }
689}
690
691TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100692 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100693 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200694 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100695 TriggerOveruse(2);
696}
697
698TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100699 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller83dbeac2017-12-14 16:39:44 +0100700 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200701 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100702 TriggerOveruse(1);
703}
704
705TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200706 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100707 InsertAndSendFramesWithInterval(
708 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
709 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
710}
711
712TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200713 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100714 ForceUpdate(kWidth, kHeight);
715 EXPECT_EQ(InitialUsage(), UsagePercent());
716 InsertAndSendFramesWithInterval(
717 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
718 EXPECT_NE(InitialUsage(), UsagePercent());
719 // Verify reset (with new width/height).
720 ForceUpdate(kWidth, kHeight + 1);
721 EXPECT_EQ(InitialUsage(), UsagePercent());
722}
723
724TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200725 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100726 ForceUpdate(kWidth, kHeight);
727 EXPECT_EQ(InitialUsage(), UsagePercent());
728 InsertAndSendFramesWithInterval(
729 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
730 EXPECT_NE(InitialUsage(), UsagePercent());
731 InsertAndSendFramesWithInterval(
732 2, options_.frame_timeout_interval_ms *
733 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
734 EXPECT_NE(InitialUsage(), UsagePercent());
735 // Verify reset.
736 InsertAndSendFramesWithInterval(
737 2, (options_.frame_timeout_interval_ms + 1) *
738 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
739 ForceUpdate(kWidth, kHeight);
740 EXPECT_EQ(InitialUsage(), UsagePercent());
741}
742
743TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200744 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100745 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
746 kProcessTimeUs);
747 // No update for the first sample.
748 EXPECT_EQ(InitialUsage(), UsagePercent());
749
750 // Total time approximately 40 * 33ms = 1.3s, significantly less
751 // than the 5s time constant.
752 InsertAndSendFramesWithInterval(
753 40, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
754
755 // Should have started to approach correct load of 15%, but not very far.
756 EXPECT_LT(UsagePercent(), InitialUsage());
757 EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
758
759 // Run for roughly 10s more, should now be closer.
760 InsertAndSendFramesWithInterval(
761 300, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
762 EXPECT_NEAR(UsagePercent(), 20, 5);
763}
764
765TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200766 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100767 ForceUpdate(kWidth, kHeight);
768 EXPECT_EQ(InitialUsage(), UsagePercent());
769}
770
771TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200772 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100773 EXPECT_CALL(mock_observer_, AdaptDown(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100774 .Times(testing::AtLeast(1));
775 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
776 static const size_t kNumFramesEncodingDelay = 3;
777 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
778 webrtc::kVideoRotation_0, 0);
779 for (size_t i = 0; i < 1000; ++i) {
780 // Unique timestamps.
781 frame.set_timestamp(static_cast<uint32_t>(i));
782 int64_t capture_time_us = rtc::TimeMicros();
783 overuse_detector_->FrameCaptured(frame, capture_time_us);
784 clock_.AdvanceTimeMicros(kIntervalUs);
785 if (i > kNumFramesEncodingDelay) {
786 overuse_detector_->FrameSent(
787 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
788 capture_time_us, kIntervalUs);
789 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100790 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100791 }
792}
793
794TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
795 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200796 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100797 EXPECT_CALL(mock_observer_, AdaptDown(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100798 .Times(testing::AtLeast(1));
799 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
800 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
801 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
802 webrtc::kVideoRotation_0, 0);
803 uint32_t timestamp = 0;
804 for (size_t i = 0; i < 1000; ++i) {
805 frame.set_timestamp(timestamp);
806 int64_t capture_time_us = rtc::TimeMicros();
807 overuse_detector_->FrameCaptured(frame, capture_time_us);
808 // Encode and send first parts almost instantly.
809 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
810 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
811 rtc::kNumMicrosecsPerMillisec);
812 // Encode heavier part, resulting in >85% usage total.
813 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
814 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
815 kDelayUs);
816 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
817 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100818 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100819 }
820}
821
822TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
823 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
824
825 rtc::Event event(false, false);
826 queue.PostTask([this, &event] {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200827 overuse_detector_->StartCheckForOveruse(options_, observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100828 event.Set();
829 });
830 event.Wait(rtc::Event::kForever);
831
832 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
833 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100834 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100835 .WillOnce(InvokeWithoutArgs([this, &event] {
836 overuse_detector_->StopCheckForOveruse();
837 event.Set();
838 }));
839
840 queue.PostTask([this] {
841 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
842 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
843 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
844 kDelayUs1);
845 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
846 kDelayUs2);
847 });
848
849 EXPECT_TRUE(event.Wait(10000));
850}
851
852// Models screencast, with irregular arrival of frames which are heavy
853// to encode.
854TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200855 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100856 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
857 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100858 .Times(testing::AtLeast(1));
859
860 const int kNumFrames = 500;
861 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
862
863 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
864 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
865
866 InsertAndSendFramesWithRandomInterval(kNumFrames,
867 kMinIntervalUs, kMaxIntervalUs,
868 kWidth, kHeight, kEncodeTimeUs);
869 // Average usage 19%. Check that estimate is in the right ball park.
870 EXPECT_NEAR(UsagePercent(), 20, 10);
871}
872
873// Models screencast, with irregular arrival of frames, often
874// exceeding the timeout interval.
875TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200876 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100877 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
878 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100879 .Times(testing::AtLeast(1));
880
881 const int kNumFrames = 500;
882 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
883
884 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
885 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
886
887 InsertAndSendFramesWithRandomInterval(kNumFrames,
888 kMinIntervalUs, kMaxIntervalUs,
889 kWidth, kHeight, kEncodeTimeUs);
890
891 // Average usage 6.6%, but since the frame_timeout_interval_ms is
892 // only 1500 ms, we often reset the estimate to the initial value.
893 // Check that estimate is in the right ball park.
894 EXPECT_GE(UsagePercent(), 1);
895 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
896}
897
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000898} // namespace webrtc