1 /*
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
11 #include <memory>
12
13 #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"
18 #include "test/gmock.h"
19 #include "test/gtest.h"
20 #include "video/overuse_frame_detector.h"
21
22 namespace webrtc {
23
24 using ::testing::InvokeWithoutArgs;
25
26 namespace {
27 const int kWidth = 640;
28 const int kHeight = 480;
29 const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
30 const int kProcessTimeUs = 5 * rtc::kNumMicrosecsPerMillisec;
31 } // namespace
32
33 class MockCpuOveruseObserver : public AdaptationObserverInterface {
34 public:
MockCpuOveruseObserver()35 MockCpuOveruseObserver() {}
~MockCpuOveruseObserver()36 virtual ~MockCpuOveruseObserver() {}
37
38 MOCK_METHOD1(AdaptUp, void(AdaptReason));
39 MOCK_METHOD1(AdaptDown, void(AdaptReason));
40 };
41
42 class CpuOveruseObserverImpl : public AdaptationObserverInterface {
43 public:
CpuOveruseObserverImpl()44 CpuOveruseObserverImpl() :
45 overuse_(0),
46 normaluse_(0) {}
~CpuOveruseObserverImpl()47 virtual ~CpuOveruseObserverImpl() {}
48
AdaptDown(AdaptReason)49 void AdaptDown(AdaptReason) { ++overuse_; }
AdaptUp(AdaptReason)50 void AdaptUp(AdaptReason) { ++normaluse_; }
51
52 int overuse_;
53 int normaluse_;
54 };
55
56 class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
57 public:
OveruseFrameDetectorUnderTest(const CpuOveruseOptions & options,AdaptationObserverInterface * overuse_observer,EncodedFrameObserver * encoder_timing,CpuOveruseMetricsObserver * metrics_observer)58 OveruseFrameDetectorUnderTest(const CpuOveruseOptions& options,
59 AdaptationObserverInterface* overuse_observer,
60 EncodedFrameObserver* encoder_timing,
61 CpuOveruseMetricsObserver* metrics_observer)
62 : OveruseFrameDetector(options,
63 overuse_observer,
64 encoder_timing,
65 metrics_observer) {}
~OveruseFrameDetectorUnderTest()66 ~OveruseFrameDetectorUnderTest() {}
67
68 using OveruseFrameDetector::CheckForOveruse;
69 };
70
71 class OveruseFrameDetectorTest : public ::testing::Test,
72 public CpuOveruseMetricsObserver {
73 protected:
SetUp()74 void SetUp() override {
75 observer_.reset(new MockCpuOveruseObserver());
76 options_.min_process_count = 0;
77 ReinitializeOveruseDetector();
78 }
79
ReinitializeOveruseDetector()80 void ReinitializeOveruseDetector() {
81 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
82 options_, observer_.get(), nullptr, this));
83 }
84
OnEncodedFrameTimeMeasured(int encode_time_ms,const CpuOveruseMetrics & metrics)85 void OnEncodedFrameTimeMeasured(int encode_time_ms,
86 const CpuOveruseMetrics& metrics) override {
87 metrics_ = metrics;
88 }
89
InitialUsage()90 int InitialUsage() {
91 return ((options_.low_encode_usage_threshold_percent +
92 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5;
93 }
94
InsertAndSendFramesWithInterval(int num_frames,int interval_us,int width,int height,int delay_us)95 void InsertAndSendFramesWithInterval(int num_frames,
96 int interval_us,
97 int width,
98 int height,
99 int delay_us) {
100 VideoFrame frame(I420Buffer::Create(width, height),
101 webrtc::kVideoRotation_0, 0);
102 uint32_t timestamp = 0;
103 while (num_frames-- > 0) {
104 frame.set_timestamp(timestamp);
105 overuse_detector_->FrameCaptured(frame, rtc::TimeMicros());
106 clock_.AdvanceTimeMicros(delay_us);
107 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros());
108 clock_.AdvanceTimeMicros(interval_us - delay_us);
109 timestamp += interval_us * 90 / 1000;
110 }
111 }
112
ForceUpdate(int width,int height)113 void ForceUpdate(int width, int height) {
114 // Insert one frame, wait a second and then put in another to force update
115 // the usage. From the tests where these are used, adding another sample
116 // doesn't affect the expected outcome (this is mainly to check initial
117 // values and whether the overuse detector has been reset or not).
118 InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec,
119 width, height, kFrameIntervalUs);
120 }
TriggerOveruse(int num_times)121 void TriggerOveruse(int num_times) {
122 const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
123 for (int i = 0; i < num_times; ++i) {
124 InsertAndSendFramesWithInterval(
125 1000, kFrameIntervalUs, kWidth, kHeight, kDelayUs);
126 overuse_detector_->CheckForOveruse();
127 }
128 }
129
TriggerUnderuse()130 void TriggerUnderuse() {
131 const int kDelayUs1 = 5000;
132 const int kDelayUs2 = 6000;
133 InsertAndSendFramesWithInterval(
134 1300, kFrameIntervalUs, kWidth, kHeight, kDelayUs1);
135 InsertAndSendFramesWithInterval(
136 1, kFrameIntervalUs, kWidth, kHeight, kDelayUs2);
137 overuse_detector_->CheckForOveruse();
138 }
139
UsagePercent()140 int UsagePercent() { return metrics_.encode_usage_percent; }
141
OveruseProcessingTimeLimitForFramerate(int fps) const142 int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
143 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
144 int64_t max_processing_time_us =
145 (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
146 return max_processing_time_us;
147 }
148
UnderuseProcessingTimeLimitForFramerate(int fps) const149 int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
150 int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
151 int64_t max_processing_time_us =
152 (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
153 return max_processing_time_us;
154 }
155
156 CpuOveruseOptions options_;
157 rtc::ScopedFakeClock clock_;
158 std::unique_ptr<MockCpuOveruseObserver> observer_;
159 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
160 CpuOveruseMetrics metrics_;
161
162 static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
163 };
164
165
166 // UsagePercent() > high_encode_usage_threshold_percent => overuse.
167 // UsagePercent() < low_encode_usage_threshold_percent => underuse.
TEST_F(OveruseFrameDetectorTest,TriggerOveruse)168 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
169 // usage > high => overuse
170 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
171 TriggerOveruse(options_.high_threshold_consecutive_count);
172 }
173
TEST_F(OveruseFrameDetectorTest,OveruseAndRecover)174 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
175 // usage > high => overuse
176 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
177 TriggerOveruse(options_.high_threshold_consecutive_count);
178 // usage < low => underuse
179 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(testing::AtLeast(1));
180 TriggerUnderuse();
181 }
182
TEST_F(OveruseFrameDetectorTest,OveruseAndRecoverWithNoObserver)183 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) {
184 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
185 options_, nullptr, nullptr, this));
186 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
187 TriggerOveruse(options_.high_threshold_consecutive_count);
188 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(0);
189 TriggerUnderuse();
190 }
191
TEST_F(OveruseFrameDetectorTest,DoubleOveruseAndRecover)192 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
193 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(2);
194 TriggerOveruse(options_.high_threshold_consecutive_count);
195 TriggerOveruse(options_.high_threshold_consecutive_count);
196 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(testing::AtLeast(1));
197 TriggerUnderuse();
198 }
199
TEST_F(OveruseFrameDetectorTest,TriggerUnderuseWithMinProcessCount)200 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
201 const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
202 options_.min_process_count = 1;
203 CpuOveruseObserverImpl overuse_observer;
204 overuse_detector_.reset(new OveruseFrameDetectorUnderTest(
205 options_, &overuse_observer, nullptr, this));
206 InsertAndSendFramesWithInterval(
207 1200, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
208 overuse_detector_->CheckForOveruse();
209 EXPECT_EQ(0, overuse_observer.normaluse_);
210 clock_.AdvanceTimeMicros(kProcessIntervalUs);
211 overuse_detector_->CheckForOveruse();
212 EXPECT_EQ(1, overuse_observer.normaluse_);
213 }
214
TEST_F(OveruseFrameDetectorTest,ConstantOveruseGivesNoNormalUsage)215 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
216 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(0);
217 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(64);
218 for (size_t i = 0; i < 64; ++i) {
219 TriggerOveruse(options_.high_threshold_consecutive_count);
220 }
221 }
222
TEST_F(OveruseFrameDetectorTest,ConsecutiveCountTriggersOveruse)223 TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
224 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
225 options_.high_threshold_consecutive_count = 2;
226 ReinitializeOveruseDetector();
227 TriggerOveruse(2);
228 }
229
TEST_F(OveruseFrameDetectorTest,IncorrectConsecutiveCountTriggersNoOveruse)230 TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
231 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
232 options_.high_threshold_consecutive_count = 2;
233 ReinitializeOveruseDetector();
234 TriggerOveruse(1);
235 }
236
TEST_F(OveruseFrameDetectorTest,ProcessingUsage)237 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
238 InsertAndSendFramesWithInterval(
239 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
240 EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
241 }
242
TEST_F(OveruseFrameDetectorTest,ResetAfterResolutionChange)243 TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
244 ForceUpdate(kWidth, kHeight);
245 EXPECT_EQ(InitialUsage(), UsagePercent());
246 InsertAndSendFramesWithInterval(
247 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
248 EXPECT_NE(InitialUsage(), UsagePercent());
249 // Verify reset (with new width/height).
250 ForceUpdate(kWidth, kHeight + 1);
251 EXPECT_EQ(InitialUsage(), UsagePercent());
252 }
253
TEST_F(OveruseFrameDetectorTest,ResetAfterFrameTimeout)254 TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
255 ForceUpdate(kWidth, kHeight);
256 EXPECT_EQ(InitialUsage(), UsagePercent());
257 InsertAndSendFramesWithInterval(
258 1000, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
259 EXPECT_NE(InitialUsage(), UsagePercent());
260 InsertAndSendFramesWithInterval(
261 2, options_.frame_timeout_interval_ms *
262 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
263 EXPECT_NE(InitialUsage(), UsagePercent());
264 // Verify reset.
265 InsertAndSendFramesWithInterval(
266 2, (options_.frame_timeout_interval_ms + 1) *
267 rtc::kNumMicrosecsPerMillisec, kWidth, kHeight, kProcessTimeUs);
268 ForceUpdate(kWidth, kHeight);
269 EXPECT_EQ(InitialUsage(), UsagePercent());
270 }
271
TEST_F(OveruseFrameDetectorTest,MinFrameSamplesBeforeUpdating)272 TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
273 options_.min_frame_samples = 40;
274 ReinitializeOveruseDetector();
275 InsertAndSendFramesWithInterval(
276 40, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
277 EXPECT_EQ(InitialUsage(), UsagePercent());
278 // Pass time far enough to digest all previous samples.
279 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
280 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
281 kProcessTimeUs);
282 // The last sample has not been processed here.
283 EXPECT_EQ(InitialUsage(), UsagePercent());
284
285 // Pass time far enough to digest all previous samples, 41 in total.
286 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec);
287 InsertAndSendFramesWithInterval(
288 1, kFrameIntervalUs, kWidth, kHeight, kProcessTimeUs);
289 EXPECT_NE(InitialUsage(), UsagePercent());
290 }
291
TEST_F(OveruseFrameDetectorTest,InitialProcessingUsage)292 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
293 ForceUpdate(kWidth, kHeight);
294 EXPECT_EQ(InitialUsage(), UsagePercent());
295 }
296
TEST_F(OveruseFrameDetectorTest,MeasuresMultipleConcurrentSamples)297 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
298 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_))
299 .Times(testing::AtLeast(1));
300 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
301 static const size_t kNumFramesEncodingDelay = 3;
302 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
303 webrtc::kVideoRotation_0, 0);
304 for (size_t i = 0; i < 1000; ++i) {
305 // Unique timestamps.
306 frame.set_timestamp(static_cast<uint32_t>(i));
307 overuse_detector_->FrameCaptured(frame, rtc::TimeMicros());
308 clock_.AdvanceTimeMicros(kIntervalUs);
309 if (i > kNumFramesEncodingDelay) {
310 overuse_detector_->FrameSent(
311 static_cast<uint32_t>(i - kNumFramesEncodingDelay),
312 rtc::TimeMicros());
313 }
314 overuse_detector_->CheckForOveruse();
315 }
316 }
317
TEST_F(OveruseFrameDetectorTest,UpdatesExistingSamples)318 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
319 // >85% encoding time should trigger overuse.
320 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_))
321 .Times(testing::AtLeast(1));
322 static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
323 static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
324 VideoFrame frame(I420Buffer::Create(kWidth, kHeight),
325 webrtc::kVideoRotation_0, 0);
326 uint32_t timestamp = 0;
327 for (size_t i = 0; i < 1000; ++i) {
328 frame.set_timestamp(timestamp);
329 overuse_detector_->FrameCaptured(frame, rtc::TimeMicros());
330 // Encode and send first parts almost instantly.
331 clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec);
332 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros());
333 // Encode heavier part, resulting in >85% usage total.
334 clock_.AdvanceTimeMicros(kDelayUs - rtc::kNumMicrosecsPerMillisec);
335 overuse_detector_->FrameSent(timestamp, rtc::TimeMicros());
336 clock_.AdvanceTimeMicros(kIntervalUs - kDelayUs);
337 timestamp += kIntervalUs * 90 / 1000;
338 overuse_detector_->CheckForOveruse();
339 }
340 }
341
TEST_F(OveruseFrameDetectorTest,RunOnTqNormalUsage)342 TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
343 rtc::TaskQueue queue("OveruseFrameDetectorTestQueue");
344
345 rtc::Event event(false, false);
346 queue.PostTask([this, &event] {
347 overuse_detector_->StartCheckForOveruse();
348 event.Set();
349 });
350 event.Wait(rtc::Event::kForever);
351
352 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
353 // set |event| to end the test.
354 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_))
355 .WillOnce(InvokeWithoutArgs([this, &event] {
356 overuse_detector_->StopCheckForOveruse();
357 event.Set();
358 }));
359
360 queue.PostTask([this] {
361 const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
362 const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
363 InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
364 kDelayUs1);
365 InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
366 kDelayUs2);
367 });
368
369 EXPECT_TRUE(event.Wait(10000));
370 }
371
TEST_F(OveruseFrameDetectorTest,MaxIntervalScalesWithFramerate)372 TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
373 const int kCapturerMaxFrameRate = 30;
374 const int kEncodeMaxFrameRate = 20; // Maximum fps the encoder can sustain.
375
376 // Trigger overuse.
377 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
378 // Processing time just below over use limit given kEncodeMaxFrameRate.
379 int64_t processing_time_us =
380 (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
381 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
382 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
383 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
384 processing_time_us);
385 overuse_detector_->CheckForOveruse();
386 }
387
388 // Simulate frame rate reduction and normal usage.
389 frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
390 overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
391 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
392 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
393 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
394 processing_time_us);
395 overuse_detector_->CheckForOveruse();
396 }
397
398 // Reduce processing time to trigger underuse.
399 processing_time_us =
400 (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
401 EXPECT_CALL(*(observer_.get()), AdaptUp(reason_)).Times(1);
402 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
403 processing_time_us);
404 overuse_detector_->CheckForOveruse();
405 }
406
TEST_F(OveruseFrameDetectorTest,RespectsMinFramerate)407 TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
408 const int kMinFrameRate = 7; // Minimum fps allowed by current detector impl.
409 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
410
411 // Normal usage just at the limit.
412 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
413 // Processing time just below over use limit given kEncodeMaxFrameRate.
414 int64_t processing_time_us =
415 (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
416 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
417 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
418 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
419 processing_time_us);
420 overuse_detector_->CheckForOveruse();
421 }
422
423 // Over the limit to overuse.
424 processing_time_us =
425 (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
426 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
427 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
428 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
429 processing_time_us);
430 overuse_detector_->CheckForOveruse();
431 }
432
433 // Reduce input frame rate. Should still trigger overuse.
434 overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
435 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
436 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
437 InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
438 processing_time_us);
439 overuse_detector_->CheckForOveruse();
440 }
441 }
442
TEST_F(OveruseFrameDetectorTest,LimitsMaxFrameInterval)443 TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
444 const int kMaxFrameRate = 20;
445 overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
446 int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
447 // Maximum frame interval allowed is 35% above ideal.
448 int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
449 // Maximum processing time, without triggering overuse, allowed with the above
450 // frame interval.
451 int64_t max_processing_time_us =
452 (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
453 100;
454
455 // Processing time just below overuse limit given kMaxFrameRate.
456 int64_t processing_time_us = (98 * max_processing_time_us) / 100;
457 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(0);
458 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
459 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
460 kHeight, processing_time_us);
461 overuse_detector_->CheckForOveruse();
462 }
463
464 // Go above limit, trigger overuse.
465 processing_time_us = (102 * max_processing_time_us) / 100;
466 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
467 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
468 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
469 kHeight, processing_time_us);
470 overuse_detector_->CheckForOveruse();
471 }
472
473 // Increase frame interval, should still trigger overuse.
474 max_frame_interval_us *= 2;
475 EXPECT_CALL(*(observer_.get()), AdaptDown(reason_)).Times(1);
476 for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
477 InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
478 kHeight, processing_time_us);
479 overuse_detector_->CheckForOveruse();
480 }
481 }
482
483 } // namespace webrtc
484