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