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