video_capture_oracle_unittest.cc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  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.
  4. #include "media/capture/content/video_capture_oracle.h"
  5. #include "base/time/time.h"
  6. #include "testing/gtest/include/gtest/gtest.h"
  7. #include "third_party/abseil-cpp/absl/types/optional.h"
  8. namespace media {
  9. namespace {
  10. constexpr base::TimeTicks kInitialTestTimeTicks =
  11. base::TimeTicks() + base::Seconds(1);
  12. constexpr base::TimeDelta k30HzPeriod = base::Seconds(1) / 30;
  13. constexpr gfx::Size k1080pSize = gfx::Size(1920, 1080);
  14. constexpr gfx::Size k720pSize = gfx::Size(1280, 720);
  15. constexpr gfx::Size k360pSize = gfx::Size(640, 360);
  16. constexpr gfx::Size kSmallestNonEmptySize = gfx::Size(2, 2);
  17. } // namespace
  18. // Tests that VideoCaptureOracle filters out events whose timestamps are
  19. // decreasing.
  20. TEST(VideoCaptureOracleTest, EnforcesEventTimeMonotonicity) {
  21. const gfx::Rect damage_rect(k720pSize);
  22. const base::TimeDelta event_increment = k30HzPeriod * 2;
  23. VideoCaptureOracle oracle(false);
  24. oracle.SetMinCapturePeriod(k30HzPeriod);
  25. oracle.SetCaptureSizeConstraints(k720pSize, k720pSize, false);
  26. base::TimeTicks t = kInitialTestTimeTicks;
  27. for (int i = 0; i < 10; ++i) {
  28. t += event_increment;
  29. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  30. VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
  31. }
  32. base::TimeTicks furthest_event_time = t;
  33. for (int i = 0; i < 10; ++i) {
  34. t -= event_increment;
  35. ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
  36. VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
  37. }
  38. t = furthest_event_time;
  39. for (int i = 0; i < 10; ++i) {
  40. t += event_increment;
  41. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  42. VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
  43. }
  44. }
  45. // Tests that VideoCaptureOracle is enforcing the requirement that
  46. // successfully captured frames are delivered in order. Otherwise, downstream
  47. // consumers could be tripped-up by out-of-order frames or frame timestamps.
  48. TEST(VideoCaptureOracleTest, EnforcesFramesDeliveredInOrder) {
  49. const gfx::Rect damage_rect(k720pSize);
  50. const base::TimeDelta event_increment = k30HzPeriod * 2;
  51. VideoCaptureOracle oracle(false);
  52. oracle.SetMinCapturePeriod(k30HzPeriod);
  53. oracle.SetCaptureSizeConstraints(k720pSize, k720pSize, false);
  54. // Most basic scenario: Frames delivered one at a time, with no additional
  55. // captures in-between deliveries.
  56. base::TimeTicks t = kInitialTestTimeTicks;
  57. int last_frame_number;
  58. base::TimeTicks ignored;
  59. for (int i = 0; i < 10; ++i) {
  60. t += event_increment;
  61. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  62. VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
  63. last_frame_number = oracle.next_frame_number();
  64. oracle.RecordCapture(0.0);
  65. ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored));
  66. }
  67. // Basic pipelined scenario: More than one frame in-flight at delivery points.
  68. for (int i = 0; i < 50; ++i) {
  69. const int num_in_flight = 1 + i % 3;
  70. for (int j = 0; j < num_in_flight; ++j) {
  71. t += event_increment;
  72. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  73. VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
  74. last_frame_number = oracle.next_frame_number();
  75. oracle.RecordCapture(0.0);
  76. }
  77. for (int j = num_in_flight - 1; j >= 0; --j) {
  78. ASSERT_TRUE(
  79. oracle.CompleteCapture(last_frame_number - j, true, &ignored));
  80. }
  81. }
  82. // Pipelined scenario with successful out-of-order delivery attempts
  83. // rejected.
  84. for (int i = 0; i < 50; ++i) {
  85. const int num_in_flight = 1 + i % 3;
  86. for (int j = 0; j < num_in_flight; ++j) {
  87. t += event_increment;
  88. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  89. VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
  90. last_frame_number = oracle.next_frame_number();
  91. oracle.RecordCapture(0.0);
  92. }
  93. ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored));
  94. for (int j = 1; j < num_in_flight; ++j) {
  95. ASSERT_FALSE(
  96. oracle.CompleteCapture(last_frame_number - j, true, &ignored));
  97. }
  98. }
  99. // Pipelined scenario with successful delivery attempts accepted after an
  100. // unsuccessful out of order delivery attempt.
  101. for (int i = 0; i < 50; ++i) {
  102. const int num_in_flight = 1 + i % 3;
  103. for (int j = 0; j < num_in_flight; ++j) {
  104. t += event_increment;
  105. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  106. VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
  107. last_frame_number = oracle.next_frame_number();
  108. oracle.RecordCapture(0.0);
  109. }
  110. // Report the last frame as an out of order failure.
  111. ASSERT_FALSE(oracle.CompleteCapture(last_frame_number, false, &ignored));
  112. for (int j = 1; j < num_in_flight - 1; ++j) {
  113. ASSERT_TRUE(
  114. oracle.CompleteCapture(last_frame_number - j, true, &ignored));
  115. }
  116. }
  117. }
  118. // Tests that VideoCaptureOracle transitions between using its two samplers in a
  119. // way that does not introduce severe jank, pauses, etc.
  120. TEST(VideoCaptureOracleTest, TransitionsSmoothlyBetweenSamplers) {
  121. const gfx::Rect animation_damage_rect(k720pSize);
  122. const base::TimeDelta event_increment = k30HzPeriod * 2;
  123. VideoCaptureOracle oracle(false);
  124. oracle.SetMinCapturePeriod(k30HzPeriod);
  125. oracle.SetCaptureSizeConstraints(k720pSize, k720pSize, false);
  126. // Run sequences of animation events and non-animation events through the
  127. // oracle. As the oracle transitions between each sampler, make sure the
  128. // frame timestamps won't trip-up downstream consumers.
  129. base::TimeTicks t = kInitialTestTimeTicks;
  130. base::TimeTicks last_frame_timestamp;
  131. for (int i = 0; i < 1000; ++i) {
  132. t += event_increment;
  133. // For every 100 events, provide 50 that will cause the
  134. // AnimatedContentSampler to lock-in, followed by 50 that will cause it to
  135. // lock-out (i.e., the oracle will use the SmoothEventSampler instead).
  136. const bool provide_animated_content_event =
  137. (i % 100) >= 25 && (i % 100) < 75;
  138. // Only the few events that trigger the lock-out transition should be
  139. // dropped, because the AnimatedContentSampler doesn't yet realize the
  140. // animation ended. Otherwise, the oracle should always decide to sample
  141. // because one of its samplers says to.
  142. const bool require_oracle_says_sample = (i % 100) < 75 || (i % 100) >= 78;
  143. const bool oracle_says_sample = oracle.ObserveEventAndDecideCapture(
  144. VideoCaptureOracle::kCompositorUpdate,
  145. provide_animated_content_event ? animation_damage_rect : gfx::Rect(),
  146. t);
  147. if (require_oracle_says_sample)
  148. ASSERT_TRUE(oracle_says_sample);
  149. if (!oracle_says_sample) {
  150. ASSERT_EQ(base::TimeDelta(), oracle.estimated_frame_duration());
  151. continue;
  152. }
  153. ASSERT_LT(base::TimeDelta(), oracle.estimated_frame_duration());
  154. const int frame_number = oracle.next_frame_number();
  155. oracle.RecordCapture(0.0);
  156. base::TimeTicks frame_timestamp;
  157. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &frame_timestamp));
  158. ASSERT_FALSE(frame_timestamp.is_null());
  159. if (!last_frame_timestamp.is_null()) {
  160. const base::TimeDelta delta = frame_timestamp - last_frame_timestamp;
  161. EXPECT_LE(event_increment.InMicroseconds(), delta.InMicroseconds());
  162. // Right after the AnimatedContentSampler lock-out transition, there were
  163. // a few frames dropped, so allow a gap in the timestamps. Otherwise, the
  164. // delta between frame timestamps should never be more than 2X the
  165. // |event_increment|.
  166. const base::TimeDelta max_acceptable_delta =
  167. (i % 100) == 78 ? event_increment * 5 : event_increment * 2;
  168. EXPECT_GE(max_acceptable_delta.InMicroseconds(), delta.InMicroseconds());
  169. }
  170. last_frame_timestamp = frame_timestamp;
  171. }
  172. }
  173. // Tests that VideoCaptureOracle prevents refresh request events from initiating
  174. // simultaneous captures.
  175. TEST(VideoCaptureOracleTest, SamplesAtCorrectTimesAroundRefreshRequests) {
  176. const base::TimeDelta vsync_interval = base::Seconds(1) / 60;
  177. const base::TimeDelta refresh_interval = base::Milliseconds(125); // 8 FPS
  178. VideoCaptureOracle oracle(false);
  179. oracle.SetMinCapturePeriod(k30HzPeriod);
  180. oracle.SetCaptureSizeConstraints(k720pSize, k720pSize, false);
  181. // Have the oracle observe some compositor events. Simulate that each capture
  182. // completes successfully.
  183. base::TimeTicks t = kInitialTestTimeTicks;
  184. base::TimeTicks ignored;
  185. bool did_complete_a_capture = false;
  186. for (int i = 0; i < 10; ++i) {
  187. t += vsync_interval;
  188. if (oracle.ObserveEventAndDecideCapture(
  189. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
  190. const int frame_number = oracle.next_frame_number();
  191. oracle.RecordCapture(0.0);
  192. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  193. did_complete_a_capture = true;
  194. }
  195. }
  196. ASSERT_TRUE(did_complete_a_capture);
  197. // Start one more compositor-based capture, but do not notify of completion
  198. // yet.
  199. for (int i = 0; i <= 10; ++i) {
  200. ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
  201. t += vsync_interval;
  202. if (oracle.ObserveEventAndDecideCapture(
  203. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
  204. break;
  205. }
  206. }
  207. int frame_number = oracle.next_frame_number();
  208. oracle.RecordCapture(0.0);
  209. // Stop providing the compositor events and start providing refresh request
  210. // events. No overdue samplings should be recommended because of the
  211. // not-yet-complete compositor-based capture.
  212. for (int i = 0; i < 10; ++i) {
  213. t += refresh_interval;
  214. ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
  215. VideoCaptureOracle::kRefreshRequest, gfx::Rect(), t));
  216. }
  217. // Now, complete the oustanding compositor-based capture and continue
  218. // providing refresh request events. The oracle should start recommending
  219. // sampling again.
  220. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  221. did_complete_a_capture = false;
  222. for (int i = 0; i < 10; ++i) {
  223. t += refresh_interval;
  224. if (oracle.ObserveEventAndDecideCapture(VideoCaptureOracle::kRefreshRequest,
  225. gfx::Rect(), t)) {
  226. frame_number = oracle.next_frame_number();
  227. oracle.RecordCapture(0.0);
  228. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  229. did_complete_a_capture = true;
  230. }
  231. }
  232. ASSERT_TRUE(did_complete_a_capture);
  233. // Start one more "refresh" capture, but do not notify of completion yet.
  234. for (int i = 0; i <= 10; ++i) {
  235. ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
  236. t += refresh_interval;
  237. if (oracle.ObserveEventAndDecideCapture(VideoCaptureOracle::kRefreshRequest,
  238. gfx::Rect(), t)) {
  239. break;
  240. }
  241. }
  242. frame_number = oracle.next_frame_number();
  243. oracle.RecordCapture(0.0);
  244. // Confirm that the oracle does not recommend sampling until the outstanding
  245. // "refresh" capture completes.
  246. for (int i = 0; i < 10; ++i) {
  247. t += refresh_interval;
  248. ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
  249. VideoCaptureOracle::kRefreshRequest, gfx::Rect(), t));
  250. }
  251. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  252. for (int i = 0; i <= 10; ++i) {
  253. ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
  254. t += refresh_interval;
  255. if (oracle.ObserveEventAndDecideCapture(VideoCaptureOracle::kRefreshRequest,
  256. gfx::Rect(), t)) {
  257. break;
  258. }
  259. }
  260. }
  261. // Tests that VideoCaptureOracle does not rapidly change proposed capture sizes,
  262. // to allow both the source content and the rest of the end-to-end system to
  263. // stabilize (if autothrottling is enabled).
  264. TEST(VideoCaptureOracleTest, DoesNotRapidlyChangeCaptureSize) {
  265. VideoCaptureOracle oracle(true);
  266. oracle.SetMinCapturePeriod(k30HzPeriod);
  267. oracle.SetCaptureSizeConstraints(kSmallestNonEmptySize, k720pSize, false);
  268. oracle.SetSourceSize(k1080pSize);
  269. // Run 30 seconds of frame captures without any source size changes.
  270. base::TimeTicks t = kInitialTestTimeTicks;
  271. const base::TimeDelta event_increment = k30HzPeriod * 2;
  272. base::TimeTicks end_t = t + base::Seconds(30);
  273. for (; t < end_t; t += event_increment) {
  274. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  275. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  276. ASSERT_EQ(k720pSize, oracle.capture_size());
  277. base::TimeTicks ignored;
  278. const int frame_number = oracle.next_frame_number();
  279. oracle.RecordCapture(0.0);
  280. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  281. // Must provide non-zero actionable resource_utilization to enable
  282. // auto-throttling.
  283. oracle.RecordConsumerFeedback(frame_number,
  284. media::VideoCaptureFeedback(0.1));
  285. }
  286. // Now run 30 seconds of frame captures with lots of random source size
  287. // changes. Check that there was no more than one size change per second.
  288. gfx::Size source_size = oracle.capture_size();
  289. base::TimeTicks time_of_last_size_change = kInitialTestTimeTicks;
  290. gfx::Size last_capture_size = oracle.capture_size();
  291. end_t = t + base::Seconds(30);
  292. for (; t < end_t; t += event_increment) {
  293. // Change the source size every frame to a random non-empty size.
  294. const gfx::Size last_source_size = source_size;
  295. source_size.SetSize(((last_source_size.width() * 11 + 12345) % 1280) + 1,
  296. ((last_source_size.height() * 11 + 12345) % 720) + 1);
  297. ASSERT_NE(last_source_size, source_size);
  298. oracle.SetSourceSize(source_size);
  299. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  300. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  301. if (oracle.capture_size() != last_capture_size) {
  302. ASSERT_GE(t - time_of_last_size_change, base::Seconds(1));
  303. time_of_last_size_change = t;
  304. last_capture_size = oracle.capture_size();
  305. }
  306. base::TimeTicks ignored;
  307. const int frame_number = oracle.next_frame_number();
  308. oracle.RecordCapture(0.0);
  309. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  310. oracle.RecordConsumerFeedback(frame_number,
  311. media::VideoCaptureFeedback(0.0));
  312. }
  313. }
  314. // Tests that VideoCaptureOracle allows every video frame to have a different
  315. // size if resize throttling is disabled.
  316. TEST(VideoCaptureOracleTest, ResizeThrottlingDisabled) {
  317. VideoCaptureOracle oracle(true);
  318. oracle.SetMinCapturePeriod(k30HzPeriod);
  319. oracle.SetMinSizeChangePeriod(base::TimeDelta());
  320. oracle.SetCaptureSizeConstraints(kSmallestNonEmptySize, k720pSize, false);
  321. oracle.SetSourceSize(k1080pSize);
  322. // Run 30 seconds of frame captures with lots of random source size
  323. // changes. The capture size should be different every time.
  324. base::TimeTicks t = kInitialTestTimeTicks;
  325. const base::TimeDelta event_increment = k30HzPeriod * 2;
  326. base::TimeTicks end_t = t + base::Seconds(30);
  327. gfx::Size source_size = oracle.capture_size();
  328. gfx::Size last_capture_size = oracle.capture_size();
  329. for (; t < end_t; t += event_increment) {
  330. // Change the source size every frame to a random non-empty size.
  331. const gfx::Size last_source_size = source_size;
  332. source_size.SetSize(((last_source_size.width() * 11 + 12345) % 1280) + 1,
  333. ((last_source_size.height() * 11 + 12345) % 720) + 1);
  334. ASSERT_NE(last_source_size, source_size);
  335. oracle.SetSourceSize(source_size);
  336. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  337. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  338. ASSERT_NE(last_capture_size, oracle.capture_size());
  339. last_capture_size = oracle.capture_size();
  340. base::TimeTicks ignored;
  341. const int frame_number = oracle.next_frame_number();
  342. oracle.RecordCapture(0.0);
  343. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  344. oracle.RecordConsumerFeedback(frame_number,
  345. media::VideoCaptureFeedback(0.0));
  346. }
  347. }
  348. namespace {
  349. // Tests that VideoCaptureOracle can auto-throttle by stepping the capture size
  350. // up or down. When |is_content_animating| is false, there is more
  351. // aggressiveness expected in the timing of stepping upwards. If
  352. // |with_consumer_feedback| is false, only buffer pool utilization varies and no
  353. // consumer feedback is provided. If |with_consumer_feedback| is true, the
  354. // buffer pool utilization is held constant at 25%, and the consumer utilization
  355. // feedback varies.
  356. void RunAutoThrottleTest(bool is_content_animating,
  357. bool with_consumer_feedback) {
  358. SCOPED_TRACE(::testing::Message()
  359. << "RunAutoThrottleTest("
  360. << "(is_content_animating=" << is_content_animating
  361. << ", with_consumer_feedback=" << with_consumer_feedback << ")");
  362. VideoCaptureOracle oracle(true);
  363. oracle.SetMinCapturePeriod(k30HzPeriod);
  364. oracle.SetCaptureSizeConstraints(kSmallestNonEmptySize, k720pSize, false);
  365. oracle.SetSourceSize(k1080pSize);
  366. // Run 10 seconds of frame captures with 90% utilization expect no capture
  367. // size changes.
  368. base::TimeTicks t = kInitialTestTimeTicks;
  369. base::TimeTicks time_of_last_size_change = t;
  370. const base::TimeDelta event_increment = k30HzPeriod * 2;
  371. base::TimeTicks end_t = t + base::Seconds(10);
  372. for (; t < end_t; t += event_increment) {
  373. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  374. VideoCaptureOracle::kCompositorUpdate,
  375. is_content_animating ? gfx::Rect(k720pSize) : gfx::Rect(), t));
  376. ASSERT_EQ(k720pSize, oracle.capture_size());
  377. const double utilization = 0.9;
  378. const int frame_number = oracle.next_frame_number();
  379. oracle.RecordCapture(with_consumer_feedback ? 0.25 : utilization);
  380. base::TimeTicks ignored;
  381. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  382. if (with_consumer_feedback) {
  383. oracle.RecordConsumerFeedback(frame_number,
  384. media::VideoCaptureFeedback(utilization));
  385. } else if (t == kInitialTestTimeTicks) {
  386. // Provide feedback with the very first capture to activate the capture
  387. // size auto-throttling logic. After this, no consumer feedback applies
  388. // and the buffer utilization will be the only consideration.
  389. oracle.RecordConsumerFeedback(frame_number,
  390. media::VideoCaptureFeedback(0.0));
  391. }
  392. }
  393. // Cause two downward steppings in resolution. First, indicate overload
  394. // until the resolution steps down. Then, indicate a 90% utilization and
  395. // expect the resolution to remain constant. Repeat.
  396. for (int i = 0; i < 2; ++i) {
  397. const gfx::Size starting_size = oracle.capture_size();
  398. SCOPED_TRACE(::testing::Message() << "Stepping down from "
  399. << starting_size.ToString()
  400. << ", i=" << i);
  401. gfx::Size stepped_down_size;
  402. end_t = t + base::Seconds(10);
  403. for (; t < end_t; t += event_increment) {
  404. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  405. VideoCaptureOracle::kCompositorUpdate,
  406. is_content_animating ? gfx::Rect(k720pSize) : gfx::Rect(), t));
  407. if (stepped_down_size.IsEmpty()) {
  408. if (oracle.capture_size() != starting_size) {
  409. time_of_last_size_change = t;
  410. stepped_down_size = oracle.capture_size();
  411. ASSERT_GT(starting_size.width(), stepped_down_size.width());
  412. ASSERT_GT(starting_size.height(), stepped_down_size.height());
  413. }
  414. } else {
  415. ASSERT_EQ(stepped_down_size, oracle.capture_size());
  416. }
  417. const double utilization = stepped_down_size.IsEmpty() ? 1.5 : 0.9;
  418. const int frame_number = oracle.next_frame_number();
  419. oracle.RecordCapture(with_consumer_feedback ? 0.25 : utilization);
  420. base::TimeTicks ignored;
  421. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  422. if (with_consumer_feedback)
  423. oracle.RecordConsumerFeedback(frame_number,
  424. media::VideoCaptureFeedback(utilization));
  425. }
  426. }
  427. // Now, cause two upward steppings in resolution. First, indicate
  428. // under-utilization until the resolution steps up. Then, indicate a 90%
  429. // utilization and expect the resolution to remain constant. Repeat.
  430. for (int i = 0; i < 2; ++i) {
  431. const gfx::Size starting_size = oracle.capture_size();
  432. SCOPED_TRACE(::testing::Message() << "Stepping up from "
  433. << starting_size.ToString()
  434. << ", i=" << i);
  435. gfx::Size stepped_up_size;
  436. end_t = t + base::Seconds(is_content_animating ? 90 : 10);
  437. for (; t < end_t; t += event_increment) {
  438. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  439. VideoCaptureOracle::kCompositorUpdate,
  440. is_content_animating ? gfx::Rect(k720pSize) : gfx::Rect(), t));
  441. if (stepped_up_size.IsEmpty()) {
  442. if (oracle.capture_size() != starting_size) {
  443. // When content is animating, a much longer amount of time must pass
  444. // before the capture size will step up.
  445. ASSERT_LT(base::Seconds(is_content_animating ? 15 : 1),
  446. t - time_of_last_size_change);
  447. time_of_last_size_change = t;
  448. stepped_up_size = oracle.capture_size();
  449. ASSERT_LT(starting_size.width(), stepped_up_size.width());
  450. ASSERT_LT(starting_size.height(), stepped_up_size.height());
  451. }
  452. } else {
  453. ASSERT_EQ(stepped_up_size, oracle.capture_size());
  454. }
  455. const double utilization = stepped_up_size.IsEmpty() ? 0.0 : 0.9;
  456. const int frame_number = oracle.next_frame_number();
  457. oracle.RecordCapture(with_consumer_feedback ? 0.25 : utilization);
  458. base::TimeTicks ignored;
  459. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  460. if (with_consumer_feedback)
  461. oracle.RecordConsumerFeedback(frame_number,
  462. media::VideoCaptureFeedback(utilization));
  463. }
  464. }
  465. }
  466. } // namespace
  467. // Tests that VideoCaptureOracle can auto-throttle by stepping the capture size
  468. // up or down, using utilization feedback signals from either the buffer pool or
  469. // the consumer, and with slightly different behavior depending on whether
  470. // content is animating.
  471. TEST(VideoCaptureOracleTest,
  472. AutoThrottlesCaptureSizeBasedOnUtilizationFeedback) {
  473. RunAutoThrottleTest(false, false);
  474. RunAutoThrottleTest(false, true);
  475. RunAutoThrottleTest(true, false);
  476. RunAutoThrottleTest(true, true);
  477. }
  478. // Test that the capture size is not auto-throttled if consumer feedback is
  479. // never provided. This represents VideoCaptureOracle being stuck in the
  480. // kThrottlingEnabled mode, but never having entered the kThrottlingActive mode.
  481. TEST(VideoCaptureOracleTest,
  482. DoesNotAutoThrottleCaptureSizeWithoutConsumerFeedback) {
  483. VideoCaptureOracle oracle(true);
  484. oracle.SetMinCapturePeriod(k30HzPeriod);
  485. oracle.SetCaptureSizeConstraints(kSmallestNonEmptySize, k720pSize, false);
  486. oracle.SetSourceSize(k1080pSize);
  487. // Run 10 seconds of frame captures with 90% utilization expect no capture
  488. // size changes.
  489. base::TimeTicks t = kInitialTestTimeTicks;
  490. const base::TimeDelta event_increment = k30HzPeriod * 2;
  491. base::TimeTicks end_t = t + base::Seconds(10);
  492. for (; t < end_t; t += event_increment) {
  493. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  494. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(k720pSize), t));
  495. ASSERT_EQ(k720pSize, oracle.capture_size());
  496. const int frame_number = oracle.next_frame_number();
  497. oracle.RecordCapture(0.9);
  498. base::TimeTicks ignored;
  499. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  500. // Important: Not calling oracle.RecordConsumerFeedback(frame_number, ...);
  501. }
  502. // Increase utilization to 1000%, but expect no capture size change because
  503. // there has never been any consumer feedback.
  504. const gfx::Size starting_size = oracle.capture_size();
  505. end_t = t + base::Seconds(10);
  506. for (; t < end_t; t += event_increment) {
  507. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  508. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(k720pSize), t));
  509. ASSERT_EQ(starting_size, oracle.capture_size());
  510. const int frame_number = oracle.next_frame_number();
  511. oracle.RecordCapture(10.0);
  512. base::TimeTicks ignored;
  513. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  514. }
  515. }
  516. // Tests that, while content is animating, VideoCaptureOracle can make frequent
  517. // capture size increases only just after the source size has changed.
  518. // Otherwise, capture size increases should only be made cautiously, after a
  519. // long "proving period of under-utilization" has elapsed.
  520. TEST(VideoCaptureOracleTest, IncreasesFrequentlyOnlyAfterSourceSizeChange) {
  521. VideoCaptureOracle oracle(true);
  522. oracle.SetMinCapturePeriod(k30HzPeriod);
  523. oracle.SetCaptureSizeConstraints(kSmallestNonEmptySize, k720pSize, false);
  524. // Start out the source size at 360p, so there is room to grow to the 720p
  525. // maximum.
  526. oracle.SetSourceSize(k360pSize);
  527. // Run 10 seconds of frame captures with under-utilization to represent a
  528. // machine that can do more, but won't because the source size is small.
  529. base::TimeTicks t = kInitialTestTimeTicks;
  530. const base::TimeDelta event_increment = k30HzPeriod * 2;
  531. base::TimeTicks end_t = t + base::Seconds(10);
  532. for (; t < end_t; t += event_increment) {
  533. if (!oracle.ObserveEventAndDecideCapture(
  534. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(k360pSize), t)) {
  535. continue;
  536. }
  537. ASSERT_EQ(k360pSize, oracle.capture_size());
  538. const int frame_number = oracle.next_frame_number();
  539. oracle.RecordCapture(0.25);
  540. base::TimeTicks ignored;
  541. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  542. oracle.RecordConsumerFeedback(frame_number,
  543. media::VideoCaptureFeedback(0.25));
  544. }
  545. // Now, set the source size to 720p, continuing to report under-utilization,
  546. // and expect the capture size increases to reach a full 720p within 15
  547. // seconds.
  548. oracle.SetSourceSize(k720pSize);
  549. gfx::Size last_capture_size = oracle.capture_size();
  550. end_t = t + base::Seconds(15);
  551. for (; t < end_t; t += event_increment) {
  552. if (!oracle.ObserveEventAndDecideCapture(
  553. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(k720pSize), t)) {
  554. continue;
  555. }
  556. ASSERT_LE(last_capture_size.width(), oracle.capture_size().width());
  557. ASSERT_LE(last_capture_size.height(), oracle.capture_size().height());
  558. last_capture_size = oracle.capture_size();
  559. const int frame_number = oracle.next_frame_number();
  560. oracle.RecordCapture(0.25);
  561. base::TimeTicks ignored;
  562. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  563. oracle.RecordConsumerFeedback(frame_number,
  564. media::VideoCaptureFeedback(0.25));
  565. }
  566. ASSERT_EQ(k720pSize, oracle.capture_size());
  567. // Now, change the source size again, but report over-utilization so the
  568. // capture size will decrease. Once it decreases one step, report 90%
  569. // utilization to achieve a steady-state.
  570. oracle.SetSourceSize(k1080pSize);
  571. gfx::Size stepped_down_size;
  572. end_t = t + base::Seconds(10);
  573. for (; t < end_t; t += event_increment) {
  574. if (!oracle.ObserveEventAndDecideCapture(
  575. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(k1080pSize), t)) {
  576. continue;
  577. }
  578. if (stepped_down_size.IsEmpty()) {
  579. if (oracle.capture_size() != k720pSize) {
  580. stepped_down_size = oracle.capture_size();
  581. ASSERT_GT(k720pSize.width(), stepped_down_size.width());
  582. ASSERT_GT(k720pSize.height(), stepped_down_size.height());
  583. }
  584. } else {
  585. ASSERT_EQ(stepped_down_size, oracle.capture_size());
  586. }
  587. const double utilization = stepped_down_size.IsEmpty() ? 1.5 : 0.9;
  588. const int frame_number = oracle.next_frame_number();
  589. oracle.RecordCapture(utilization);
  590. base::TimeTicks ignored;
  591. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  592. oracle.RecordConsumerFeedback(frame_number,
  593. media::VideoCaptureFeedback(utilization));
  594. }
  595. ASSERT_FALSE(stepped_down_size.IsEmpty());
  596. // Now, if we report under-utilization again (without any source size change),
  597. // there should be a long "proving period" before there is any increase in
  598. // capture size made by the oracle.
  599. const base::TimeTicks proving_period_end_time = t + base::Seconds(15);
  600. gfx::Size stepped_up_size;
  601. end_t = t + base::Seconds(60);
  602. for (; t < end_t; t += event_increment) {
  603. if (!oracle.ObserveEventAndDecideCapture(
  604. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(k1080pSize), t)) {
  605. continue;
  606. }
  607. if (stepped_up_size.IsEmpty()) {
  608. if (oracle.capture_size() != stepped_down_size) {
  609. ASSERT_LT(proving_period_end_time, t);
  610. stepped_up_size = oracle.capture_size();
  611. ASSERT_LT(stepped_down_size.width(), stepped_up_size.width());
  612. ASSERT_LT(stepped_down_size.height(), stepped_up_size.height());
  613. }
  614. } else {
  615. ASSERT_EQ(stepped_up_size, oracle.capture_size());
  616. }
  617. const double utilization = stepped_up_size.IsEmpty() ? 0.25 : 0.9;
  618. const int frame_number = oracle.next_frame_number();
  619. oracle.RecordCapture(utilization);
  620. base::TimeTicks ignored;
  621. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  622. oracle.RecordConsumerFeedback(frame_number,
  623. media::VideoCaptureFeedback(utilization));
  624. }
  625. ASSERT_FALSE(stepped_up_size.IsEmpty());
  626. }
  627. // Tests that VideoCaptureOracle does not change the capture size if
  628. // auto-throttling is enabled when using a fixed resolution policy.
  629. TEST(VideoCaptureOracleTest, DoesNotAutoThrottleWhenResolutionIsFixed) {
  630. VideoCaptureOracle oracle(true);
  631. oracle.SetMinCapturePeriod(k30HzPeriod);
  632. oracle.SetCaptureSizeConstraints(k720pSize, k720pSize, false);
  633. oracle.SetSourceSize(k1080pSize);
  634. // Run 10 seconds of frame captures with 90% utilization expect no capture
  635. // size changes.
  636. base::TimeTicks t = kInitialTestTimeTicks;
  637. const base::TimeDelta event_increment = k30HzPeriod * 2;
  638. base::TimeTicks end_t = t + base::Seconds(10);
  639. for (; t < end_t; t += event_increment) {
  640. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  641. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  642. ASSERT_EQ(k720pSize, oracle.capture_size());
  643. base::TimeTicks ignored;
  644. const int frame_number = oracle.next_frame_number();
  645. oracle.RecordCapture(0.9);
  646. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  647. oracle.RecordConsumerFeedback(frame_number,
  648. media::VideoCaptureFeedback(0.9));
  649. }
  650. // Now run 10 seconds with overload indicated. Still, expect no capture size
  651. // changes.
  652. end_t = t + base::Seconds(10);
  653. for (; t < end_t; t += event_increment) {
  654. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  655. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  656. ASSERT_EQ(k720pSize, oracle.capture_size());
  657. base::TimeTicks ignored;
  658. const int frame_number = oracle.next_frame_number();
  659. oracle.RecordCapture(2.0);
  660. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  661. oracle.RecordConsumerFeedback(frame_number,
  662. media::VideoCaptureFeedback(2.0));
  663. }
  664. }
  665. // Tests that VideoCaptureOracle reduces resolution on max_pixels feedback.
  666. TEST(VideoCaptureOracleTest, RespectsMaxPixelsFeedback) {
  667. VideoCaptureOracle oracle(true);
  668. oracle.SetMinCapturePeriod(k30HzPeriod);
  669. oracle.SetCaptureSizeConstraints(kSmallestNonEmptySize, k720pSize, false);
  670. oracle.SetSourceSize(k720pSize);
  671. // Run 1 second with no feedback and expect no capture size changes.
  672. base::TimeTicks t = kInitialTestTimeTicks;
  673. const base::TimeDelta event_increment = k30HzPeriod * 2;
  674. base::TimeTicks end_t = t + base::Seconds(1);
  675. for (; t < end_t; t += event_increment) {
  676. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  677. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  678. ASSERT_EQ(k720pSize, oracle.capture_size());
  679. base::TimeTicks ignored;
  680. const int frame_number = oracle.next_frame_number();
  681. oracle.RecordCapture(0.25); // Low buffer utilization.
  682. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  683. oracle.RecordConsumerFeedback(frame_number, media::VideoCaptureFeedback());
  684. }
  685. // Now run for a single frame with 360p pixel limit.
  686. {
  687. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  688. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  689. ASSERT_EQ(k720pSize, oracle.capture_size());
  690. base::TimeTicks ignored;
  691. const int frame_number = oracle.next_frame_number();
  692. oracle.RecordCapture(0.25); // Low buffer utilization.
  693. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  694. oracle.RecordConsumerFeedback(
  695. frame_number,
  696. media::VideoCaptureFeedback(
  697. -1.0, std::numeric_limits<float>::infinity(), k360pSize.GetArea()));
  698. t += event_increment;
  699. }
  700. // Capture another frame. Size should be 360p. Make feedback with no limit.
  701. {
  702. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  703. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  704. ASSERT_EQ(k360pSize, oracle.capture_size());
  705. base::TimeTicks ignored;
  706. const int frame_number = oracle.next_frame_number();
  707. oracle.RecordCapture(0.25); // Low buffer utilization.
  708. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  709. oracle.RecordConsumerFeedback(frame_number, media::VideoCaptureFeedback());
  710. t += event_increment;
  711. }
  712. // Capture another frame. Size should be reverted back, since the last frame
  713. // reported no limit.
  714. {
  715. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  716. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  717. ASSERT_EQ(k720pSize, oracle.capture_size());
  718. base::TimeTicks ignored;
  719. const int frame_number = oracle.next_frame_number();
  720. oracle.RecordCapture(0.25); // Low buffer utilization.
  721. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  722. oracle.RecordConsumerFeedback(frame_number, media::VideoCaptureFeedback());
  723. t += event_increment;
  724. }
  725. }
  726. // Tests that VideoCaptureOracle respects resource_utilization feedback over
  727. // max_pixels feedback.
  728. TEST(VideoCaptureOracleTest, IgnoresMaxPixelsFeedbackIfAutoThrottlingIsOn) {
  729. VideoCaptureOracle oracle(true);
  730. oracle.SetMinCapturePeriod(k30HzPeriod);
  731. oracle.SetCaptureSizeConstraints(kSmallestNonEmptySize, k720pSize, false);
  732. oracle.SetSourceSize(k720pSize);
  733. // Run 1 second with no feedback and expect no capture size changes.
  734. base::TimeTicks t = kInitialTestTimeTicks;
  735. const base::TimeDelta event_increment = k30HzPeriod * 2;
  736. base::TimeTicks end_t = t + base::Seconds(1);
  737. for (; t < end_t; t += event_increment) {
  738. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  739. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  740. ASSERT_EQ(k720pSize, oracle.capture_size());
  741. base::TimeTicks ignored;
  742. const int frame_number = oracle.next_frame_number();
  743. oracle.RecordCapture(0.25); // Low buffer utilization.
  744. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  745. oracle.RecordConsumerFeedback(frame_number,
  746. media::VideoCaptureFeedback(0.25));
  747. }
  748. // Now run with a new 360p pixel limit returned in the feedback.
  749. {
  750. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  751. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  752. ASSERT_EQ(k720pSize, oracle.capture_size());
  753. base::TimeTicks ignored;
  754. const int frame_number = oracle.next_frame_number();
  755. oracle.RecordCapture(0.25); // Low buffer utilization.
  756. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  757. oracle.RecordConsumerFeedback(
  758. frame_number,
  759. media::VideoCaptureFeedback(
  760. 0.25, std::numeric_limits<float>::infinity(), k360pSize.GetArea()));
  761. t += event_increment;
  762. }
  763. // Capture another frame. Size should still be 720p, since the autothrottling
  764. // was enabled by the previous feedback.
  765. {
  766. ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
  767. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
  768. ASSERT_EQ(k720pSize, oracle.capture_size());
  769. base::TimeTicks ignored;
  770. const int frame_number = oracle.next_frame_number();
  771. oracle.RecordCapture(0.25); // Low buffer utilization.
  772. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  773. oracle.RecordConsumerFeedback(frame_number, media::VideoCaptureFeedback());
  774. t += event_increment;
  775. }
  776. }
  777. // Tests that VideoCaptureOracle respects the max framerate requested by the
  778. // consumer.
  779. TEST(VideoCaptureOracleTest, RespectsMaxFrameRateFeedback) {
  780. constexpr base::TimeDelta vsync_interval = base::Hertz(60);
  781. constexpr base::TimeDelta k5HzPeriod = base::Hertz(5);
  782. constexpr base::TimeDelta kAllowedError = base::Milliseconds(1);
  783. constexpr float k5Fps = 5.0;
  784. constexpr float kNoResourceUtilization = -1.0;
  785. constexpr float kNoFpsLimit = std::numeric_limits<float>::infinity();
  786. VideoCaptureOracle oracle(false);
  787. oracle.SetMinCapturePeriod(k30HzPeriod);
  788. oracle.SetCaptureSizeConstraints(k720pSize, k720pSize, false);
  789. // Have the oracle observe some compositor events. Simulate that each capture
  790. // completes successfully.
  791. base::TimeTicks t = kInitialTestTimeTicks;
  792. base::TimeTicks ignored;
  793. int frame_number;
  794. // As if previous frame was captured at 30 fps.
  795. absl::optional<base::TimeTicks> last_capture_time;
  796. for (int i = 0; i < 100; ++i) {
  797. t += vsync_interval;
  798. if (oracle.ObserveEventAndDecideCapture(
  799. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
  800. frame_number = oracle.next_frame_number();
  801. oracle.RecordCapture(0.0);
  802. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  803. if (last_capture_time) {
  804. EXPECT_GE(t - *last_capture_time, k30HzPeriod - kAllowedError);
  805. EXPECT_LE(t - *last_capture_time, k30HzPeriod + kAllowedError);
  806. }
  807. last_capture_time = t;
  808. }
  809. }
  810. // 100 vsync periods is more than enough to capture something.
  811. ASSERT_TRUE(last_capture_time.has_value());
  812. // Receive feedback on the very last frame.
  813. oracle.RecordConsumerFeedback(
  814. frame_number, media::VideoCaptureFeedback(kNoResourceUtilization, k5Fps));
  815. // Don't measure frame-rate across different target frame-rates.
  816. last_capture_time = absl::nullopt;
  817. // Continue capturing frames, observe that frame-rate limit is respected.
  818. for (int i = 0; i < 100; ++i) {
  819. t += vsync_interval;
  820. if (oracle.ObserveEventAndDecideCapture(
  821. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
  822. frame_number = oracle.next_frame_number();
  823. oracle.RecordCapture(0.0);
  824. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  825. if (last_capture_time) {
  826. EXPECT_GE(t - *last_capture_time, k5HzPeriod - kAllowedError);
  827. EXPECT_LE(t - *last_capture_time, k5HzPeriod + kAllowedError);
  828. }
  829. last_capture_time = t;
  830. }
  831. }
  832. // 100 vsync periods is more than enough to capture something.
  833. ASSERT_TRUE(last_capture_time.has_value());
  834. // Receive feedback with no limit.
  835. oracle.RecordConsumerFeedback(
  836. frame_number,
  837. media::VideoCaptureFeedback(kNoResourceUtilization, kNoFpsLimit));
  838. // Don't measure frame-rate across different target frame-rates.
  839. last_capture_time = absl::nullopt;
  840. // Continue capturing frames, observe that original min capture period is
  841. // respected.
  842. for (int i = 0; i < 100; ++i) {
  843. t += vsync_interval;
  844. if (oracle.ObserveEventAndDecideCapture(
  845. VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
  846. frame_number = oracle.next_frame_number();
  847. oracle.RecordCapture(0.0);
  848. ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
  849. if (last_capture_time) {
  850. EXPECT_GE(t - *last_capture_time, k30HzPeriod - kAllowedError);
  851. EXPECT_LE(t - *last_capture_time, k30HzPeriod + kAllowedError);
  852. }
  853. last_capture_time = t;
  854. }
  855. }
  856. // 100 vsync periods is more than enough to capture something.
  857. ASSERT_TRUE(last_capture_time.has_value());
  858. }
  859. } // namespace media