1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/capture/content/video_capture_oracle.h"
7 #include "base/strings/stringprintf.h"
8 #include "testing/gtest/include/gtest/gtest.h"
14 base::TimeTicks
InitialTestTimeTicks() {
15 return base::TimeTicks() + base::TimeDelta::FromSeconds(1);
18 base::TimeDelta
Get30HzPeriod() {
19 return base::TimeDelta::FromSeconds(1) / 30;
22 gfx::Size
Get1080pSize() {
23 return gfx::Size(1920, 1080);
26 gfx::Size
Get720pSize() {
27 return gfx::Size(1280, 720);
30 gfx::Size
Get360pSize() {
31 return gfx::Size(640, 360);
36 // Tests that VideoCaptureOracle filters out events whose timestamps are
38 TEST(VideoCaptureOracleTest
, EnforcesEventTimeMonotonicity
) {
39 const gfx::Rect
damage_rect(Get720pSize());
40 const base::TimeDelta event_increment
= Get30HzPeriod() * 2;
42 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
43 media::RESOLUTION_POLICY_FIXED_RESOLUTION
, false);
45 base::TimeTicks t
= InitialTestTimeTicks();
46 for (int i
= 0; i
< 10; ++i
) {
48 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
49 VideoCaptureOracle::kCompositorUpdate
, damage_rect
, t
));
52 base::TimeTicks furthest_event_time
= t
;
53 for (int i
= 0; i
< 10; ++i
) {
55 ASSERT_FALSE(oracle
.ObserveEventAndDecideCapture(
56 VideoCaptureOracle::kCompositorUpdate
, damage_rect
, t
));
59 t
= furthest_event_time
;
60 for (int i
= 0; i
< 10; ++i
) {
62 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
63 VideoCaptureOracle::kCompositorUpdate
, damage_rect
, t
));
67 // Tests that VideoCaptureOracle is enforcing the requirement that
68 // successfully captured frames are delivered in order. Otherwise, downstream
69 // consumers could be tripped-up by out-of-order frames or frame timestamps.
70 TEST(VideoCaptureOracleTest
, EnforcesFramesDeliveredInOrder
) {
71 const gfx::Rect
damage_rect(Get720pSize());
72 const base::TimeDelta event_increment
= Get30HzPeriod() * 2;
74 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
75 media::RESOLUTION_POLICY_FIXED_RESOLUTION
, false);
77 // Most basic scenario: Frames delivered one at a time, with no additional
78 // captures in-between deliveries.
79 base::TimeTicks t
= InitialTestTimeTicks();
80 int last_frame_number
;
81 base::TimeTicks ignored
;
82 for (int i
= 0; i
< 10; ++i
) {
84 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
85 VideoCaptureOracle::kCompositorUpdate
, damage_rect
, t
));
86 last_frame_number
= oracle
.RecordCapture(0.0);
87 ASSERT_TRUE(oracle
.CompleteCapture(last_frame_number
, true, &ignored
));
90 // Basic pipelined scenario: More than one frame in-flight at delivery points.
91 for (int i
= 0; i
< 50; ++i
) {
92 const int num_in_flight
= 1 + i
% 3;
93 for (int j
= 0; j
< num_in_flight
; ++j
) {
95 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
96 VideoCaptureOracle::kCompositorUpdate
, damage_rect
, t
));
97 last_frame_number
= oracle
.RecordCapture(0.0);
99 for (int j
= num_in_flight
- 1; j
>= 0; --j
) {
101 oracle
.CompleteCapture(last_frame_number
- j
, true, &ignored
));
105 // Pipelined scenario with successful out-of-order delivery attempts
107 for (int i
= 0; i
< 50; ++i
) {
108 const int num_in_flight
= 1 + i
% 3;
109 for (int j
= 0; j
< num_in_flight
; ++j
) {
110 t
+= event_increment
;
111 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
112 VideoCaptureOracle::kCompositorUpdate
, damage_rect
, t
));
113 last_frame_number
= oracle
.RecordCapture(0.0);
115 ASSERT_TRUE(oracle
.CompleteCapture(last_frame_number
, true, &ignored
));
116 for (int j
= 1; j
< num_in_flight
; ++j
) {
118 oracle
.CompleteCapture(last_frame_number
- j
, true, &ignored
));
122 // Pipelined scenario with successful delivery attempts accepted after an
123 // unsuccessful out of order delivery attempt.
124 for (int i
= 0; i
< 50; ++i
) {
125 const int num_in_flight
= 1 + i
% 3;
126 for (int j
= 0; j
< num_in_flight
; ++j
) {
127 t
+= event_increment
;
128 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
129 VideoCaptureOracle::kCompositorUpdate
, damage_rect
, t
));
130 last_frame_number
= oracle
.RecordCapture(0.0);
132 // Report the last frame as an out of order failure.
133 ASSERT_FALSE(oracle
.CompleteCapture(last_frame_number
, false, &ignored
));
134 for (int j
= 1; j
< num_in_flight
- 1; ++j
) {
136 oracle
.CompleteCapture(last_frame_number
- j
, true, &ignored
));
141 // Tests that VideoCaptureOracle transitions between using its two samplers in a
142 // way that does not introduce severe jank, pauses, etc.
143 TEST(VideoCaptureOracleTest
, TransitionsSmoothlyBetweenSamplers
) {
144 const gfx::Rect
animation_damage_rect(Get720pSize());
145 const base::TimeDelta event_increment
= Get30HzPeriod() * 2;
147 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
148 media::RESOLUTION_POLICY_FIXED_RESOLUTION
, false);
150 // Run sequences of animation events and non-animation events through the
151 // oracle. As the oracle transitions between each sampler, make sure the
152 // frame timestamps won't trip-up downstream consumers.
153 base::TimeTicks t
= InitialTestTimeTicks();
154 base::TimeTicks last_frame_timestamp
;
155 for (int i
= 0; i
< 1000; ++i
) {
156 t
+= event_increment
;
158 // For every 100 events, provide 50 that will cause the
159 // AnimatedContentSampler to lock-in, followed by 50 that will cause it to
160 // lock-out (i.e., the oracle will use the SmoothEventSampler instead).
161 const bool provide_animated_content_event
=
162 (i
% 100) >= 25 && (i
% 100) < 75;
164 // Only the few events that trigger the lock-out transition should be
165 // dropped, because the AnimatedContentSampler doesn't yet realize the
166 // animation ended. Otherwise, the oracle should always decide to sample
167 // because one of its samplers says to.
168 const bool require_oracle_says_sample
= (i
% 100) < 75 || (i
% 100) >= 78;
169 const bool oracle_says_sample
= oracle
.ObserveEventAndDecideCapture(
170 VideoCaptureOracle::kCompositorUpdate
,
171 provide_animated_content_event
? animation_damage_rect
: gfx::Rect(),
173 if (require_oracle_says_sample
)
174 ASSERT_TRUE(oracle_says_sample
);
175 if (!oracle_says_sample
) {
176 ASSERT_EQ(base::TimeDelta(), oracle
.estimated_frame_duration());
179 ASSERT_LT(base::TimeDelta(), oracle
.estimated_frame_duration());
181 const int frame_number
= oracle
.RecordCapture(0.0);
183 base::TimeTicks frame_timestamp
;
184 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &frame_timestamp
));
185 ASSERT_FALSE(frame_timestamp
.is_null());
186 if (!last_frame_timestamp
.is_null()) {
187 const base::TimeDelta delta
= frame_timestamp
- last_frame_timestamp
;
188 EXPECT_LE(event_increment
.InMicroseconds(), delta
.InMicroseconds());
189 // Right after the AnimatedContentSampler lock-out transition, there were
190 // a few frames dropped, so allow a gap in the timestamps. Otherwise, the
191 // delta between frame timestamps should never be more than 2X the
192 // |event_increment|.
193 const base::TimeDelta max_acceptable_delta
=
194 (i
% 100) == 78 ? event_increment
* 5 : event_increment
* 2;
195 EXPECT_GE(max_acceptable_delta
.InMicroseconds(), delta
.InMicroseconds());
197 last_frame_timestamp
= frame_timestamp
;
201 // Tests that VideoCaptureOracle prevents timer polling from initiating
202 // simultaneous captures.
203 TEST(VideoCaptureOracleTest
, SamplesOnlyOneOverdueFrameAtATime
) {
204 const base::TimeDelta vsync_interval
= base::TimeDelta::FromSeconds(1) / 60;
205 const base::TimeDelta timer_interval
= base::TimeDelta::FromMilliseconds(
206 VideoCaptureOracle::kMinTimerPollPeriodMillis
);
208 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
209 media::RESOLUTION_POLICY_FIXED_RESOLUTION
, false);
211 // Have the oracle observe some compositor events. Simulate that each capture
212 // completes successfully.
213 base::TimeTicks t
= InitialTestTimeTicks();
214 base::TimeTicks ignored
;
215 bool did_complete_a_capture
= false;
216 for (int i
= 0; i
< 10; ++i
) {
218 if (oracle
.ObserveEventAndDecideCapture(
219 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(), t
)) {
221 oracle
.CompleteCapture(oracle
.RecordCapture(0.0), true, &ignored
));
222 did_complete_a_capture
= true;
225 ASSERT_TRUE(did_complete_a_capture
);
227 // Start one more compositor-based capture, but do not notify of completion
229 for (int i
= 0; i
<= 10; ++i
) {
230 ASSERT_GT(10, i
) << "BUG: Seems like it'll never happen!";
232 if (oracle
.ObserveEventAndDecideCapture(
233 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(), t
)) {
237 int frame_number
= oracle
.RecordCapture(0.0);
239 // Stop providing the compositor events and start providing timer polling
240 // events. No overdue samplings should be recommended because of the
241 // not-yet-complete compositor-based capture.
242 for (int i
= 0; i
< 10; ++i
) {
244 ASSERT_FALSE(oracle
.ObserveEventAndDecideCapture(
245 VideoCaptureOracle::kTimerPoll
, gfx::Rect(), t
));
248 // Now, complete the oustanding compositor-based capture and continue
249 // providing timer polling events. The oracle should start recommending
251 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
252 did_complete_a_capture
= false;
253 for (int i
= 0; i
< 10; ++i
) {
255 if (oracle
.ObserveEventAndDecideCapture(VideoCaptureOracle::kTimerPoll
,
258 oracle
.CompleteCapture(oracle
.RecordCapture(0.0), true, &ignored
));
259 did_complete_a_capture
= true;
262 ASSERT_TRUE(did_complete_a_capture
);
264 // Start one more timer-based capture, but do not notify of completion yet.
265 for (int i
= 0; i
<= 10; ++i
) {
266 ASSERT_GT(10, i
) << "BUG: Seems like it'll never happen!";
268 if (oracle
.ObserveEventAndDecideCapture(VideoCaptureOracle::kTimerPoll
,
273 frame_number
= oracle
.RecordCapture(0.0);
275 // Confirm that the oracle does not recommend sampling until the outstanding
276 // timer-based capture completes.
277 for (int i
= 0; i
< 10; ++i
) {
279 ASSERT_FALSE(oracle
.ObserveEventAndDecideCapture(
280 VideoCaptureOracle::kTimerPoll
, gfx::Rect(), t
));
282 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
283 for (int i
= 0; i
<= 10; ++i
) {
284 ASSERT_GT(10, i
) << "BUG: Seems like it'll never happen!";
286 if (oracle
.ObserveEventAndDecideCapture(VideoCaptureOracle::kTimerPoll
,
293 // Tests that VideoCaptureOracle does not rapidly change proposed capture sizes,
294 // to allow both the source content and the rest of the end-to-end system to
296 TEST(VideoCaptureOracleTest
, DoesNotRapidlyChangeCaptureSize
) {
297 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
298 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT
, true);
300 // Run 30 seconds of frame captures without any source size changes.
301 base::TimeTicks t
= InitialTestTimeTicks();
302 const base::TimeDelta event_increment
= Get30HzPeriod() * 2;
303 base::TimeTicks end_t
= t
+ base::TimeDelta::FromSeconds(30);
304 for (; t
< end_t
; t
+= event_increment
) {
305 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
306 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(), t
));
307 ASSERT_EQ(Get720pSize(), oracle
.capture_size());
308 base::TimeTicks ignored
;
310 oracle
.CompleteCapture(oracle
.RecordCapture(0.0), true, &ignored
));
313 // Now run 30 seconds of frame captures with lots of random source size
314 // changes. Check that there was no more than one size change per second.
315 gfx::Size source_size
= oracle
.capture_size();
316 base::TimeTicks time_of_last_size_change
= InitialTestTimeTicks();
317 gfx::Size last_capture_size
= oracle
.capture_size();
318 end_t
= t
+ base::TimeDelta::FromSeconds(30);
319 for (; t
< end_t
; t
+= event_increment
) {
320 // Change the source size every frame to a random non-empty size.
321 const gfx::Size last_source_size
= source_size
;
322 source_size
.SetSize(((last_source_size
.width() * 11 + 12345) % 1280) + 1,
323 ((last_source_size
.height() * 11 + 12345) % 720) + 1);
324 ASSERT_NE(last_source_size
, source_size
);
325 oracle
.SetSourceSize(source_size
);
327 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
328 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(), t
));
330 if (oracle
.capture_size() != last_capture_size
) {
331 ASSERT_GE(t
- time_of_last_size_change
, base::TimeDelta::FromSeconds(1));
332 time_of_last_size_change
= t
;
333 last_capture_size
= oracle
.capture_size();
336 base::TimeTicks ignored
;
338 oracle
.CompleteCapture(oracle
.RecordCapture(0.0), true, &ignored
));
344 // Tests that VideoCaptureOracle can auto-throttle by stepping the capture size
345 // up or down. When |is_content_animating| is false, there is more
346 // aggressiveness expected in the timing of stepping upwards. If
347 // |with_consumer_feedback| is false, only buffer pool utilization varies and no
348 // consumer feedback is provided. If |with_consumer_feedback| is true, the
349 // buffer pool utilization is held constant at 25%, and the consumer utilization
351 void RunAutoThrottleTest(bool is_content_animating
,
352 bool with_consumer_feedback
) {
353 SCOPED_TRACE(::testing::Message()
354 << "RunAutoThrottleTest("
355 << "(is_content_animating=" << is_content_animating
356 << ", with_consumer_feedback=" << with_consumer_feedback
<< ")");
358 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
359 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT
, true);
361 // Run 10 seconds of frame captures with 90% utilization expect no capture
363 base::TimeTicks t
= InitialTestTimeTicks();
364 base::TimeTicks time_of_last_size_change
= t
;
365 const base::TimeDelta event_increment
= Get30HzPeriod() * 2;
366 base::TimeTicks end_t
= t
+ base::TimeDelta::FromSeconds(10);
367 for (; t
< end_t
; t
+= event_increment
) {
368 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
369 VideoCaptureOracle::kCompositorUpdate
,
370 is_content_animating
? gfx::Rect(Get720pSize()) : gfx::Rect(), t
));
371 ASSERT_EQ(Get720pSize(), oracle
.capture_size());
372 const double utilization
= 0.9;
373 const int frame_number
=
374 oracle
.RecordCapture(with_consumer_feedback
? 0.25 : utilization
);
375 base::TimeTicks ignored
;
376 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
377 if (with_consumer_feedback
)
378 oracle
.RecordConsumerFeedback(frame_number
, utilization
);
381 // Cause two downward steppings in resolution. First, indicate overload
382 // until the resolution steps down. Then, indicate a 90% utilization and
383 // expect the resolution to remain constant. Repeat.
384 for (int i
= 0; i
< 2; ++i
) {
385 const gfx::Size starting_size
= oracle
.capture_size();
386 SCOPED_TRACE(::testing::Message() << "Stepping down from "
387 << starting_size
.ToString()
390 gfx::Size stepped_down_size
;
391 end_t
= t
+ base::TimeDelta::FromSeconds(10);
392 for (; t
< end_t
; t
+= event_increment
) {
393 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
394 VideoCaptureOracle::kCompositorUpdate
,
395 is_content_animating
? gfx::Rect(Get720pSize()) : gfx::Rect(), t
));
397 if (stepped_down_size
.IsEmpty()) {
398 if (oracle
.capture_size() != starting_size
) {
399 time_of_last_size_change
= t
;
400 stepped_down_size
= oracle
.capture_size();
401 ASSERT_GT(starting_size
.width(), stepped_down_size
.width());
402 ASSERT_GT(starting_size
.height(), stepped_down_size
.height());
405 ASSERT_EQ(stepped_down_size
, oracle
.capture_size());
408 const double utilization
= stepped_down_size
.IsEmpty() ? 1.5 : 0.9;
409 const int frame_number
=
410 oracle
.RecordCapture(with_consumer_feedback
? 0.25 : utilization
);
411 base::TimeTicks ignored
;
412 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
413 if (with_consumer_feedback
)
414 oracle
.RecordConsumerFeedback(frame_number
, utilization
);
418 // Now, cause two upward steppings in resolution. First, indicate
419 // under-utilization until the resolution steps up. Then, indicate a 90%
420 // utilization and expect the resolution to remain constant. Repeat.
421 for (int i
= 0; i
< 2; ++i
) {
422 const gfx::Size starting_size
= oracle
.capture_size();
423 SCOPED_TRACE(::testing::Message() << "Stepping up from "
424 << starting_size
.ToString()
427 gfx::Size stepped_up_size
;
428 end_t
= t
+ base::TimeDelta::FromSeconds(is_content_animating
? 90 : 10);
429 for (; t
< end_t
; t
+= event_increment
) {
430 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
431 VideoCaptureOracle::kCompositorUpdate
,
432 is_content_animating
? gfx::Rect(Get720pSize()) : gfx::Rect(), t
));
434 if (stepped_up_size
.IsEmpty()) {
435 if (oracle
.capture_size() != starting_size
) {
436 // When content is animating, a much longer amount of time must pass
437 // before the capture size will step up.
438 ASSERT_LT(base::TimeDelta::FromSeconds(is_content_animating
? 15 : 1),
439 t
- time_of_last_size_change
);
440 time_of_last_size_change
= t
;
441 stepped_up_size
= oracle
.capture_size();
442 ASSERT_LT(starting_size
.width(), stepped_up_size
.width());
443 ASSERT_LT(starting_size
.height(), stepped_up_size
.height());
446 ASSERT_EQ(stepped_up_size
, oracle
.capture_size());
449 const double utilization
= stepped_up_size
.IsEmpty() ? 0.0 : 0.9;
450 const int frame_number
=
451 oracle
.RecordCapture(with_consumer_feedback
? 0.25 : utilization
);
452 base::TimeTicks ignored
;
453 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
454 if (with_consumer_feedback
)
455 oracle
.RecordConsumerFeedback(frame_number
, utilization
);
462 // Tests that VideoCaptureOracle can auto-throttle by stepping the capture size
463 // up or down, using utilization feedback signals from either the buffer pool or
464 // the consumer, and with slightly different behavior depending on whether
465 // content is animating.
466 TEST(VideoCaptureOracleTest
, AutoThrottlesBasedOnUtilizationFeedback
) {
467 RunAutoThrottleTest(false, false);
468 RunAutoThrottleTest(false, true);
469 RunAutoThrottleTest(true, false);
470 RunAutoThrottleTest(true, true);
473 // Tests that, while content is animating, VideoCaptureOracle can make frequent
474 // capture size increases only just after the source size has changed.
475 // Otherwise, capture size increases should only be made cautiously, after a
476 // long "proving period of under-utilization" has elapsed.
477 TEST(VideoCaptureOracleTest
, IncreasesFrequentlyOnlyAfterSourceSizeChange
) {
478 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
479 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT
, true);
481 // Start out the source size at 360p, so there is room to grow to the 720p
483 oracle
.SetSourceSize(Get360pSize());
485 // Run 10 seconds of frame captures with under-utilization to represent a
486 // machine that can do more, but won't because the source size is small.
487 base::TimeTicks t
= InitialTestTimeTicks();
488 const base::TimeDelta event_increment
= Get30HzPeriod() * 2;
489 base::TimeTicks end_t
= t
+ base::TimeDelta::FromSeconds(10);
490 for (; t
< end_t
; t
+= event_increment
) {
491 if (!oracle
.ObserveEventAndDecideCapture(
492 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(Get360pSize()),
496 ASSERT_EQ(Get360pSize(), oracle
.capture_size());
497 const int frame_number
= oracle
.RecordCapture(0.25);
498 base::TimeTicks ignored
;
499 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
502 // Now, set the source size to 720p, continuing to report under-utilization,
503 // and expect the capture size increases to reach a full 720p within 15
505 oracle
.SetSourceSize(Get720pSize());
506 gfx::Size last_capture_size
= oracle
.capture_size();
507 end_t
= t
+ base::TimeDelta::FromSeconds(15);
508 for (; t
< end_t
; t
+= event_increment
) {
509 if (!oracle
.ObserveEventAndDecideCapture(
510 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(Get720pSize()),
514 ASSERT_LE(last_capture_size
.width(), oracle
.capture_size().width());
515 ASSERT_LE(last_capture_size
.height(), oracle
.capture_size().height());
516 last_capture_size
= oracle
.capture_size();
517 const int frame_number
= oracle
.RecordCapture(0.25);
518 base::TimeTicks ignored
;
519 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
521 ASSERT_EQ(Get720pSize(), oracle
.capture_size());
523 // Now, change the source size again, but report over-utilization so the
524 // capture size will decrease. Once it decreases one step, report 90%
525 // utilization to achieve a steady-state.
526 oracle
.SetSourceSize(Get1080pSize());
527 gfx::Size stepped_down_size
;
528 end_t
= t
+ base::TimeDelta::FromSeconds(10);
529 for (; t
< end_t
; t
+= event_increment
) {
530 if (!oracle
.ObserveEventAndDecideCapture(
531 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(Get1080pSize()),
536 if (stepped_down_size
.IsEmpty()) {
537 if (oracle
.capture_size() != Get720pSize()) {
538 stepped_down_size
= oracle
.capture_size();
539 ASSERT_GT(Get720pSize().width(), stepped_down_size
.width());
540 ASSERT_GT(Get720pSize().height(), stepped_down_size
.height());
543 ASSERT_EQ(stepped_down_size
, oracle
.capture_size());
546 const double utilization
= stepped_down_size
.IsEmpty() ? 1.5 : 0.9;
547 const int frame_number
= oracle
.RecordCapture(utilization
);
548 base::TimeTicks ignored
;
549 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
551 ASSERT_FALSE(stepped_down_size
.IsEmpty());
553 // Now, if we report under-utilization again (without any source size change),
554 // there should be a long "proving period" before there is any increase in
555 // capture size made by the oracle.
556 const base::TimeTicks proving_period_end_time
=
557 t
+ base::TimeDelta::FromSeconds(15);
558 gfx::Size stepped_up_size
;
559 end_t
= t
+ base::TimeDelta::FromSeconds(60);
560 for (; t
< end_t
; t
+= event_increment
) {
561 if (!oracle
.ObserveEventAndDecideCapture(
562 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(Get1080pSize()),
567 if (stepped_up_size
.IsEmpty()) {
568 if (oracle
.capture_size() != stepped_down_size
) {
569 ASSERT_LT(proving_period_end_time
, t
);
570 stepped_up_size
= oracle
.capture_size();
571 ASSERT_LT(stepped_down_size
.width(), stepped_up_size
.width());
572 ASSERT_LT(stepped_down_size
.height(), stepped_up_size
.height());
575 ASSERT_EQ(stepped_up_size
, oracle
.capture_size());
578 const double utilization
= stepped_up_size
.IsEmpty() ? 0.25 : 0.9;
579 const int frame_number
= oracle
.RecordCapture(utilization
);
580 base::TimeTicks ignored
;
581 ASSERT_TRUE(oracle
.CompleteCapture(frame_number
, true, &ignored
));
583 ASSERT_FALSE(stepped_up_size
.IsEmpty());
586 // Tests that VideoCaptureOracle does not change the capture size if
587 // auto-throttling is enabled when using a fixed resolution policy.
588 TEST(VideoCaptureOracleTest
, DoesNotAutoThrottleWhenResolutionIsFixed
) {
589 VideoCaptureOracle
oracle(Get30HzPeriod(), Get720pSize(),
590 media::RESOLUTION_POLICY_FIXED_RESOLUTION
, true);
592 // Run 10 seconds of frame captures with 90% utilization expect no capture
594 base::TimeTicks t
= InitialTestTimeTicks();
595 const base::TimeDelta event_increment
= Get30HzPeriod() * 2;
596 base::TimeTicks end_t
= t
+ base::TimeDelta::FromSeconds(10);
597 for (; t
< end_t
; t
+= event_increment
) {
598 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
599 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(), t
));
600 ASSERT_EQ(Get720pSize(), oracle
.capture_size());
601 base::TimeTicks ignored
;
603 oracle
.CompleteCapture(oracle
.RecordCapture(0.9), true, &ignored
));
606 // Now run 10 seconds with overload indicated. Still, expect no capture size
608 end_t
= t
+ base::TimeDelta::FromSeconds(10);
609 for (; t
< end_t
; t
+= event_increment
) {
610 ASSERT_TRUE(oracle
.ObserveEventAndDecideCapture(
611 VideoCaptureOracle::kCompositorUpdate
, gfx::Rect(), t
));
612 ASSERT_EQ(Get720pSize(), oracle
.capture_size());
613 base::TimeTicks ignored
;
615 oracle
.CompleteCapture(oracle
.RecordCapture(2.0), true, &ignored
));