blob: cefc91c2ef8e2a7a56e0a12196f2d7d6c18079a1 [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:
nissee0e3bdf2017-01-18 02:16:20 -080061 OveruseFrameDetectorUnderTest(const CpuOveruseOptions& options,
sprangb1ca0732017-02-01 08:38:12 -080062 AdaptationObserverInterface* overuse_observer,
perkjd52063f2016-09-07 06:32:18 -070063 CpuOveruseMetricsObserver* metrics_observer)
nissee0e3bdf2017-01-18 02:16:20 -080064 : OveruseFrameDetector(options,
perkjd52063f2016-09-07 06:32:18 -070065 overuse_observer,
perkjd52063f2016-09-07 06:32:18 -070066 metrics_observer) {}
67 ~OveruseFrameDetectorUnderTest() {}
68
69 using OveruseFrameDetector::CheckForOveruse;
70};
71
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000072class OveruseFrameDetectorTest : public ::testing::Test,
73 public CpuOveruseMetricsObserver {
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000074 protected:
nisseef8b61e2016-04-29 06:09:15 -070075 void SetUp() override {
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +000076 observer_.reset(new MockCpuOveruseObserver());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +000077 options_.min_process_count = 0;
Peter Boström4b91bd02015-06-26 06:58:16 +020078 ReinitializeOveruseDetector();
79 }
80
81 void ReinitializeOveruseDetector() {
perkjd52063f2016-09-07 06:32:18 -070082 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
Niels Möller6b642f72017-12-08 14:11:14 +010083 options_, observer_.get(), this));
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +000084 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +000085
Peter Boströme4499152016-02-05 11:13:28 +010086 void OnEncodedFrameTimeMeasured(int encode_time_ms,
87 const CpuOveruseMetrics& metrics) override {
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000088 metrics_ = metrics;
89 }
90
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +000091 int InitialUsage() {
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +000092 return ((options_.low_encode_usage_threshold_percent +
93 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5;
94 }
95
Niels Möller83dbeac2017-12-14 16:39:44 +010096 virtual void InsertAndSendFramesWithInterval(int num_frames,
97 int interval_us,
98 int width,
99 int height,
100 int delay_us) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100101 VideoFrame frame(I420Buffer::Create(width, height),
102 webrtc::kVideoRotation_0, 0);
103 uint32_t timestamp = 0;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000104 while (num_frames-- > 0) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100105 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100106 int64_t capture_time_us = rtc::TimeMicros();
107 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100108 clock_.AdvanceTimeMicros(delay_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100109 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
110 capture_time_us, delay_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100111 clock_.AdvanceTimeMicros(interval_us - delay_us);
112 timestamp += interval_us * 90 / 1000;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000113 }
114 }
115
Niels Möller83dbeac2017-12-14 16:39:44 +0100116 virtual void InsertAndSendFramesWithRandomInterval(int num_frames,
117 int min_interval_us,
118 int max_interval_us,
119 int width,
120 int height,
121 int delay_us) {
Niels Möllere541be72017-12-13 13:03:10 +0100122 webrtc::Random random(17);
123
124 VideoFrame frame(I420Buffer::Create(width, height),
125 webrtc::kVideoRotation_0, 0);
126 uint32_t timestamp = 0;
127 while (num_frames-- > 0) {
128 frame.set_timestamp(timestamp);
129 int interval_us = random.Rand(min_interval_us, max_interval_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100130 int64_t capture_time_us = rtc::TimeMicros();
131 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möllere541be72017-12-13 13:03:10 +0100132 clock_.AdvanceTimeMicros(delay_us);
Niels Möller83dbeac2017-12-14 16:39:44 +0100133 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
134 capture_time_us,
135 rtc::Optional<int>(delay_us));
Niels Möllere541be72017-12-13 13:03:10 +0100136
137 overuse_detector_->CheckForOveruse();
138 // Avoid turning clock backwards.
139 if (interval_us > delay_us)
140 clock_.AdvanceTimeMicros(interval_us - delay_us);
141
142 timestamp += interval_us * 90 / 1000;
143 }
144 }
145
Niels Möller83dbeac2017-12-14 16:39:44 +0100146 virtual void ForceUpdate(int width, int height) {
Niels Möller7dc26b72017-12-06 10:27:48 +0100147 // Insert one frame, wait a second and then put in another to force update
148 // the usage. From the tests where these are used, adding another sample
149 // doesn't affect the expected outcome (this is mainly to check initial
150 // values and whether the overuse detector has been reset or not).
151 InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec,
152 width, height, kFrameIntervalUs);
Peter Boströme4499152016-02-05 11:13:28 +0100153 }
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000154 void TriggerOveruse(int num_times) {
nissee0e3bdf2017-01-18 02:16:20 -0800155 const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000156 for (int i = 0; i < num_times; ++i) {
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000157 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800158 1000, kFrameIntervalUs, kWidth, kHeight, kDelayUs);
perkjd52063f2016-09-07 06:32:18 -0700159 overuse_detector_->CheckForOveruse();
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000160 }
161 }
162
Åsa Persson746210f2015-09-08 10:52:42 +0200163 void TriggerUnderuse() {
nissee0e3bdf2017-01-18 02:16:20 -0800164 const int kDelayUs1 = 5000;
165 const int kDelayUs2 = 6000;
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000166 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800167 1300, kFrameIntervalUs, kWidth, kHeight, kDelayUs1);
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000168 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800169 1, kFrameIntervalUs, kWidth, kHeight, kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700170 overuse_detector_->CheckForOveruse();
asapersson@webrtc.orgce12f1f2014-03-24 21:59:16 +0000171 }
172
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000173 int UsagePercent() { return metrics_.encode_usage_percent; }
asapersson@webrtc.orgab6bf4f2014-05-27 07:43:15 +0000174
sprangfda496a2017-06-15 04:21:07 -0700175 int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
176 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
177 int64_t max_processing_time_us =
178 (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
179 return max_processing_time_us;
180 }
181
182 int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
183 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
184 int64_t max_processing_time_us =
185 (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
186 return max_processing_time_us;
187 }
188
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000189 CpuOveruseOptions options_;
nissee0e3bdf2017-01-18 02:16:20 -0800190 rtc::ScopedFakeClock clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800191 std::unique_ptr<MockCpuOveruseObserver> observer_;
perkjd52063f2016-09-07 06:32:18 -0700192 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000193 CpuOveruseMetrics metrics_;
kthelgason876222f2016-11-29 01:44:11 -0800194
sprangb1ca0732017-02-01 08:38:12 -0800195 static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000196};
197
Åsa Persson746210f2015-09-08 10:52:42 +0200198
Åsa Persson746210f2015-09-08 10:52:42 +0200199// UsagePercent() > high_encode_usage_threshold_percent => overuse.
200// UsagePercent() < low_encode_usage_threshold_percent => underuse.
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000201TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
Åsa Persson746210f2015-09-08 10:52:42 +0200202 // usage > high => overuse
sprangb1ca0732017-02-01 08:38:12 -0800203 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000204 TriggerOveruse(options_.high_threshold_consecutive_count);
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000205}
206
207TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
Åsa Persson746210f2015-09-08 10:52:42 +0200208 // usage > high => overuse
sprangb1ca0732017-02-01 08:38:12 -0800209 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000210 TriggerOveruse(options_.high_threshold_consecutive_count);
Åsa Persson746210f2015-09-08 10:52:42 +0200211 // usage < low => underuse
sprangb1ca0732017-02-01 08:38:12 -0800212 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000213 TriggerUnderuse();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000214}
215
asapersson@webrtc.org2881ab12014-06-12 08:46:46 +0000216TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) {
perkjd52063f2016-09-07 06:32:18 -0700217 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
Niels Möller6b642f72017-12-08 14:11:14 +0100218 options_, nullptr, this));
sprangb1ca0732017-02-01 08:38:12 -0800219 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000220 TriggerOveruse(options_.high_threshold_consecutive_count);
sprangb1ca0732017-02-01 08:38:12 -0800221 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(0);
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000222 TriggerUnderuse();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000223}
224
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000225TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
sprangb1ca0732017-02-01 08:38:12 -0800226 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(2);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000227 TriggerOveruse(options_.high_threshold_consecutive_count);
228 TriggerOveruse(options_.high_threshold_consecutive_count);
sprangb1ca0732017-02-01 08:38:12 -0800229 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(testing::AtLeast(1));
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000230 TriggerUnderuse();
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000231}
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000232
asapersson@webrtc.org9aed0022014-10-16 06:57:12 +0000233TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
nissee0e3bdf2017-01-18 02:16:20 -0800234 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000235 options_.min_process_count = 1;
Peter Boström4b91bd02015-06-26 06:58:16 +0200236 CpuOveruseObserverImpl overuse_observer;
perkjd52063f2016-09-07 06:32:18 -0700237 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
Niels Möller6b642f72017-12-08 14:11:14 +0100238 options_, &overuse_observer, this));
Åsa Persson746210f2015-09-08 10:52:42 +0200239 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800240 1200, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
perkjd52063f2016-09-07 06:32:18 -0700241 overuse_detector_->CheckForOveruse();
Peter Boström4b91bd02015-06-26 06:58:16 +0200242 EXPECT_EQ(0, overuse_observer.normaluse_);
nissee0e3bdf2017-01-18 02:16:20 -0800243 clock_.AdvanceTimeMicros(kProcessIntervalUs);
perkjd52063f2016-09-07 06:32:18 -0700244 overuse_detector_->CheckForOveruse();
Peter Boström4b91bd02015-06-26 06:58:16 +0200245 EXPECT_EQ(1, overuse_observer.normaluse_);
asapersson@webrtc.orgb60346e2014-02-17 19:02:15 +0000246}
247
pbos@webrtc.orga9575702013-08-30 17:16:32 +0000248TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
sprangb1ca0732017-02-01 08:38:12 -0800249 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(0);
250 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(64);
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100251 for (size_t i = 0; i < 64; ++i) {
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000252 TriggerOveruse(options_.high_threshold_consecutive_count);
253 }
mflodman@webrtc.orgd4412fe2013-07-31 16:42:21 +0000254}
255
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000256TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
sprangb1ca0732017-02-01 08:38:12 -0800257 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000258 options_.high_threshold_consecutive_count = 2;
Peter Boström4b91bd02015-06-26 06:58:16 +0200259 ReinitializeOveruseDetector();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000260 TriggerOveruse(2);
261}
262
263TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
sprangb1ca0732017-02-01 08:38:12 -0800264 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000265 options_.high_threshold_consecutive_count = 2;
Peter Boström4b91bd02015-06-26 06:58:16 +0200266 ReinitializeOveruseDetector();
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000267 TriggerOveruse(1);
268}
269
Åsa Persson746210f2015-09-08 10:52:42 +0200270TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
271 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800272 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
273 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000274}
275
Åsa Persson746210f2015-09-08 10:52:42 +0200276TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
Peter Boströme4499152016-02-05 11:13:28 +0100277 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200278 EXPECT_EQ(InitialUsage(), UsagePercent());
279 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800280 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200281 EXPECT_NE(InitialUsage(), UsagePercent());
Peter Boströme4499152016-02-05 11:13:28 +0100282 // Verify reset (with new width/height).
283 ForceUpdate(kWidth, kHeight + 1);
Åsa Persson746210f2015-09-08 10:52:42 +0200284 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000285}
286
Åsa Persson746210f2015-09-08 10:52:42 +0200287TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
Peter Boströme4499152016-02-05 11:13:28 +0100288 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200289 EXPECT_EQ(InitialUsage(), UsagePercent());
290 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800291 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200292 EXPECT_NE(InitialUsage(), UsagePercent());
293 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800294 2, options_.frame_timeout_interval_ms *
295 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
Åsa Persson746210f2015-09-08 10:52:42 +0200296 EXPECT_NE(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000297 // Verify reset.
Åsa Persson746210f2015-09-08 10:52:42 +0200298 InsertAndSendFramesWithInterval(
nissee0e3bdf2017-01-18 02:16:20 -0800299 2, (options_.frame_timeout_interval_ms + 1) *
300 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
Peter Boströme4499152016-02-05 11:13:28 +0100301 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200302 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.org8a8c3ef2014-03-20 13:15:01 +0000303}
304
Niels Möller7dc26b72017-12-06 10:27:48 +0100305TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
306 options_.min_frame_samples = 40;
307 ReinitializeOveruseDetector();
308 InsertAndSendFramesWithInterval(
309 40, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
310 EXPECT_EQ(InitialUsage(), UsagePercent());
311 // Pass time far enough to digest all previous samples.
312 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
313 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
314 kProcessTimeUs);
315 // The last sample has not been processed here.
316 EXPECT_EQ(InitialUsage(), UsagePercent());
317
318 // Pass time far enough to digest all previous samples, 41 in total.
319 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
320 InsertAndSendFramesWithInterval(
321 1, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
322 EXPECT_NE(InitialUsage(), UsagePercent());
323}
324
Åsa Persson746210f2015-09-08 10:52:42 +0200325TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
Peter Boströme4499152016-02-05 11:13:28 +0100326 ForceUpdate(kWidth, kHeight);
Åsa Persson746210f2015-09-08 10:52:42 +0200327 EXPECT_EQ(InitialUsage(), UsagePercent());
asapersson@webrtc.orgb24d3352013-11-20 13:51:40 +0000328}
329
Niels Möller7dc26b72017-12-06 10:27:48 +0100330TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
331 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_))
332 .Times(testing::AtLeast(1));
333 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
334 static const size_t kNumFramesEncodingDelay = 3;
335 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
336 webrtc::kVideoRotation_0, 0);
337 for (size_t i = 0; i < 1000; ++i) {
338 // Unique timestamps.
339 frame.set_timestamp(static_cast<uint32_t>(i));
Niels Möller83dbeac2017-12-14 16:39:44 +0100340 int64_t capture_time_us = rtc::TimeMicros();
341 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100342 clock_.AdvanceTimeMicros(kIntervalUs);
343 if (i > kNumFramesEncodingDelay) {
344 overuse_detector_->FrameSent(
Niels Möller83dbeac2017-12-14 16:39:44 +0100345 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
346 capture_time_us, kIntervalUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100347 }
348 overuse_detector_->CheckForOveruse();
349 }
350}
351
352TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
353 // >85% encoding time should trigger overuse.
354 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_))
355 .Times(testing::AtLeast(1));
356 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
357 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
358 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
359 webrtc::kVideoRotation_0, 0);
360 uint32_t timestamp = 0;
361 for (size_t i = 0; i < 1000; ++i) {
362 frame.set_timestamp(timestamp);
Niels Möller83dbeac2017-12-14 16:39:44 +0100363 int64_t capture_time_us = rtc::TimeMicros();
364 overuse_detector_->FrameCaptured(frame, capture_time_us);
Niels Möller7dc26b72017-12-06 10:27:48 +0100365 // Encode and send first parts almost instantly.
366 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100367 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
368 rtc::kNumMicrosecsPerMillisec);
Niels Möller7dc26b72017-12-06 10:27:48 +0100369 // Encode heavier part, resulting in >85% usage total.
370 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
Niels Möller83dbeac2017-12-14 16:39:44 +0100371 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
372 kDelayUs);
Niels Möller7dc26b72017-12-06 10:27:48 +0100373 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
374 timestamp += kIntervalUs * 90 / 1000;
375 overuse_detector_->CheckForOveruse();
376 }
377}
378
perkjd52063f2016-09-07 06:32:18 -0700379TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
380 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
381
382 rtc::Event event(false, false);
383 queue.PostTask([this, &event] {
384 overuse_detector_->StartCheckForOveruse();
385 event.Set();
386 });
387 event.Wait(rtc::Event::kForever);
388
389 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
390 // set |event| to end the test.
sprangb1ca0732017-02-01 08:38:12 -0800391 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_))
kthelgason876222f2016-11-29 01:44:11 -0800392 .WillOnce(InvokeWithoutArgs([this, &event] {
perkjd52063f2016-09-07 06:32:18 -0700393 overuse_detector_->StopCheckForOveruse();
394 event.Set();
395 }));
396
eladalon1cc5fc32017-08-23 04:15:18 -0700397 queue.PostTask([this] {
nissee0e3bdf2017-01-18 02:16:20 -0800398 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
399 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
400 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
401 kDelayUs1);
402 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
403 kDelayUs2);
perkjd52063f2016-09-07 06:32:18 -0700404 });
405
406 EXPECT_TRUE(event.Wait(10000));
407}
408
Niels Möller7dc26b72017-12-06 10:27:48 +0100409TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
410 const int kCapturerMaxFrameRate = 30;
411 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
sprangfda496a2017-06-15 04:21:07 -0700412
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;
418 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
419 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
420 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
421 processing_time_us);
sprangfda496a2017-06-15 04:21:07 -0700422 overuse_detector_->CheckForOveruse();
423 }
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);
428 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
429 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
430 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
431 processing_time_us);
432 overuse_detector_->CheckForOveruse();
433 }
434
435 // Reduce processing time to trigger underuse.
436 processing_time_us =
437 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
438 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(1);
439 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
440 processing_time_us);
441 overuse_detector_->CheckForOveruse();
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.
446 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
sprangfda496a2017-06-15 04:21:07 -0700447
Niels Möller7dc26b72017-12-06 10:27:48 +0100448 // Normal usage just at the limit.
449 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
450 // Processing time just below over use limit given kEncodeMaxFrameRate.
451 int64_t processing_time_us =
452 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
453 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
454 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
455 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
456 processing_time_us);
sprangfda496a2017-06-15 04:21:07 -0700457 overuse_detector_->CheckForOveruse();
458 }
Niels Möller7dc26b72017-12-06 10:27:48 +0100459
460 // Over the limit to overuse.
461 processing_time_us =
462 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
463 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
464 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
465 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
466 processing_time_us);
467 overuse_detector_->CheckForOveruse();
468 }
469
470 // Reduce input frame rate. Should still trigger overuse.
471 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
472 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
473 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
474 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
475 processing_time_us);
476 overuse_detector_->CheckForOveruse();
477 }
478}
479
480TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
481 const int kMaxFrameRate = 20;
482 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;
494 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
495 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
496 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
497 kHeight, processing_time_us);
498 overuse_detector_->CheckForOveruse();
499 }
500
501 // Go above limit, trigger overuse.
502 processing_time_us = (102 * max_processing_time_us) / 100;
503 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
504 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
505 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
506 kHeight, processing_time_us);
507 overuse_detector_->CheckForOveruse();
508 }
509
510 // Increase frame interval, should still trigger overuse.
511 max_frame_interval_us *= 2;
512 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
513 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
514 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
515 kHeight, processing_time_us);
516 overuse_detector_->CheckForOveruse();
517 }
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
527 // EXPECT_CALL(*(observer_.get()), AdaptDown(_)).Times(0);
528 // EXPECT_CALL(*(observer_.get()), AdaptUp(reason_))
529 // .Times(testing::AtLeast(1));
530
531 const int kNumFrames = 500;
532 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
533
534 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
535 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
536
537 const int kTargetFramerate = 5;
538
539 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
540
541 InsertAndSendFramesWithRandomInterval(kNumFrames,
542 kMinIntervalUs, kMaxIntervalUs,
543 kWidth, kHeight, kEncodeTimeUs);
544 // Average usage 19%. Check that estimate is in the right ball park.
545 // EXPECT_NEAR(UsagePercent(), 20, 10);
546 EXPECT_NEAR(UsagePercent(), 20, 35);
547}
548
549// Models screencast, with irregular arrival of frames, often
550// exceeding the timeout interval.
551TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
552 // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
553 // behavior is improved in this scenario, and we get AdaptUp events.
554 EXPECT_CALL(*(observer_.get()), AdaptDown(_)).Times(0);
555 // EXPECT_CALL(*(observer_.get()), AdaptUp(reason_))
556 // .Times(testing::AtLeast(1));
557
558 const int kNumFrames = 500;
559 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
560
561 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
562 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
563
564 const int kTargetFramerate = 5;
565
566 overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
567
568 InsertAndSendFramesWithRandomInterval(kNumFrames,
569 kMinIntervalUs, kMaxIntervalUs,
570 kWidth, kHeight, kEncodeTimeUs);
571
572 // Average usage 6.6%, but since the frame_timeout_interval_ms is
573 // only 1500 ms, we often reset the estimate to the initial value.
574 // Check that estimate is in the right ball park.
575 EXPECT_GE(UsagePercent(), 1);
576 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
577}
578
Niels Möller83dbeac2017-12-14 16:39:44 +0100579// Tests using new cpu load estimator
580class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
581 protected:
582 void SetUp() override {
583 options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
584 OveruseFrameDetectorTest::SetUp();
585 }
586
587 void InsertAndSendFramesWithInterval(int num_frames,
588 int interval_us,
589 int width,
590 int height,
591 int delay_us) override {
592 VideoFrame frame(I420Buffer::Create(width, height),
593 webrtc::kVideoRotation_0, 0);
594 while (num_frames-- > 0) {
595 int64_t capture_time_us = rtc::TimeMicros();
596 overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
597 overuse_detector_->FrameSent(0 /* ignored timestamp */,
598 0 /* ignored send_time_us */,
599 capture_time_us, delay_us);
600 clock_.AdvanceTimeMicros(interval_us);
601 }
602 }
603
604 void InsertAndSendFramesWithRandomInterval(int num_frames,
605 int min_interval_us,
606 int max_interval_us,
607 int width,
608 int height,
609 int delay_us) override {
610 webrtc::Random random(17);
611
612 VideoFrame frame(I420Buffer::Create(width, height),
613 webrtc::kVideoRotation_0, 0);
614 for (int i = 0; i < num_frames; i++) {
615 int interval_us = random.Rand(min_interval_us, max_interval_us);
616 int64_t capture_time_us = rtc::TimeMicros();
617 overuse_detector_->FrameCaptured(frame, capture_time_us);
618 overuse_detector_->FrameSent(0 /* ignored timestamp */,
619 0 /* ignored send_time_us */,
620 capture_time_us, delay_us);
621
622 overuse_detector_->CheckForOveruse();
623 clock_.AdvanceTimeMicros(interval_us);
624 }
625 }
626
627 void ForceUpdate(int width, int height) override {
628 // This is mainly to check initial values and whether the overuse
629 // detector has been reset or not.
630 InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
631 kFrameIntervalUs);
632 }
633};
634
635// UsagePercent() > high_encode_usage_threshold_percent => overuse.
636// UsagePercent() < low_encode_usage_threshold_percent => underuse.
637TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
638 // usage > high => overuse
639 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
640 TriggerOveruse(options_.high_threshold_consecutive_count);
641}
642
643TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
644 // usage > high => overuse
645 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
646 TriggerOveruse(options_.high_threshold_consecutive_count);
647 // usage < low => underuse
648 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(testing::AtLeast(1));
649 TriggerUnderuse();
650}
651
652TEST_F(OveruseFrameDetectorTest2, OveruseAndRecoverWithNoObserver) {
653 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
654 options_, nullptr, this));
655 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
656 TriggerOveruse(options_.high_threshold_consecutive_count);
657 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(0);
658 TriggerUnderuse();
659}
660
661TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
662 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(2);
663 TriggerOveruse(options_.high_threshold_consecutive_count);
664 TriggerOveruse(options_.high_threshold_consecutive_count);
665 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(testing::AtLeast(1));
666 TriggerUnderuse();
667}
668
669TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
670 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
671 options_.min_process_count = 1;
672 CpuOveruseObserverImpl overuse_observer;
673 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
674 options_, &overuse_observer, this));
675 InsertAndSendFramesWithInterval(
676 1200, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
677 overuse_detector_->CheckForOveruse();
678 EXPECT_EQ(0, overuse_observer.normaluse_);
679 clock_.AdvanceTimeMicros(kProcessIntervalUs);
680 overuse_detector_->CheckForOveruse();
681 EXPECT_EQ(1, overuse_observer.normaluse_);
682}
683
684TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
685 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(0);
686 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(64);
687 for (size_t i = 0; i < 64; ++i) {
688 TriggerOveruse(options_.high_threshold_consecutive_count);
689 }
690}
691
692TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
693 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
694 options_.high_threshold_consecutive_count = 2;
695 ReinitializeOveruseDetector();
696 TriggerOveruse(2);
697}
698
699TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
700 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
701 options_.high_threshold_consecutive_count = 2;
702 ReinitializeOveruseDetector();
703 TriggerOveruse(1);
704}
705
706TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
707 InsertAndSendFramesWithInterval(
708 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
709 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
710}
711
712TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
713 ForceUpdate(kWidth, kHeight);
714 EXPECT_EQ(InitialUsage(), UsagePercent());
715 InsertAndSendFramesWithInterval(
716 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
717 EXPECT_NE(InitialUsage(), UsagePercent());
718 // Verify reset (with new width/height).
719 ForceUpdate(kWidth, kHeight + 1);
720 EXPECT_EQ(InitialUsage(), UsagePercent());
721}
722
723TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
724 ForceUpdate(kWidth, kHeight);
725 EXPECT_EQ(InitialUsage(), UsagePercent());
726 InsertAndSendFramesWithInterval(
727 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
728 EXPECT_NE(InitialUsage(), UsagePercent());
729 InsertAndSendFramesWithInterval(
730 2, options_.frame_timeout_interval_ms *
731 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
732 EXPECT_NE(InitialUsage(), UsagePercent());
733 // Verify reset.
734 InsertAndSendFramesWithInterval(
735 2, (options_.frame_timeout_interval_ms + 1) *
736 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
737 ForceUpdate(kWidth, kHeight);
738 EXPECT_EQ(InitialUsage(), UsagePercent());
739}
740
741TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
742 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
743 kProcessTimeUs);
744 // No update for the first sample.
745 EXPECT_EQ(InitialUsage(), UsagePercent());
746
747 // Total time approximately 40 * 33ms = 1.3s, significantly less
748 // than the 5s time constant.
749 InsertAndSendFramesWithInterval(
750 40, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
751
752 // Should have started to approach correct load of 15%, but not very far.
753 EXPECT_LT(UsagePercent(), InitialUsage());
754 EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
755
756 // Run for roughly 10s more, should now be closer.
757 InsertAndSendFramesWithInterval(
758 300, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
759 EXPECT_NEAR(UsagePercent(), 20, 5);
760}
761
762TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
763 ForceUpdate(kWidth, kHeight);
764 EXPECT_EQ(InitialUsage(), UsagePercent());
765}
766
767TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
768 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_))
769 .Times(testing::AtLeast(1));
770 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
771 static const size_t kNumFramesEncodingDelay = 3;
772 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
773 webrtc::kVideoRotation_0, 0);
774 for (size_t i = 0; i < 1000; ++i) {
775 // Unique timestamps.
776 frame.set_timestamp(static_cast<uint32_t>(i));
777 int64_t capture_time_us = rtc::TimeMicros();
778 overuse_detector_->FrameCaptured(frame, capture_time_us);
779 clock_.AdvanceTimeMicros(kIntervalUs);
780 if (i > kNumFramesEncodingDelay) {
781 overuse_detector_->FrameSent(
782 static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
783 capture_time_us, kIntervalUs);
784 }
785 overuse_detector_->CheckForOveruse();
786 }
787}
788
789TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
790 // >85% encoding time should trigger overuse.
791 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_))
792 .Times(testing::AtLeast(1));
793 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
794 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
795 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
796 webrtc::kVideoRotation_0, 0);
797 uint32_t timestamp = 0;
798 for (size_t i = 0; i < 1000; ++i) {
799 frame.set_timestamp(timestamp);
800 int64_t capture_time_us = rtc::TimeMicros();
801 overuse_detector_->FrameCaptured(frame, capture_time_us);
802 // Encode and send first parts almost instantly.
803 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
804 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
805 rtc::kNumMicrosecsPerMillisec);
806 // Encode heavier part, resulting in >85% usage total.
807 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
808 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
809 kDelayUs);
810 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
811 timestamp += kIntervalUs * 90 / 1000;
812 overuse_detector_->CheckForOveruse();
813 }
814}
815
816TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
817 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
818
819 rtc::Event event(false, false);
820 queue.PostTask([this, &event] {
821 overuse_detector_->StartCheckForOveruse();
822 event.Set();
823 });
824 event.Wait(rtc::Event::kForever);
825
826 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
827 // set |event| to end the test.
828 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_))
829 .WillOnce(InvokeWithoutArgs([this, &event] {
830 overuse_detector_->StopCheckForOveruse();
831 event.Set();
832 }));
833
834 queue.PostTask([this] {
835 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
836 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
837 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
838 kDelayUs1);
839 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
840 kDelayUs2);
841 });
842
843 EXPECT_TRUE(event.Wait(10000));
844}
845
846// Models screencast, with irregular arrival of frames which are heavy
847// to encode.
848TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
849 EXPECT_CALL(*(observer_.get()), AdaptDown(_)).Times(0);
850 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_))
851 .Times(testing::AtLeast(1));
852
853 const int kNumFrames = 500;
854 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
855
856 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
857 const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
858
859 InsertAndSendFramesWithRandomInterval(kNumFrames,
860 kMinIntervalUs, kMaxIntervalUs,
861 kWidth, kHeight, kEncodeTimeUs);
862 // Average usage 19%. Check that estimate is in the right ball park.
863 EXPECT_NEAR(UsagePercent(), 20, 10);
864}
865
866// Models screencast, with irregular arrival of frames, often
867// exceeding the timeout interval.
868TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
869 EXPECT_CALL(*(observer_.get()), AdaptDown(_)).Times(0);
870 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_))
871 .Times(testing::AtLeast(1));
872
873 const int kNumFrames = 500;
874 const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
875
876 const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
877 const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
878
879 InsertAndSendFramesWithRandomInterval(kNumFrames,
880 kMinIntervalUs, kMaxIntervalUs,
881 kWidth, kHeight, kEncodeTimeUs);
882
883 // Average usage 6.6%, but since the frame_timeout_interval_ms is
884 // only 1500 ms, we often reset the estimate to the initial value.
885 // Check that estimate is in the right ball park.
886 EXPECT_GE(UsagePercent(), 1);
887 EXPECT_LE(UsagePercent(), InitialUsage() + 5);
888}
889
mflodman@webrtc.orge6168f52013-06-26 11:23:01 +0000890} // namespace webrtc