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