1 /*
2  *  Copyright (c) 2020 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 "video/adaptation/overuse_frame_detector.h"
12 
13 #include <memory>
14 
15 #include "api/video/encoded_image.h"
16 #include "api/video/i420_buffer.h"
17 #include "modules/video_coding/utility/quality_scaler.h"
18 #include "rtc_base/event.h"
19 #include "rtc_base/fake_clock.h"
20 #include "rtc_base/random.h"
21 #include "rtc_base/task_queue_for_test.h"
22 #include "test/gmock.h"
23 #include "test/gtest.h"
24 
25 namespace webrtc {
26 
27 using ::testing::_;
28 using ::testing::InvokeWithoutArgs;
29 
30 namespace {
31 const int kWidth = 640;
32 const int kHeight = 480;
33 // Corresponds to load of 15%
34 const int kFrameIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
35 const int kProcessTimeUs = 5 * rtc::kNumMicrosecsPerMillisec;
36 }  // namespace
37 
38 class MockCpuOveruseObserver : public AdaptationObserverInterface {
39  public:
MockCpuOveruseObserver()40   MockCpuOveruseObserver() {}
~MockCpuOveruseObserver()41   virtual ~MockCpuOveruseObserver() {}
42 
43   MOCK_METHOD1(AdaptUp, void(AdaptReason));
44   MOCK_METHOD1(AdaptDown, bool(AdaptReason));
45 };
46 
47 class CpuOveruseObserverImpl : public AdaptationObserverInterface {
48  public:
CpuOveruseObserverImpl()49   CpuOveruseObserverImpl() : overuse_(0), normaluse_(0) {}
~CpuOveruseObserverImpl()50   virtual ~CpuOveruseObserverImpl() {}
51 
AdaptDown(AdaptReason)52   bool AdaptDown(AdaptReason) override {
53     ++overuse_;
54     return true;
55   }
AdaptUp(AdaptReason)56   void AdaptUp(AdaptReason) override { ++normaluse_; }
57 
58   int overuse_;
59   int normaluse_;
60 };
61 
62 class OveruseFrameDetectorUnderTest : public OveruseFrameDetector {
63  public:
OveruseFrameDetectorUnderTest(CpuOveruseMetricsObserver * metrics_observer)64   explicit OveruseFrameDetectorUnderTest(
65       CpuOveruseMetricsObserver* metrics_observer)
66       : OveruseFrameDetector(metrics_observer) {}
~OveruseFrameDetectorUnderTest()67   ~OveruseFrameDetectorUnderTest() {}
68 
69   using OveruseFrameDetector::CheckForOveruse;
70   using OveruseFrameDetector::SetOptions;
71 };
72 
73 class OveruseFrameDetectorTest : public ::testing::Test,
74                                  public CpuOveruseMetricsObserver {
75  protected:
SetUp()76   void SetUp() override {
77     observer_ = &mock_observer_;
78     options_.min_process_count = 0;
79     overuse_detector_ = std::make_unique<OveruseFrameDetectorUnderTest>(this);
80     // Unfortunately, we can't call SetOptions here, since that would break
81     // single-threading requirements in the RunOnTqNormalUsage test.
82   }
83 
OnEncodedFrameTimeMeasured(int encode_time_ms,int encode_usage_percent)84   void OnEncodedFrameTimeMeasured(int encode_time_ms,
85                                   int encode_usage_percent) override {
86     encode_usage_percent_ = encode_usage_percent;
87   }
88 
InitialUsage()89   int InitialUsage() {
90     return ((options_.low_encode_usage_threshold_percent +
91              options_.high_encode_usage_threshold_percent) /
92             2.0f) +
93            0.5;
94   }
95 
InsertAndSendFramesWithInterval(int num_frames,int interval_us,int width,int height,int delay_us)96   virtual void InsertAndSendFramesWithInterval(int num_frames,
97                                                int interval_us,
98                                                int width,
99                                                int height,
100                                                int delay_us) {
101     VideoFrame frame =
102         VideoFrame::Builder()
103             .set_video_frame_buffer(I420Buffer::Create(width, height))
104             .set_rotation(webrtc::kVideoRotation_0)
105             .set_timestamp_us(0)
106             .build();
107     uint32_t timestamp = 0;
108     while (num_frames-- > 0) {
109       frame.set_timestamp(timestamp);
110       int64_t capture_time_us = rtc::TimeMicros();
111       overuse_detector_->FrameCaptured(frame, capture_time_us);
112       clock_.AdvanceTime(TimeDelta::Micros(delay_us));
113       overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
114                                    capture_time_us, delay_us);
115       clock_.AdvanceTime(TimeDelta::Micros(interval_us - delay_us));
116       timestamp += interval_us * 90 / 1000;
117     }
118   }
119 
InsertAndSendSimulcastFramesWithInterval(int num_frames,int interval_us,int width,int height,rtc::ArrayView<const int> delays_us)120   virtual void InsertAndSendSimulcastFramesWithInterval(
121       int num_frames,
122       int interval_us,
123       int width,
124       int height,
125       // One element per layer
126       rtc::ArrayView<const int> delays_us) {
127     VideoFrame frame =
128         VideoFrame::Builder()
129             .set_video_frame_buffer(I420Buffer::Create(width, height))
130             .set_rotation(webrtc::kVideoRotation_0)
131             .set_timestamp_us(0)
132             .build();
133     uint32_t timestamp = 0;
134     while (num_frames-- > 0) {
135       frame.set_timestamp(timestamp);
136       int64_t capture_time_us = rtc::TimeMicros();
137       overuse_detector_->FrameCaptured(frame, capture_time_us);
138       int max_delay_us = 0;
139       for (int delay_us : delays_us) {
140         if (delay_us > max_delay_us) {
141           clock_.AdvanceTime(TimeDelta::Micros(delay_us - max_delay_us));
142           max_delay_us = delay_us;
143         }
144 
145         overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
146                                      capture_time_us, delay_us);
147       }
148       overuse_detector_->CheckForOveruse(observer_);
149       clock_.AdvanceTime(TimeDelta::Micros(interval_us - max_delay_us));
150       timestamp += interval_us * 90 / 1000;
151     }
152   }
153 
InsertAndSendFramesWithRandomInterval(int num_frames,int min_interval_us,int max_interval_us,int width,int height,int delay_us)154   virtual void InsertAndSendFramesWithRandomInterval(int num_frames,
155                                                      int min_interval_us,
156                                                      int max_interval_us,
157                                                      int width,
158                                                      int height,
159                                                      int delay_us) {
160     webrtc::Random random(17);
161 
162     VideoFrame frame =
163         VideoFrame::Builder()
164             .set_video_frame_buffer(I420Buffer::Create(width, height))
165             .set_rotation(webrtc::kVideoRotation_0)
166             .set_timestamp_us(0)
167             .build();
168     uint32_t timestamp = 0;
169     while (num_frames-- > 0) {
170       frame.set_timestamp(timestamp);
171       int interval_us = random.Rand(min_interval_us, max_interval_us);
172       int64_t capture_time_us = rtc::TimeMicros();
173       overuse_detector_->FrameCaptured(frame, capture_time_us);
174       clock_.AdvanceTime(TimeDelta::Micros(delay_us));
175       overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(),
176                                    capture_time_us,
177                                    absl::optional<int>(delay_us));
178 
179       overuse_detector_->CheckForOveruse(observer_);
180       // Avoid turning clock backwards.
181       if (interval_us > delay_us)
182         clock_.AdvanceTime(TimeDelta::Micros(interval_us - delay_us));
183 
184       timestamp += interval_us * 90 / 1000;
185     }
186   }
187 
ForceUpdate(int width,int height)188   virtual void ForceUpdate(int width, int height) {
189     // Insert one frame, wait a second and then put in another to force update
190     // the usage. From the tests where these are used, adding another sample
191     // doesn't affect the expected outcome (this is mainly to check initial
192     // values and whether the overuse detector has been reset or not).
193     InsertAndSendFramesWithInterval(2, rtc::kNumMicrosecsPerSec, width, height,
194                                     kFrameIntervalUs);
195   }
TriggerOveruse(int num_times)196   void TriggerOveruse(int num_times) {
197     const int kDelayUs = 32 * rtc::kNumMicrosecsPerMillisec;
198     for (int i = 0; i < num_times; ++i) {
199       InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
200                                       kDelayUs);
201       overuse_detector_->CheckForOveruse(observer_);
202     }
203   }
204 
TriggerUnderuse()205   void TriggerUnderuse() {
206     const int kDelayUs1 = 5000;
207     const int kDelayUs2 = 6000;
208     InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
209                                     kDelayUs1);
210     InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
211                                     kDelayUs2);
212     overuse_detector_->CheckForOveruse(observer_);
213   }
214 
UsagePercent()215   int UsagePercent() { return encode_usage_percent_; }
216 
OveruseProcessingTimeLimitForFramerate(int fps) const217   int64_t OveruseProcessingTimeLimitForFramerate(int fps) const {
218     int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
219     int64_t max_processing_time_us =
220         (frame_interval * options_.high_encode_usage_threshold_percent) / 100;
221     return max_processing_time_us;
222   }
223 
UnderuseProcessingTimeLimitForFramerate(int fps) const224   int64_t UnderuseProcessingTimeLimitForFramerate(int fps) const {
225     int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps;
226     int64_t max_processing_time_us =
227         (frame_interval * options_.low_encode_usage_threshold_percent) / 100;
228     return max_processing_time_us;
229   }
230 
231   CpuOveruseOptions options_;
232   rtc::ScopedFakeClock clock_;
233   MockCpuOveruseObserver mock_observer_;
234   AdaptationObserverInterface* observer_;
235   std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_;
236   int encode_usage_percent_ = -1;
237 
238   static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
239 };
240 
241 // UsagePercent() > high_encode_usage_threshold_percent => overuse.
242 // UsagePercent() < low_encode_usage_threshold_percent => underuse.
TEST_F(OveruseFrameDetectorTest,TriggerOveruse)243 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) {
244   // usage > high => overuse
245   overuse_detector_->SetOptions(options_);
246   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
247   TriggerOveruse(options_.high_threshold_consecutive_count);
248 }
249 
TEST_F(OveruseFrameDetectorTest,OveruseAndRecover)250 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) {
251   // usage > high => overuse
252   overuse_detector_->SetOptions(options_);
253   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
254   TriggerOveruse(options_.high_threshold_consecutive_count);
255   // usage < low => underuse
256   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
257   TriggerUnderuse();
258 }
259 
TEST_F(OveruseFrameDetectorTest,DoubleOveruseAndRecover)260 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
261   overuse_detector_->SetOptions(options_);
262   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
263   TriggerOveruse(options_.high_threshold_consecutive_count);
264   TriggerOveruse(options_.high_threshold_consecutive_count);
265   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
266   TriggerUnderuse();
267 }
268 
TEST_F(OveruseFrameDetectorTest,TriggerUnderuseWithMinProcessCount)269 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
270   const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
271   options_.min_process_count = 1;
272   CpuOveruseObserverImpl overuse_observer;
273   observer_ = nullptr;
274   overuse_detector_->SetOptions(options_);
275   InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
276                                   kProcessTimeUs);
277   overuse_detector_->CheckForOveruse(&overuse_observer);
278   EXPECT_EQ(0, overuse_observer.normaluse_);
279   clock_.AdvanceTime(TimeDelta::Micros(kProcessIntervalUs));
280   overuse_detector_->CheckForOveruse(&overuse_observer);
281   EXPECT_EQ(1, overuse_observer.normaluse_);
282 }
283 
TEST_F(OveruseFrameDetectorTest,ConstantOveruseGivesNoNormalUsage)284 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
285   overuse_detector_->SetOptions(options_);
286   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
287   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
288   for (size_t i = 0; i < 64; ++i) {
289     TriggerOveruse(options_.high_threshold_consecutive_count);
290   }
291 }
292 
TEST_F(OveruseFrameDetectorTest,ConsecutiveCountTriggersOveruse)293 TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) {
294   overuse_detector_->SetOptions(options_);
295   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
296   options_.high_threshold_consecutive_count = 2;
297   overuse_detector_->SetOptions(options_);
298   TriggerOveruse(2);
299 }
300 
TEST_F(OveruseFrameDetectorTest,IncorrectConsecutiveCountTriggersNoOveruse)301 TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) {
302   overuse_detector_->SetOptions(options_);
303   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
304   options_.high_threshold_consecutive_count = 2;
305   overuse_detector_->SetOptions(options_);
306   TriggerOveruse(1);
307 }
308 
TEST_F(OveruseFrameDetectorTest,ProcessingUsage)309 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
310   overuse_detector_->SetOptions(options_);
311   InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
312                                   kProcessTimeUs);
313   EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
314 }
315 
TEST_F(OveruseFrameDetectorTest,ResetAfterResolutionChange)316 TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
317   overuse_detector_->SetOptions(options_);
318   ForceUpdate(kWidth, kHeight);
319   EXPECT_EQ(InitialUsage(), UsagePercent());
320   InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
321                                   kProcessTimeUs);
322   EXPECT_NE(InitialUsage(), UsagePercent());
323   // Verify reset (with new width/height).
324   ForceUpdate(kWidth, kHeight + 1);
325   EXPECT_EQ(InitialUsage(), UsagePercent());
326 }
327 
TEST_F(OveruseFrameDetectorTest,ResetAfterFrameTimeout)328 TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
329   overuse_detector_->SetOptions(options_);
330   ForceUpdate(kWidth, kHeight);
331   EXPECT_EQ(InitialUsage(), UsagePercent());
332   InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
333                                   kProcessTimeUs);
334   EXPECT_NE(InitialUsage(), UsagePercent());
335   InsertAndSendFramesWithInterval(
336       2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
337       kWidth, kHeight, kProcessTimeUs);
338   EXPECT_NE(InitialUsage(), UsagePercent());
339   // Verify reset.
340   InsertAndSendFramesWithInterval(
341       2,
342       (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
343       kWidth, kHeight, kProcessTimeUs);
344   ForceUpdate(kWidth, kHeight);
345   EXPECT_EQ(InitialUsage(), UsagePercent());
346 }
347 
TEST_F(OveruseFrameDetectorTest,MinFrameSamplesBeforeUpdating)348 TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
349   options_.min_frame_samples = 40;
350   overuse_detector_->SetOptions(options_);
351   InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
352                                   kProcessTimeUs);
353   EXPECT_EQ(InitialUsage(), UsagePercent());
354   // Pass time far enough to digest all previous samples.
355   clock_.AdvanceTime(TimeDelta::Seconds(1));
356   InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
357                                   kProcessTimeUs);
358   // The last sample has not been processed here.
359   EXPECT_EQ(InitialUsage(), UsagePercent());
360 
361   // Pass time far enough to digest all previous samples, 41 in total.
362   clock_.AdvanceTime(TimeDelta::Seconds(1));
363   InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
364                                   kProcessTimeUs);
365   EXPECT_NE(InitialUsage(), UsagePercent());
366 }
367 
TEST_F(OveruseFrameDetectorTest,InitialProcessingUsage)368 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
369   overuse_detector_->SetOptions(options_);
370   ForceUpdate(kWidth, kHeight);
371   EXPECT_EQ(InitialUsage(), UsagePercent());
372 }
373 
TEST_F(OveruseFrameDetectorTest,MeasuresMultipleConcurrentSamples)374 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
375   overuse_detector_->SetOptions(options_);
376   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
377   static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
378   static const size_t kNumFramesEncodingDelay = 3;
379   VideoFrame frame =
380       VideoFrame::Builder()
381           .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
382           .set_rotation(webrtc::kVideoRotation_0)
383           .set_timestamp_us(0)
384           .build();
385   for (size_t i = 0; i < 1000; ++i) {
386     // Unique timestamps.
387     frame.set_timestamp(static_cast<uint32_t>(i));
388     int64_t capture_time_us = rtc::TimeMicros();
389     overuse_detector_->FrameCaptured(frame, capture_time_us);
390     clock_.AdvanceTime(TimeDelta::Micros(kIntervalUs));
391     if (i > kNumFramesEncodingDelay) {
392       overuse_detector_->FrameSent(
393           static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
394           capture_time_us, kIntervalUs);
395     }
396     overuse_detector_->CheckForOveruse(observer_);
397   }
398 }
399 
TEST_F(OveruseFrameDetectorTest,UpdatesExistingSamples)400 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
401   // >85% encoding time should trigger overuse.
402   overuse_detector_->SetOptions(options_);
403   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
404   static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
405   static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
406   VideoFrame frame =
407       VideoFrame::Builder()
408           .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
409           .set_rotation(webrtc::kVideoRotation_0)
410           .set_timestamp_us(0)
411           .build();
412   uint32_t timestamp = 0;
413   for (size_t i = 0; i < 1000; ++i) {
414     frame.set_timestamp(timestamp);
415     int64_t capture_time_us = rtc::TimeMicros();
416     overuse_detector_->FrameCaptured(frame, capture_time_us);
417     // Encode and send first parts almost instantly.
418     clock_.AdvanceTime(TimeDelta::Millis(1));
419     overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
420                                  rtc::kNumMicrosecsPerMillisec);
421     // Encode heavier part, resulting in >85% usage total.
422     clock_.AdvanceTime(TimeDelta::Micros(kDelayUs) - TimeDelta::Millis(1));
423     overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
424                                  kDelayUs);
425     clock_.AdvanceTime(TimeDelta::Micros(kIntervalUs - kDelayUs));
426     timestamp += kIntervalUs * 90 / 1000;
427     overuse_detector_->CheckForOveruse(observer_);
428   }
429 }
430 
TEST_F(OveruseFrameDetectorTest,RunOnTqNormalUsage)431 TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) {
432   TaskQueueForTest queue("OveruseFrameDetectorTestQueue");
433 
434   queue.SendTask(
435       [&] {
436         overuse_detector_->StartCheckForOveruse(queue.Get(), options_,
437                                                 observer_);
438       },
439       RTC_FROM_HERE);
440 
441   rtc::Event event;
442   // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
443   // set |event| to end the test.
444   EXPECT_CALL(mock_observer_, AdaptUp(reason_))
445       .WillOnce(InvokeWithoutArgs([this, &event] {
446         overuse_detector_->StopCheckForOveruse();
447         event.Set();
448       }));
449 
450   queue.PostTask([this] {
451     const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
452     const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
453     InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
454                                     kDelayUs1);
455     InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
456                                     kDelayUs2);
457   });
458 
459   EXPECT_TRUE(event.Wait(10000));
460 }
461 
TEST_F(OveruseFrameDetectorTest,MaxIntervalScalesWithFramerate)462 TEST_F(OveruseFrameDetectorTest, MaxIntervalScalesWithFramerate) {
463   const int kCapturerMaxFrameRate = 30;
464   const int kEncodeMaxFrameRate = 20;  // Maximum fps the encoder can sustain.
465 
466   overuse_detector_->SetOptions(options_);
467   // Trigger overuse.
468   int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kCapturerMaxFrameRate;
469   // Processing time just below over use limit given kEncodeMaxFrameRate.
470   int64_t processing_time_us =
471       (98 * OveruseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
472   EXPECT_CALL(mock_observer_, 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(observer_);
477   }
478 
479   // Simulate frame rate reduction and normal usage.
480   frame_interval_us = rtc::kNumMicrosecsPerSec / kEncodeMaxFrameRate;
481   overuse_detector_->OnTargetFramerateUpdated(kEncodeMaxFrameRate);
482   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
483   for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
484     InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
485                                     processing_time_us);
486     overuse_detector_->CheckForOveruse(observer_);
487   }
488 
489   // Reduce processing time to trigger underuse.
490   processing_time_us =
491       (98 * UnderuseProcessingTimeLimitForFramerate(kEncodeMaxFrameRate)) / 100;
492   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(1);
493   InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
494                                   processing_time_us);
495   overuse_detector_->CheckForOveruse(observer_);
496 }
497 
TEST_F(OveruseFrameDetectorTest,RespectsMinFramerate)498 TEST_F(OveruseFrameDetectorTest, RespectsMinFramerate) {
499   const int kMinFrameRate = 7;  // Minimum fps allowed by current detector impl.
500   overuse_detector_->SetOptions(options_);
501   overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate);
502 
503   // Normal usage just at the limit.
504   int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMinFrameRate;
505   // Processing time just below over use limit given kEncodeMaxFrameRate.
506   int64_t processing_time_us =
507       (98 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
508   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
509   for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
510     InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
511                                     processing_time_us);
512     overuse_detector_->CheckForOveruse(observer_);
513   }
514 
515   // Over the limit to overuse.
516   processing_time_us =
517       (102 * OveruseProcessingTimeLimitForFramerate(kMinFrameRate)) / 100;
518   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
519   for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
520     InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
521                                     processing_time_us);
522     overuse_detector_->CheckForOveruse(observer_);
523   }
524 
525   // Reduce input frame rate. Should still trigger overuse.
526   overuse_detector_->OnTargetFramerateUpdated(kMinFrameRate - 1);
527   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
528   for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
529     InsertAndSendFramesWithInterval(1200, frame_interval_us, kWidth, kHeight,
530                                     processing_time_us);
531     overuse_detector_->CheckForOveruse(observer_);
532   }
533 }
534 
TEST_F(OveruseFrameDetectorTest,LimitsMaxFrameInterval)535 TEST_F(OveruseFrameDetectorTest, LimitsMaxFrameInterval) {
536   const int kMaxFrameRate = 20;
537   overuse_detector_->SetOptions(options_);
538   overuse_detector_->OnTargetFramerateUpdated(kMaxFrameRate);
539   int64_t frame_interval_us = rtc::kNumMicrosecsPerSec / kMaxFrameRate;
540   // Maximum frame interval allowed is 35% above ideal.
541   int64_t max_frame_interval_us = (135 * frame_interval_us) / 100;
542   // Maximum processing time, without triggering overuse, allowed with the above
543   // frame interval.
544   int64_t max_processing_time_us =
545       (max_frame_interval_us * options_.high_encode_usage_threshold_percent) /
546       100;
547 
548   // Processing time just below overuse limit given kMaxFrameRate.
549   int64_t processing_time_us = (98 * max_processing_time_us) / 100;
550   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
551   for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
552     InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
553                                     kHeight, processing_time_us);
554     overuse_detector_->CheckForOveruse(observer_);
555   }
556 
557   // Go above limit, trigger overuse.
558   processing_time_us = (102 * max_processing_time_us) / 100;
559   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
560   for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
561     InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
562                                     kHeight, processing_time_us);
563     overuse_detector_->CheckForOveruse(observer_);
564   }
565 
566   // Increase frame interval, should still trigger overuse.
567   max_frame_interval_us *= 2;
568   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
569   for (int i = 0; i < options_.high_threshold_consecutive_count; ++i) {
570     InsertAndSendFramesWithInterval(1200, max_frame_interval_us, kWidth,
571                                     kHeight, processing_time_us);
572     overuse_detector_->CheckForOveruse(observer_);
573   }
574 }
575 
576 // Models screencast, with irregular arrival of frames which are heavy
577 // to encode.
TEST_F(OveruseFrameDetectorTest,NoOveruseForLargeRandomFrameInterval)578 TEST_F(OveruseFrameDetectorTest, NoOveruseForLargeRandomFrameInterval) {
579   // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
580   // behavior is improved in this scenario, with only AdaptUp events,
581   // and estimated load closer to the true average.
582 
583   // EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
584   // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
585   //     .Times(::testing::AtLeast(1));
586   overuse_detector_->SetOptions(options_);
587 
588   const int kNumFrames = 500;
589   const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
590 
591   const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
592   const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
593 
594   const int kTargetFramerate = 5;
595 
596   overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
597 
598   InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
599                                         kMaxIntervalUs, kWidth, kHeight,
600                                         kEncodeTimeUs);
601   // Average usage 19%. Check that estimate is in the right ball park.
602   // EXPECT_NEAR(UsagePercent(), 20, 10);
603   EXPECT_NEAR(UsagePercent(), 20, 35);
604 }
605 
606 // Models screencast, with irregular arrival of frames, often
607 // exceeding the timeout interval.
TEST_F(OveruseFrameDetectorTest,NoOveruseForRandomFrameIntervalWithReset)608 TEST_F(OveruseFrameDetectorTest, NoOveruseForRandomFrameIntervalWithReset) {
609   // TODO(bugs.webrtc.org/8504): When new estimator is relanded,
610   // behavior is improved in this scenario, and we get AdaptUp events.
611   overuse_detector_->SetOptions(options_);
612   EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
613   // EXPECT_CALL(mock_observer_, AdaptUp(reason_))
614   //     .Times(::testing::AtLeast(1));
615 
616   const int kNumFrames = 500;
617   const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
618 
619   const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
620   const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
621 
622   const int kTargetFramerate = 5;
623 
624   overuse_detector_->OnTargetFramerateUpdated(kTargetFramerate);
625 
626   InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
627                                         kMaxIntervalUs, kWidth, kHeight,
628                                         kEncodeTimeUs);
629 
630   // Average usage 6.6%, but since the frame_timeout_interval_ms is
631   // only 1500 ms, we often reset the estimate to the initial value.
632   // Check that estimate is in the right ball park.
633   EXPECT_GE(UsagePercent(), 1);
634   EXPECT_LE(UsagePercent(), InitialUsage() + 5);
635 }
636 
637 // Models simulcast, with multiple encoded frames for each input frame.
638 // Load estimate should be based on the maximum encode time per input frame.
TEST_F(OveruseFrameDetectorTest,NoOveruseForSimulcast)639 TEST_F(OveruseFrameDetectorTest, NoOveruseForSimulcast) {
640   overuse_detector_->SetOptions(options_);
641   EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
642 
643   constexpr int kNumFrames = 500;
644   constexpr int kEncodeTimesUs[] = {
645       10 * rtc::kNumMicrosecsPerMillisec,
646       8 * rtc::kNumMicrosecsPerMillisec,
647       12 * rtc::kNumMicrosecsPerMillisec,
648   };
649   constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
650 
651   InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
652                                            kHeight, kEncodeTimesUs);
653 
654   // Average usage 40%. 12 ms / 30 ms.
655   EXPECT_GE(UsagePercent(), 35);
656   EXPECT_LE(UsagePercent(), 45);
657 }
658 
659 // Tests using new cpu load estimator
660 class OveruseFrameDetectorTest2 : public OveruseFrameDetectorTest {
661  protected:
SetUp()662   void SetUp() override {
663     options_.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
664     OveruseFrameDetectorTest::SetUp();
665   }
666 
InsertAndSendFramesWithInterval(int num_frames,int interval_us,int width,int height,int delay_us)667   void InsertAndSendFramesWithInterval(int num_frames,
668                                        int interval_us,
669                                        int width,
670                                        int height,
671                                        int delay_us) override {
672     VideoFrame frame =
673         VideoFrame::Builder()
674             .set_video_frame_buffer(I420Buffer::Create(width, height))
675             .set_rotation(webrtc::kVideoRotation_0)
676             .set_timestamp_us(0)
677             .build();
678     while (num_frames-- > 0) {
679       int64_t capture_time_us = rtc::TimeMicros();
680       overuse_detector_->FrameCaptured(frame, capture_time_us /* ignored */);
681       overuse_detector_->FrameSent(0 /* ignored timestamp */,
682                                    0 /* ignored send_time_us */,
683                                    capture_time_us, delay_us);
684       clock_.AdvanceTime(TimeDelta::Micros(interval_us));
685     }
686   }
687 
InsertAndSendFramesWithRandomInterval(int num_frames,int min_interval_us,int max_interval_us,int width,int height,int delay_us)688   void InsertAndSendFramesWithRandomInterval(int num_frames,
689                                              int min_interval_us,
690                                              int max_interval_us,
691                                              int width,
692                                              int height,
693                                              int delay_us) override {
694     webrtc::Random random(17);
695 
696     VideoFrame frame =
697         VideoFrame::Builder()
698             .set_video_frame_buffer(I420Buffer::Create(width, height))
699             .set_rotation(webrtc::kVideoRotation_0)
700             .set_timestamp_us(0)
701             .build();
702     for (int i = 0; i < num_frames; i++) {
703       int interval_us = random.Rand(min_interval_us, max_interval_us);
704       int64_t capture_time_us = rtc::TimeMicros();
705       overuse_detector_->FrameCaptured(frame, capture_time_us);
706       overuse_detector_->FrameSent(0 /* ignored timestamp */,
707                                    0 /* ignored send_time_us */,
708                                    capture_time_us, delay_us);
709 
710       overuse_detector_->CheckForOveruse(observer_);
711       clock_.AdvanceTime(TimeDelta::Micros(interval_us));
712     }
713   }
714 
ForceUpdate(int width,int height)715   void ForceUpdate(int width, int height) override {
716     // This is mainly to check initial values and whether the overuse
717     // detector has been reset or not.
718     InsertAndSendFramesWithInterval(1, rtc::kNumMicrosecsPerSec, width, height,
719                                     kFrameIntervalUs);
720   }
721 };
722 
723 // UsagePercent() > high_encode_usage_threshold_percent => overuse.
724 // UsagePercent() < low_encode_usage_threshold_percent => underuse.
TEST_F(OveruseFrameDetectorTest2,TriggerOveruse)725 TEST_F(OveruseFrameDetectorTest2, TriggerOveruse) {
726   // usage > high => overuse
727   overuse_detector_->SetOptions(options_);
728   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
729   TriggerOveruse(options_.high_threshold_consecutive_count);
730 }
731 
TEST_F(OveruseFrameDetectorTest2,OveruseAndRecover)732 TEST_F(OveruseFrameDetectorTest2, OveruseAndRecover) {
733   // usage > high => overuse
734   overuse_detector_->SetOptions(options_);
735   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
736   TriggerOveruse(options_.high_threshold_consecutive_count);
737   // usage < low => underuse
738   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
739   TriggerUnderuse();
740 }
741 
TEST_F(OveruseFrameDetectorTest2,DoubleOveruseAndRecover)742 TEST_F(OveruseFrameDetectorTest2, DoubleOveruseAndRecover) {
743   overuse_detector_->SetOptions(options_);
744   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(2);
745   TriggerOveruse(options_.high_threshold_consecutive_count);
746   TriggerOveruse(options_.high_threshold_consecutive_count);
747   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
748   TriggerUnderuse();
749 }
750 
TEST_F(OveruseFrameDetectorTest2,TriggerUnderuseWithMinProcessCount)751 TEST_F(OveruseFrameDetectorTest2, TriggerUnderuseWithMinProcessCount) {
752   const int kProcessIntervalUs = 5 * rtc::kNumMicrosecsPerSec;
753   options_.min_process_count = 1;
754   CpuOveruseObserverImpl overuse_observer;
755   observer_ = nullptr;
756   overuse_detector_->SetOptions(options_);
757   InsertAndSendFramesWithInterval(1200, kFrameIntervalUs, kWidth, kHeight,
758                                   kProcessTimeUs);
759   overuse_detector_->CheckForOveruse(&overuse_observer);
760   EXPECT_EQ(0, overuse_observer.normaluse_);
761   clock_.AdvanceTime(TimeDelta::Micros(kProcessIntervalUs));
762   overuse_detector_->CheckForOveruse(&overuse_observer);
763   EXPECT_EQ(1, overuse_observer.normaluse_);
764 }
765 
TEST_F(OveruseFrameDetectorTest2,ConstantOveruseGivesNoNormalUsage)766 TEST_F(OveruseFrameDetectorTest2, ConstantOveruseGivesNoNormalUsage) {
767   overuse_detector_->SetOptions(options_);
768   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(0);
769   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(64);
770   for (size_t i = 0; i < 64; ++i) {
771     TriggerOveruse(options_.high_threshold_consecutive_count);
772   }
773 }
774 
TEST_F(OveruseFrameDetectorTest2,ConsecutiveCountTriggersOveruse)775 TEST_F(OveruseFrameDetectorTest2, ConsecutiveCountTriggersOveruse) {
776   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(1);
777   options_.high_threshold_consecutive_count = 2;
778   overuse_detector_->SetOptions(options_);
779   TriggerOveruse(2);
780 }
781 
TEST_F(OveruseFrameDetectorTest2,IncorrectConsecutiveCountTriggersNoOveruse)782 TEST_F(OveruseFrameDetectorTest2, IncorrectConsecutiveCountTriggersNoOveruse) {
783   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(0);
784   options_.high_threshold_consecutive_count = 2;
785   overuse_detector_->SetOptions(options_);
786   TriggerOveruse(1);
787 }
788 
TEST_F(OveruseFrameDetectorTest2,ProcessingUsage)789 TEST_F(OveruseFrameDetectorTest2, ProcessingUsage) {
790   overuse_detector_->SetOptions(options_);
791   InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
792                                   kProcessTimeUs);
793   EXPECT_EQ(kProcessTimeUs * 100 / kFrameIntervalUs, UsagePercent());
794 }
795 
TEST_F(OveruseFrameDetectorTest2,ResetAfterResolutionChange)796 TEST_F(OveruseFrameDetectorTest2, ResetAfterResolutionChange) {
797   overuse_detector_->SetOptions(options_);
798   ForceUpdate(kWidth, kHeight);
799   EXPECT_EQ(InitialUsage(), UsagePercent());
800   InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
801                                   kProcessTimeUs);
802   EXPECT_NE(InitialUsage(), UsagePercent());
803   // Verify reset (with new width/height).
804   ForceUpdate(kWidth, kHeight + 1);
805   EXPECT_EQ(InitialUsage(), UsagePercent());
806 }
807 
TEST_F(OveruseFrameDetectorTest2,ResetAfterFrameTimeout)808 TEST_F(OveruseFrameDetectorTest2, ResetAfterFrameTimeout) {
809   overuse_detector_->SetOptions(options_);
810   ForceUpdate(kWidth, kHeight);
811   EXPECT_EQ(InitialUsage(), UsagePercent());
812   InsertAndSendFramesWithInterval(1000, kFrameIntervalUs, kWidth, kHeight,
813                                   kProcessTimeUs);
814   EXPECT_NE(InitialUsage(), UsagePercent());
815   InsertAndSendFramesWithInterval(
816       2, options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec,
817       kWidth, kHeight, kProcessTimeUs);
818   EXPECT_NE(InitialUsage(), UsagePercent());
819   // Verify reset.
820   InsertAndSendFramesWithInterval(
821       2,
822       (options_.frame_timeout_interval_ms + 1) * rtc::kNumMicrosecsPerMillisec,
823       kWidth, kHeight, kProcessTimeUs);
824   ForceUpdate(kWidth, kHeight);
825   EXPECT_EQ(InitialUsage(), UsagePercent());
826 }
827 
TEST_F(OveruseFrameDetectorTest2,ConvergesSlowly)828 TEST_F(OveruseFrameDetectorTest2, ConvergesSlowly) {
829   overuse_detector_->SetOptions(options_);
830   InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
831                                   kProcessTimeUs);
832   // No update for the first sample.
833   EXPECT_EQ(InitialUsage(), UsagePercent());
834 
835   // Total time approximately 40 * 33ms = 1.3s, significantly less
836   // than the 5s time constant.
837   InsertAndSendFramesWithInterval(40, kFrameIntervalUs, kWidth, kHeight,
838                                   kProcessTimeUs);
839 
840   // Should have started to approach correct load of 15%, but not very far.
841   EXPECT_LT(UsagePercent(), InitialUsage());
842   EXPECT_GT(UsagePercent(), (InitialUsage() * 3 + 15) / 4);
843 
844   // Run for roughly 10s more, should now be closer.
845   InsertAndSendFramesWithInterval(300, kFrameIntervalUs, kWidth, kHeight,
846                                   kProcessTimeUs);
847   EXPECT_NEAR(UsagePercent(), 20, 5);
848 }
849 
TEST_F(OveruseFrameDetectorTest2,InitialProcessingUsage)850 TEST_F(OveruseFrameDetectorTest2, InitialProcessingUsage) {
851   overuse_detector_->SetOptions(options_);
852   ForceUpdate(kWidth, kHeight);
853   EXPECT_EQ(InitialUsage(), UsagePercent());
854 }
855 
TEST_F(OveruseFrameDetectorTest2,MeasuresMultipleConcurrentSamples)856 TEST_F(OveruseFrameDetectorTest2, MeasuresMultipleConcurrentSamples) {
857   overuse_detector_->SetOptions(options_);
858   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
859   static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
860   static const size_t kNumFramesEncodingDelay = 3;
861   VideoFrame frame =
862       VideoFrame::Builder()
863           .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
864           .set_rotation(webrtc::kVideoRotation_0)
865           .set_timestamp_us(0)
866           .build();
867   for (size_t i = 0; i < 1000; ++i) {
868     // Unique timestamps.
869     frame.set_timestamp(static_cast<uint32_t>(i));
870     int64_t capture_time_us = rtc::TimeMicros();
871     overuse_detector_->FrameCaptured(frame, capture_time_us);
872     clock_.AdvanceTime(TimeDelta::Micros(kIntervalUs));
873     if (i > kNumFramesEncodingDelay) {
874       overuse_detector_->FrameSent(
875           static_cast<uint32_t>(i - kNumFramesEncodingDelay), rtc::TimeMicros(),
876           capture_time_us, kIntervalUs);
877     }
878     overuse_detector_->CheckForOveruse(observer_);
879   }
880 }
881 
TEST_F(OveruseFrameDetectorTest2,UpdatesExistingSamples)882 TEST_F(OveruseFrameDetectorTest2, UpdatesExistingSamples) {
883   // >85% encoding time should trigger overuse.
884   overuse_detector_->SetOptions(options_);
885   EXPECT_CALL(mock_observer_, AdaptDown(reason_)).Times(::testing::AtLeast(1));
886   static const int kIntervalUs = 33 * rtc::kNumMicrosecsPerMillisec;
887   static const int kDelayUs = 30 * rtc::kNumMicrosecsPerMillisec;
888   VideoFrame frame =
889       VideoFrame::Builder()
890           .set_video_frame_buffer(I420Buffer::Create(kWidth, kHeight))
891           .set_rotation(webrtc::kVideoRotation_0)
892           .set_timestamp_us(0)
893           .build();
894   uint32_t timestamp = 0;
895   for (size_t i = 0; i < 1000; ++i) {
896     frame.set_timestamp(timestamp);
897     int64_t capture_time_us = rtc::TimeMicros();
898     overuse_detector_->FrameCaptured(frame, capture_time_us);
899     // Encode and send first parts almost instantly.
900     clock_.AdvanceTime(TimeDelta::Millis(1));
901     overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
902                                  rtc::kNumMicrosecsPerMillisec);
903     // Encode heavier part, resulting in >85% usage total.
904     clock_.AdvanceTime(TimeDelta::Micros(kDelayUs) - TimeDelta::Millis(1));
905     overuse_detector_->FrameSent(timestamp, rtc::TimeMicros(), capture_time_us,
906                                  kDelayUs);
907     clock_.AdvanceTime(TimeDelta::Micros(kIntervalUs - kDelayUs));
908     timestamp += kIntervalUs * 90 / 1000;
909     overuse_detector_->CheckForOveruse(observer_);
910   }
911 }
912 
TEST_F(OveruseFrameDetectorTest2,RunOnTqNormalUsage)913 TEST_F(OveruseFrameDetectorTest2, RunOnTqNormalUsage) {
914   TaskQueueForTest queue("OveruseFrameDetectorTestQueue");
915 
916   queue.SendTask(
917       [&] {
918         overuse_detector_->StartCheckForOveruse(queue.Get(), options_,
919                                                 observer_);
920       },
921       RTC_FROM_HERE);
922 
923   rtc::Event event;
924   // Expect NormalUsage(). When called, stop the |overuse_detector_| and then
925   // set |event| to end the test.
926   EXPECT_CALL(mock_observer_, AdaptUp(reason_))
927       .WillOnce(InvokeWithoutArgs([this, &event] {
928         overuse_detector_->StopCheckForOveruse();
929         event.Set();
930       }));
931 
932   queue.PostTask([this] {
933     const int kDelayUs1 = 5 * rtc::kNumMicrosecsPerMillisec;
934     const int kDelayUs2 = 6 * rtc::kNumMicrosecsPerMillisec;
935     InsertAndSendFramesWithInterval(1300, kFrameIntervalUs, kWidth, kHeight,
936                                     kDelayUs1);
937     InsertAndSendFramesWithInterval(1, kFrameIntervalUs, kWidth, kHeight,
938                                     kDelayUs2);
939   });
940 
941   EXPECT_TRUE(event.Wait(10000));
942 }
943 
944 // Models screencast, with irregular arrival of frames which are heavy
945 // to encode.
TEST_F(OveruseFrameDetectorTest2,NoOveruseForLargeRandomFrameInterval)946 TEST_F(OveruseFrameDetectorTest2, NoOveruseForLargeRandomFrameInterval) {
947   overuse_detector_->SetOptions(options_);
948   EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
949   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
950 
951   const int kNumFrames = 500;
952   const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
953 
954   const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
955   const int kMaxIntervalUs = 1000 * rtc::kNumMicrosecsPerMillisec;
956 
957   InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
958                                         kMaxIntervalUs, kWidth, kHeight,
959                                         kEncodeTimeUs);
960   // Average usage 19%. Check that estimate is in the right ball park.
961   EXPECT_NEAR(UsagePercent(), 20, 10);
962 }
963 
964 // Models screencast, with irregular arrival of frames, often
965 // exceeding the timeout interval.
TEST_F(OveruseFrameDetectorTest2,NoOveruseForRandomFrameIntervalWithReset)966 TEST_F(OveruseFrameDetectorTest2, NoOveruseForRandomFrameIntervalWithReset) {
967   overuse_detector_->SetOptions(options_);
968   EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
969   EXPECT_CALL(mock_observer_, AdaptUp(reason_)).Times(::testing::AtLeast(1));
970 
971   const int kNumFrames = 500;
972   const int kEncodeTimeUs = 100 * rtc::kNumMicrosecsPerMillisec;
973 
974   const int kMinIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
975   const int kMaxIntervalUs = 3000 * rtc::kNumMicrosecsPerMillisec;
976 
977   InsertAndSendFramesWithRandomInterval(kNumFrames, kMinIntervalUs,
978                                         kMaxIntervalUs, kWidth, kHeight,
979                                         kEncodeTimeUs);
980 
981   // Average usage 6.6%, but since the frame_timeout_interval_ms is
982   // only 1500 ms, we often reset the estimate to the initial value.
983   // Check that estimate is in the right ball park.
984   EXPECT_GE(UsagePercent(), 1);
985   EXPECT_LE(UsagePercent(), InitialUsage() + 5);
986 }
987 
TEST_F(OveruseFrameDetectorTest2,ToleratesOutOfOrderFrames)988 TEST_F(OveruseFrameDetectorTest2, ToleratesOutOfOrderFrames) {
989   overuse_detector_->SetOptions(options_);
990   // Represents a cpu utilization close to 100%. First input frame results in
991   // three encoded frames, and the last of those isn't finished until after the
992   // first encoded frame corresponding to the next input frame.
993   const int kEncodeTimeUs = 30 * rtc::kNumMicrosecsPerMillisec;
994   const int kCaptureTimesMs[] = {33, 33, 66, 33};
995 
996   for (int capture_time_ms : kCaptureTimesMs) {
997     overuse_detector_->FrameSent(
998         0, 0, capture_time_ms * rtc::kNumMicrosecsPerMillisec, kEncodeTimeUs);
999   }
1000   EXPECT_GE(UsagePercent(), InitialUsage());
1001 }
1002 
1003 // Models simulcast, with multiple encoded frames for each input frame.
1004 // Load estimate should be based on the maximum encode time per input frame.
TEST_F(OveruseFrameDetectorTest2,NoOveruseForSimulcast)1005 TEST_F(OveruseFrameDetectorTest2, NoOveruseForSimulcast) {
1006   overuse_detector_->SetOptions(options_);
1007   EXPECT_CALL(mock_observer_, AdaptDown(_)).Times(0);
1008 
1009   constexpr int kNumFrames = 500;
1010   constexpr int kEncodeTimesUs[] = {
1011       10 * rtc::kNumMicrosecsPerMillisec,
1012       8 * rtc::kNumMicrosecsPerMillisec,
1013       12 * rtc::kNumMicrosecsPerMillisec,
1014   };
1015   constexpr int kIntervalUs = 30 * rtc::kNumMicrosecsPerMillisec;
1016 
1017   InsertAndSendSimulcastFramesWithInterval(kNumFrames, kIntervalUs, kWidth,
1018                                            kHeight, kEncodeTimesUs);
1019 
1020   // Average usage 40%. 12 ms / 30 ms.
1021   EXPECT_GE(UsagePercent(), 35);
1022   EXPECT_LE(UsagePercent(), 45);
1023 }
1024 
1025 }  // namespace webrtc
1026