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