blob: e65dc26495378872285bf817e0a0b517f198e4e1 [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 {
Yves Gerey665174f2018-06-19 15:03:05 +020029const int kWidth = 640;
30const int kHeight = 480;
31// Corresponds to load of 15%
32const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
33const 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:
Yves Gerey665174f2018-06-19 15:03:05 +020047 CpuOveruseObserverImpl() : overuse_(0), normaluse_(0) {}
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000048 virtual ~CpuOveruseObserverImpl() {}
49
sprangb1ca0732017-02-01 08:38:12 -080050 void AdaptDown(AdaptReason) { ++overuse_; }
51 void AdaptUp(AdaptReason) { ++normaluse_; }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000052
53 int overuse_;
54 int normaluse_;
55};
56
perkjd52063f2016-09-07 06:32:18 -070057class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
58 public:
Niels Möllerd1f7eb62018-03-28 16:40:58 +020059 explicit OveruseFrameDetectorUnderTest(
60 CpuOveruseMetricsObserver* metrics_observer)
61 : OveruseFrameDetector(metrics_observer) {}
perkjd52063f2016-09-07 06:32:18 -070062 ~OveruseFrameDetectorUnderTest() {}
63
64 using OveruseFrameDetector::CheckForOveruse;
Niels Möllerd1f7eb62018-03-28 16:40:58 +020065 using OveruseFrameDetector::SetOptions;
perkjd52063f2016-09-07 06:32:18 -070066};
67
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000068class OveruseFrameDetectorTest : public ::testing::Test,
69 public CpuOveruseMetricsObserver {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000070 protected:
nisseef8b61e2016-04-29 06:09:15 -070071 void SetUp() override {
Niels Möller73f29cb2018-01-31 16:09:31 +010072 observer_ = &mock_observer_;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000073 options_.min_process_count = 0;
Karl Wiberg918f50c2018-07-05 11:40:33 +020074 overuse_detector_ = absl::make_unique<OveruseFrameDetectorUnderTest>(this);
Niels Möllerd1f7eb62018-03-28 16:40:58 +020075 // Unfortunately, we can't call SetOptions here, since that would break
76 // single-threading requirements in the RunOnTqNormalUsage test.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000077 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +000078
Peter Boströme4499152016-02-05 11:13:28 +010079 void OnEncodedFrameTimeMeasured(int encode_time_ms,
Niels Möller213618e2018-07-24 09:29:58 +020080 int encode_usage_percent) override {
81 encode_usage_percent_ = encode_usage_percent;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000082 }
83
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000084 int InitialUsage() {
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000085 return ((options_.low_encode_usage_threshold_percent +
Yves Gerey665174f2018-06-19 15:03:05 +020086 options_.high_encode_usage_threshold_percent) /
87 2.0f) +
88 0.5;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000089 }
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).
Yves Gerey665174f2018-06-19 15:03:05 +0200146 InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec, width, height,
147 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) {
Yves Gerey665174f2018-06-19 15:03:05 +0200152 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
153 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;
Yves Gerey665174f2018-06-19 15:03:05 +0200161 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
162 kDelayUs1);
163 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
164 kDelayUs2);
Niels Möller73f29cb2018-01-31 16:09:31 +0100165 overuse_detector_->CheckForOveruse(observer_);
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000166 }
167
Niels Möller213618e2018-07-24 09:29:58 +0200168 int UsagePercent() { return 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_;
Niels Möller213618e2018-07-24 09:29:58 +0200189 int encode_usage_percent_ = -1;
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// UsagePercent() > high_encode_usage_threshold_percent => overuse.
195// UsagePercent() < low_encode_usage_threshold_percent => underuse.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000196TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
Åsa Persson746210f2015-09-08 10:52:42 +0200197 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200198 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100199 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000200 TriggerOveruse(options_.high_threshold_consecutive_count);
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000201}
202
203TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
Åsa Persson746210f2015-09-08 10:52:42 +0200204 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200205 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100206 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000207 TriggerOveruse(options_.high_threshold_consecutive_count);
Åsa Persson746210f2015-09-08 10:52:42 +0200208 // usage < low => underuse
Niels Möller73f29cb2018-01-31 16:09:31 +0100209 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000210 TriggerUnderuse();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000211}
212
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000213TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200214 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100215 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000216 TriggerOveruse(options_.high_threshold_consecutive_count);
217 TriggerOveruse(options_.high_threshold_consecutive_count);
Niels Möller73f29cb2018-01-31 16:09:31 +0100218 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000219 TriggerUnderuse();
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000220}
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000221
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000222TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
nissee0e3bdf2017-01-18 02:16:20 -0800223 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000224 options_.min_process_count = 1;
Peter Boström4b91bd02015-06-26 06:58:16 +0200225 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100226 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200227 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200228 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
229 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100230 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200231 EXPECT_EQ(0, overuse_observer.normaluse_);
nissee0e3bdf2017-01-18 02:16:20 -0800232 clock_.AdvanceTimeMicros(kProcessIntervalUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100233 overuse_detector_->CheckForOveruse(&overuse_observer);
Peter Boström4b91bd02015-06-26 06:58:16 +0200234 EXPECT_EQ(1, overuse_observer.normaluse_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000235}
236
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000237TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200238 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100239 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
240 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100241 for (size_t i = 0; i < 64; ++i) {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000242 TriggerOveruse(options_.high_threshold_consecutive_count);
243 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000244}
245
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000246TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200247 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100248 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000249 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200250 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000251 TriggerOveruse(2);
252}
253
254TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200255 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100256 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000257 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200258 overuse_detector_->SetOptions(options_);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000259 TriggerOveruse(1);
260}
261
Åsa Persson746210f2015-09-08 10:52:42 +0200262TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200263 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200264 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
265 kProcessTimeUs);
nissee0e3bdf2017-01-18 02:16:20 -0800266 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000267}
268
Åsa Persson746210f2015-09-08 10:52:42 +0200269TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200270 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100271 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200272 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200273 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
274 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200275 EXPECT_NE(InitialUsage(), UsagePercent());
Peter Boströme4499152016-02-05 11:13:28 +0100276 // Verify reset (with new width/height).
277 ForceUpdate(kWidth, kHeight + 1);
Åsa Persson746210f2015-09-08 10:52:42 +0200278 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000279}
280
Åsa Persson746210f2015-09-08 10:52:42 +0200281TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200282 overuse_detector_->SetOptions(options_);
Peter Boströme4499152016-02-05 11:13:28 +0100283 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200284 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200285 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
286 kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200287 EXPECT_NE(InitialUsage(), UsagePercent());
288 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200289 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
290 kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200291 EXPECT_NE(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000292 // Verify reset.
Åsa Persson746210f2015-09-08 10:52:42 +0200293 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200294 2,
295 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
296 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_);
Yves Gerey665174f2018-06-19 15:03:05 +0200304 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
305 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100306 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);
Yves Gerey665174f2018-06-19 15:03:05 +0200316 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
317 kProcessTimeUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100318 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_);
Yves Gerey665174f2018-06-19 15:03:05 +0200329 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100330 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
331 static const size_t kNumFramesEncodingDelay = 3;
332 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
333 webrtc::kVideoRotation_0, 0);
334 for (size_t i = 0; i < 1000; ++i) {
335 // Unique timestamps.
336 frame.set_timestamp(static_cast<uint32_t>(i));
Niels Möller83dbeac2017-12-14 16:39:44 +0100337 int64_t capture_time_us = rtc::TimeMicros();
338 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100339 clock_.AdvanceTimeMicros(kIntervalUs);
340 if (i > kNumFramesEncodingDelay) {
341 overuse_detector_->FrameSent(
Niels Möller83dbeac2017-12-14 16:39:44 +0100342 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
343 capture_time_us, kIntervalUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100344 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100345 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100346 }
347}
348
349TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
350 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200351 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200352 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller7dc26b72017-12-06 10:27:48 +0100353 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
354 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
355 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
356 webrtc::kVideoRotation_0, 0);
357 uint32_t timestamp = 0;
358 for (size_t i = 0; i < 1000; ++i) {
359 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100360 int64_t capture_time_us = rtc::TimeMicros();
361 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100362 // Encode and send first parts almost instantly.
363 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100364 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
365 rtc::kNumMicrosecsPerMillisec);
Niels Möller7dc26b72017-12-06 10:27:48 +0100366 // Encode heavier part, resulting in >85% usage total.
367 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100368 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
369 kDelayUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100370 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
371 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100372 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100373 }
374}
375
perkjd52063f2016-09-07 06:32:18 -0700376TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
377 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
378
379 rtc::Event event(false, false);
380 queue.PostTask([this, &event] {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200381 overuse_detector_->StartCheckForOveruse(options_, observer_);
perkjd52063f2016-09-07 06:32:18 -0700382 event.Set();
383 });
384 event.Wait(rtc::Event::kForever);
385
386 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
387 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100388 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
kthelgason876222f2016-11-29 01:44:11 -0800389 .WillOnce(InvokeWithoutArgs([this, &event] {
perkjd52063f2016-09-07 06:32:18 -0700390 overuse_detector_->StopCheckForOveruse();
391 event.Set();
392 }));
393
eladalon1cc5fc32017-08-23 04:15:18 -0700394 queue.PostTask([this] {
nissee0e3bdf2017-01-18 02:16:20 -0800395 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
396 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
397 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
398 kDelayUs1);
399 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
400 kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700401 });
402
403 EXPECT_TRUE(event.Wait(10000));
404}
405
Niels Möller7dc26b72017-12-06 10:27:48 +0100406TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
407 const int kCapturerMaxFrameRate = 30;
408 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
sprangfda496a2017-06-15 04:21:07 -0700409
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200410 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100411 // Trigger overuse.
412 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
413 // Processing time just below over use limit given kEncodeMaxFrameRate.
414 int64_t processing_time_us =
415 (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100416 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100417 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
418 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
419 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100420 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700421 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100422
423 // Simulate frame rate reduction and normal usage.
424 frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
425 overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
Niels Möller73f29cb2018-01-31 16:09:31 +0100426 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100427 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
428 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
429 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100430 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100431 }
432
433 // Reduce processing time to trigger underuse.
434 processing_time_us =
435 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100436 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100437 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
438 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100439 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700440}
441
Niels Möller7dc26b72017-12-06 10:27:48 +0100442TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
443 const int kMinFrameRate = 7; // Minimum fps allowed by current detector impl.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200444 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100445 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
sprangfda496a2017-06-15 04:21:07 -0700446
Niels Möller7dc26b72017-12-06 10:27:48 +0100447 // Normal usage just at the limit.
448 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
449 // Processing time just below over use limit given kEncodeMaxFrameRate.
450 int64_t processing_time_us =
451 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100452 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100453 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
454 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
455 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100456 overuse_detector_->CheckForOveruse(observer_);
sprangfda496a2017-06-15 04:21:07 -0700457 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100458
459 // Over the limit to overuse.
460 processing_time_us =
461 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100462 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100463 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
464 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
465 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100466 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100467 }
468
469 // Reduce input frame rate. Should still trigger overuse.
470 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
Niels Möller73f29cb2018-01-31 16:09:31 +0100471 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100472 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
473 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
474 processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100475 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100476 }
477}
478
479TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
480 const int kMaxFrameRate = 20;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200481 overuse_detector_->SetOptions(options_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100482 overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
483 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
484 // Maximum frame interval allowed is 35% above ideal.
485 int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
486 // Maximum processing time, without triggering overuse, allowed with the above
487 // frame interval.
488 int64_t max_processing_time_us =
489 (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
490 100;
491
492 // Processing time just below overuse limit given kMaxFrameRate.
493 int64_t processing_time_us = (98 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100494 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller7dc26b72017-12-06 10:27:48 +0100495 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
496 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
497 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100498 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100499 }
500
501 // Go above limit, trigger overuse.
502 processing_time_us = (102 * max_processing_time_us) / 100;
Niels Möller73f29cb2018-01-31 16:09:31 +0100503 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100504 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
505 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
506 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100507 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100508 }
509
510 // Increase frame interval, should still trigger overuse.
511 max_frame_interval_us *= 2;
Niels Möller73f29cb2018-01-31 16:09:31 +0100512 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller7dc26b72017-12-06 10:27:48 +0100513 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
514 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
515 kHeight, processing_time_us);
Niels Möller73f29cb2018-01-31 16:09:31 +0100516 overuse_detector_->CheckForOveruse(observer_);
Niels Möller7dc26b72017-12-06 10:27:48 +0100517 }
sprangfda496a2017-06-15 04:21:07 -0700518}
519
Niels Möllere541be72017-12-13 13:03:10 +0100520// Models screencast, with irregular arrival of frames which are heavy
521// to encode.
522TEST_F(OveruseFrameDetectorTest, NoOveruseForLargeRandomFrameInterval) {
523 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
524 // behavior is improved in this scenario, with only AdaptUp events,
525 // and estimated load closer to the true average.
526
Niels Möller73f29cb2018-01-31 16:09:31 +0100527 // EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
528 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möllere541be72017-12-13 13:03:10 +0100529 // .Times(testing::AtLeast(1));
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200530 overuse_detector_->SetOptions(options_);
Niels Möllere541be72017-12-13 13:03:10 +0100531
532 const int kNumFrames = 500;
533 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
534
535 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
536 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
537
538 const int kTargetFramerate = 5;
539
540 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
541
Yves Gerey665174f2018-06-19 15:03:05 +0200542 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
543 kMaxIntervalUs, kWidth, kHeight,
544 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100545 // Average usage 19%. Check that estimate is in the right ball park.
546 // EXPECT_NEAR(UsagePercent(), 20, 10);
547 EXPECT_NEAR(UsagePercent(), 20, 35);
548}
549
550// Models screencast, with irregular arrival of frames, often
551// exceeding the timeout interval.
552TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
553 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
554 // behavior is improved in this scenario, and we get AdaptUp events.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200555 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100556 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
557 // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möllere541be72017-12-13 13:03:10 +0100558 // .Times(testing::AtLeast(1));
559
560 const int kNumFrames = 500;
561 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
562
563 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
564 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
565
566 const int kTargetFramerate = 5;
567
568 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
569
Yves Gerey665174f2018-06-19 15:03:05 +0200570 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
571 kMaxIntervalUs, kWidth, kHeight,
572 kEncodeTimeUs);
Niels Möllere541be72017-12-13 13:03:10 +0100573
574 // Average usage 6.6%, but since the frame_timeout_interval_ms is
575 // only 1500 ms, we often reset the estimate to the initial value.
576 // Check that estimate is in the right ball park.
577 EXPECT_GE(UsagePercent(), 1);
578 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
579}
580
Niels Möller83dbeac2017-12-14 16:39:44 +0100581// Tests using new cpu load estimator
582class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
583 protected:
584 void SetUp() override {
585 options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
586 OveruseFrameDetectorTest::SetUp();
587 }
588
589 void InsertAndSendFramesWithInterval(int num_frames,
590 int interval_us,
591 int width,
592 int height,
593 int delay_us) override {
594 VideoFrame frame(I420Buffer::Create(width, height),
595 webrtc::kVideoRotation_0, 0);
596 while (num_frames-- > 0) {
597 int64_t capture_time_us = rtc::TimeMicros();
598 overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
599 overuse_detector_->FrameSent(0 /* ignored timestamp */,
600 0 /* ignored send_time_us */,
601 capture_time_us, delay_us);
602 clock_.AdvanceTimeMicros(interval_us);
603 }
604 }
605
606 void InsertAndSendFramesWithRandomInterval(int num_frames,
607 int min_interval_us,
608 int max_interval_us,
609 int width,
610 int height,
611 int delay_us) override {
612 webrtc::Random random(17);
613
614 VideoFrame frame(I420Buffer::Create(width, height),
615 webrtc::kVideoRotation_0, 0);
616 for (int i = 0; i < num_frames; i++) {
617 int interval_us = random.Rand(min_interval_us, max_interval_us);
618 int64_t capture_time_us = rtc::TimeMicros();
619 overuse_detector_->FrameCaptured(frame, capture_time_us);
620 overuse_detector_->FrameSent(0 /* ignored timestamp */,
621 0 /* ignored send_time_us */,
622 capture_time_us, delay_us);
623
Niels Möller73f29cb2018-01-31 16:09:31 +0100624 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100625 clock_.AdvanceTimeMicros(interval_us);
626 }
627 }
628
629 void ForceUpdate(int width, int height) override {
630 // This is mainly to check initial values and whether the overuse
631 // detector has been reset or not.
632 InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
633 kFrameIntervalUs);
634 }
635};
636
637// UsagePercent() > high_encode_usage_threshold_percent => overuse.
638// UsagePercent() < low_encode_usage_threshold_percent => underuse.
639TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
640 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200641 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100642 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100643 TriggerOveruse(options_.high_threshold_consecutive_count);
644}
645
646TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
647 // usage > high => overuse
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200648 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100649 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100650 TriggerOveruse(options_.high_threshold_consecutive_count);
651 // usage < low => underuse
Niels Möller73f29cb2018-01-31 16:09:31 +0100652 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100653 TriggerUnderuse();
654}
655
656TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200657 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100658 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
Niels Möller83dbeac2017-12-14 16:39:44 +0100659 TriggerOveruse(options_.high_threshold_consecutive_count);
660 TriggerOveruse(options_.high_threshold_consecutive_count);
Niels Möller73f29cb2018-01-31 16:09:31 +0100661 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100662 TriggerUnderuse();
663}
664
665TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
666 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
667 options_.min_process_count = 1;
668 CpuOveruseObserverImpl overuse_observer;
Niels Möller73f29cb2018-01-31 16:09:31 +0100669 observer_ = nullptr;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200670 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200671 InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
672 kProcessTimeUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100673 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100674 EXPECT_EQ(0, overuse_observer.normaluse_);
675 clock_.AdvanceTimeMicros(kProcessIntervalUs);
Niels Möller73f29cb2018-01-31 16:09:31 +0100676 overuse_detector_->CheckForOveruse(&overuse_observer);
Niels Möller83dbeac2017-12-14 16:39:44 +0100677 EXPECT_EQ(1, overuse_observer.normaluse_);
678}
679
680TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200681 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100682 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
683 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
Niels Möller83dbeac2017-12-14 16:39:44 +0100684 for (size_t i = 0; i < 64; ++i) {
685 TriggerOveruse(options_.high_threshold_consecutive_count);
686 }
687}
688
689TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100690 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
Niels Möller83dbeac2017-12-14 16:39:44 +0100691 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200692 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100693 TriggerOveruse(2);
694}
695
696TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100697 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
Niels Möller83dbeac2017-12-14 16:39:44 +0100698 options_.high_threshold_consecutive_count = 2;
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200699 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100700 TriggerOveruse(1);
701}
702
703TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200704 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200705 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
706 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100707 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
708}
709
710TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200711 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100712 ForceUpdate(kWidth, kHeight);
713 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200714 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
715 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100716 EXPECT_NE(InitialUsage(), UsagePercent());
717 // Verify reset (with new width/height).
718 ForceUpdate(kWidth, kHeight + 1);
719 EXPECT_EQ(InitialUsage(), UsagePercent());
720}
721
722TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200723 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100724 ForceUpdate(kWidth, kHeight);
725 EXPECT_EQ(InitialUsage(), UsagePercent());
Yves Gerey665174f2018-06-19 15:03:05 +0200726 InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
727 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100728 EXPECT_NE(InitialUsage(), UsagePercent());
729 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200730 2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
731 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100732 EXPECT_NE(InitialUsage(), UsagePercent());
733 // Verify reset.
734 InsertAndSendFramesWithInterval(
Yves Gerey665174f2018-06-19 15:03:05 +0200735 2,
736 (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
737 kWidth, kHeight, kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100738 ForceUpdate(kWidth, kHeight);
739 EXPECT_EQ(InitialUsage(), UsagePercent());
740}
741
742TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200743 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100744 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
745 kProcessTimeUs);
746 // No update for the first sample.
747 EXPECT_EQ(InitialUsage(), UsagePercent());
748
749 // Total time approximately 40 * 33ms = 1.3s, significantly less
750 // than the 5s time constant.
Yves Gerey665174f2018-06-19 15:03:05 +0200751 InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
752 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100753
754 // Should have started to approach correct load of 15%, but not very far.
755 EXPECT_LT(UsagePercent(), InitialUsage());
756 EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
757
758 // Run for roughly 10s more, should now be closer.
Yves Gerey665174f2018-06-19 15:03:05 +0200759 InsertAndSendFramesWithInterval(300, kFrameIntervalUs, kWidth, kHeight,
760 kProcessTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100761 EXPECT_NEAR(UsagePercent(), 20, 5);
762}
763
764TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200765 overuse_detector_->SetOptions(options_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100766 ForceUpdate(kWidth, kHeight);
767 EXPECT_EQ(InitialUsage(), UsagePercent());
768}
769
770TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200771 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200772 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100773 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
774 static const size_t kNumFramesEncodingDelay = 3;
775 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
776 webrtc::kVideoRotation_0, 0);
777 for (size_t i = 0; i < 1000; ++i) {
778 // Unique timestamps.
779 frame.set_timestamp(static_cast<uint32_t>(i));
780 int64_t capture_time_us = rtc::TimeMicros();
781 overuse_detector_->FrameCaptured(frame, capture_time_us);
782 clock_.AdvanceTimeMicros(kIntervalUs);
783 if (i > kNumFramesEncodingDelay) {
784 overuse_detector_->FrameSent(
785 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
786 capture_time_us, kIntervalUs);
787 }
Niels Möller73f29cb2018-01-31 16:09:31 +0100788 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100789 }
790}
791
792TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
793 // >85% encoding time should trigger overuse.
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200794 overuse_detector_->SetOptions(options_);
Yves Gerey665174f2018-06-19 15:03:05 +0200795 EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100796 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
797 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
798 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
799 webrtc::kVideoRotation_0, 0);
800 uint32_t timestamp = 0;
801 for (size_t i = 0; i < 1000; ++i) {
802 frame.set_timestamp(timestamp);
803 int64_t capture_time_us = rtc::TimeMicros();
804 overuse_detector_->FrameCaptured(frame, capture_time_us);
805 // Encode and send first parts almost instantly.
806 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
807 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
808 rtc::kNumMicrosecsPerMillisec);
809 // Encode heavier part, resulting in >85% usage total.
810 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
811 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
812 kDelayUs);
813 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
814 timestamp += kIntervalUs * 90 / 1000;
Niels Möller73f29cb2018-01-31 16:09:31 +0100815 overuse_detector_->CheckForOveruse(observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100816 }
817}
818
819TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
820 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
821
822 rtc::Event event(false, false);
823 queue.PostTask([this, &event] {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200824 overuse_detector_->StartCheckForOveruse(options_, observer_);
Niels Möller83dbeac2017-12-14 16:39:44 +0100825 event.Set();
826 });
827 event.Wait(rtc::Event::kForever);
828
829 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
830 // set |event| to end the test.
Niels Möller73f29cb2018-01-31 16:09:31 +0100831 EXPECT_CALL(mock_observer_, AdaptUp(reason_))
Niels Möller83dbeac2017-12-14 16:39:44 +0100832 .WillOnce(InvokeWithoutArgs([this, &event] {
833 overuse_detector_->StopCheckForOveruse();
834 event.Set();
835 }));
836
837 queue.PostTask([this] {
838 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
839 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
840 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
841 kDelayUs1);
842 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
843 kDelayUs2);
844 });
845
846 EXPECT_TRUE(event.Wait(10000));
847}
848
849// Models screencast, with irregular arrival of frames which are heavy
850// to encode.
851TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200852 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100853 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Yves Gerey665174f2018-06-19 15:03:05 +0200854 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100855
856 const int kNumFrames = 500;
857 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
858
859 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
860 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
861
Yves Gerey665174f2018-06-19 15:03:05 +0200862 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
863 kMaxIntervalUs, kWidth, kHeight,
864 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100865 // Average usage 19%. Check that estimate is in the right ball park.
866 EXPECT_NEAR(UsagePercent(), 20, 10);
867}
868
869// Models screencast, with irregular arrival of frames, often
870// exceeding the timeout interval.
871TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
Niels Möllerd1f7eb62018-03-28 16:40:58 +0200872 overuse_detector_->SetOptions(options_);
Niels Möller73f29cb2018-01-31 16:09:31 +0100873 EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
Yves Gerey665174f2018-06-19 15:03:05 +0200874 EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(testing::AtLeast(1));
Niels Möller83dbeac2017-12-14 16:39:44 +0100875
876 const int kNumFrames = 500;
877 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
878
879 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
880 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
881
Yves Gerey665174f2018-06-19 15:03:05 +0200882 InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
883 kMaxIntervalUs, kWidth, kHeight,
884 kEncodeTimeUs);
Niels Möller83dbeac2017-12-14 16:39:44 +0100885
886 // Average usage 6.6%, but since the frame_timeout_interval_ms is
887 // only 1500 ms, we often reset the estimate to the initial value.
888 // Check that estimate is in the right ball park.
889 EXPECT_GE(UsagePercent(), 1);
890 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
891}
892
Niels Möller58d2a5e2018-08-07 16:37:18 +0200893TEST_F(OveruseFrameDetectorTest2, ToleratesOutOfOrderFrames) {
894 overuse_detector_->SetOptions(options_);
895 // Represents a cpu utilization close to 100%. First input frame results in
896 // three encoded frames, and the last of those isn't finished until after the
897 // first encoded frame corresponding to the next input frame.
898 const int kEncodeTimeUs = 30 * rtc::kNumMicrosecsPerMillisec;
899 const int kCaptureTimesMs[] = { 33, 33, 66, 33 };
900
901 for (int capture_time_ms : kCaptureTimesMs) {
902 overuse_detector_->FrameSent(
903 0, 0, capture_time_ms * rtc::kNumMicrosecsPerMillisec, kEncodeTimeUs);
904 }
905 EXPECT_GE(UsagePercent(), InitialUsage());
906}
907
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000908} // namespace webrtc