Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / capture / content / smooth_event_sampler_unittest.cc
blobb3234aa20d69869e74e3eef4cbaebc39ab4ab4bf
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/smooth_event_sampler.h"
7 #include "base/strings/stringprintf.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 namespace media {
12 namespace {
14 bool AddEventAndConsiderSampling(SmoothEventSampler* sampler,
15 base::TimeTicks event_time) {
16 sampler->ConsiderPresentationEvent(event_time);
17 return sampler->ShouldSample();
20 void SteadyStateSampleAndAdvance(base::TimeDelta vsync,
21 SmoothEventSampler* sampler,
22 base::TimeTicks* t) {
23 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t));
24 ASSERT_TRUE(sampler->HasUnrecordedEvent());
25 sampler->RecordSample();
26 ASSERT_FALSE(sampler->HasUnrecordedEvent());
27 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
28 *t += vsync;
29 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
32 void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync,
33 SmoothEventSampler* sampler,
34 base::TimeTicks* t) {
35 ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t));
36 ASSERT_TRUE(sampler->HasUnrecordedEvent());
37 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
38 *t += vsync;
39 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
42 base::TimeTicks InitialTestTimeTicks() {
43 return base::TimeTicks() + base::TimeDelta::FromSeconds(1);
46 void TestRedundantCaptureStrategy(base::TimeDelta capture_period,
47 int redundant_capture_goal,
48 SmoothEventSampler* sampler,
49 base::TimeTicks* t) {
50 // Before any events have been considered, we're overdue for sampling.
51 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t));
53 // Consider the first event. We want to sample that.
54 ASSERT_FALSE(sampler->HasUnrecordedEvent());
55 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t));
56 ASSERT_TRUE(sampler->HasUnrecordedEvent());
57 sampler->RecordSample();
58 ASSERT_FALSE(sampler->HasUnrecordedEvent());
60 // After more than 250 ms has passed without considering an event, we should
61 // repeatedly be overdue for sampling. However, once the redundant capture
62 // goal is achieved, we should no longer be overdue for sampling.
63 *t += base::TimeDelta::FromMilliseconds(250);
64 for (int i = 0; i < redundant_capture_goal; i++) {
65 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
66 ASSERT_FALSE(sampler->HasUnrecordedEvent());
67 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t))
68 << "Should sample until redundant capture goal is hit";
69 sampler->RecordSample();
70 *t += capture_period; // Timer fires once every capture period.
72 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t))
73 << "Should not be overdue once redundant capture goal achieved.";
76 } // namespace
78 // 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains
79 // much more comprehensive before/after/edge-case scenarios than the others.
80 TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
81 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
82 const int redundant_capture_goal = 200;
83 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
85 SmoothEventSampler sampler(capture_period, redundant_capture_goal);
86 base::TimeTicks t = InitialTestTimeTicks();
88 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
89 &t);
91 // Steady state, we should capture every other vsync, indefinitely.
92 for (int i = 0; i < 100; i++) {
93 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
94 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
95 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
98 // Now pretend we're limited by backpressure in the pipeline. In this scenario
99 // case we are adding events but not sampling them.
100 for (int i = 0; i < 20; i++) {
101 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
102 ASSERT_EQ(i >= 14, sampler.IsOverdueForSamplingAt(t));
103 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
104 ASSERT_TRUE(sampler.HasUnrecordedEvent());
105 t += vsync;
108 // Now suppose we can sample again. We should be back in the steady state,
109 // but at a different phase.
110 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
111 for (int i = 0; i < 100; i++) {
112 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
113 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
114 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
118 // 50Hz sampled at 30Hz should produce a sequence where some frames are skipped.
119 TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
120 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
121 const int redundant_capture_goal = 2;
122 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50;
124 SmoothEventSampler sampler(capture_period, redundant_capture_goal);
125 base::TimeTicks t = InitialTestTimeTicks();
127 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
128 &t);
130 // Steady state, we should capture 1st, 2nd and 4th frames out of every five
131 // frames, indefinitely.
132 for (int i = 0; i < 100; i++) {
133 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
134 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
135 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
136 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
137 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
138 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
141 // Now pretend we're limited by backpressure in the pipeline. In this scenario
142 // case we are adding events but not sampling them.
143 for (int i = 0; i < 20; i++) {
144 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
145 ASSERT_EQ(i >= 11, sampler.IsOverdueForSamplingAt(t));
146 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
147 t += vsync;
150 // Now suppose we can sample again. We should be back in the steady state
151 // again.
152 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
153 for (int i = 0; i < 100; i++) {
154 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
155 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
156 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
157 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
158 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
159 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
163 // 75Hz sampled at 30Hz should produce a sequence where some frames are skipped.
164 TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) {
165 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
166 const int redundant_capture_goal = 32;
167 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75;
169 SmoothEventSampler sampler(capture_period, redundant_capture_goal);
170 base::TimeTicks t = InitialTestTimeTicks();
172 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
173 &t);
175 // Steady state, we should capture 1st and 3rd frames out of every five
176 // frames, indefinitely.
177 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
178 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
179 for (int i = 0; i < 100; i++) {
180 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
181 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
182 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
183 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
184 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
185 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
188 // Now pretend we're limited by backpressure in the pipeline. In this scenario
189 // case we are adding events but not sampling them.
190 for (int i = 0; i < 20; i++) {
191 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
192 ASSERT_EQ(i >= 16, sampler.IsOverdueForSamplingAt(t));
193 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
194 t += vsync;
197 // Now suppose we can sample again. We capture the next frame, and not the one
198 // after that, and then we're back in the steady state again.
199 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
200 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
201 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
202 for (int i = 0; i < 100; i++) {
203 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
204 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
205 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
206 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
207 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
208 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
212 // 30Hz sampled at 30Hz should produce 30Hz.
213 TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
214 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
215 const int redundant_capture_goal = 1;
216 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30;
218 SmoothEventSampler sampler(capture_period, redundant_capture_goal);
219 base::TimeTicks t = InitialTestTimeTicks();
221 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
222 &t);
224 // Steady state, we should capture every vsync, indefinitely.
225 for (int i = 0; i < 200; i++) {
226 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
227 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
230 // Now pretend we're limited by backpressure in the pipeline. In this scenario
231 // case we are adding events but not sampling them.
232 for (int i = 0; i < 10; i++) {
233 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
234 ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t));
235 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
236 t += vsync;
239 // Now suppose we can sample again. We should be back in the steady state.
240 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
241 for (int i = 0; i < 100; i++) {
242 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
243 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
247 // 24Hz sampled at 30Hz should produce 24Hz.
248 TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) {
249 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
250 const int redundant_capture_goal = 333;
251 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24;
253 SmoothEventSampler sampler(capture_period, redundant_capture_goal);
254 base::TimeTicks t = InitialTestTimeTicks();
256 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
257 &t);
259 // Steady state, we should capture every vsync, indefinitely.
260 for (int i = 0; i < 200; i++) {
261 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
262 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
265 // Now pretend we're limited by backpressure in the pipeline. In this scenario
266 // case we are adding events but not sampling them.
267 for (int i = 0; i < 10; i++) {
268 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
269 ASSERT_EQ(i >= 6, sampler.IsOverdueForSamplingAt(t));
270 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
271 t += vsync;
274 // Now suppose we can sample again. We should be back in the steady state.
275 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
276 for (int i = 0; i < 100; i++) {
277 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
278 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
282 // Tests that changing the minimum capture period during usage results in the
283 // desired behavior.
284 TEST(SmoothEventSamplerTest, Sample60HertzWithVariedCapturePeriods) {
285 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
286 const base::TimeDelta one_to_one_period = vsync;
287 const base::TimeDelta two_to_one_period = vsync * 2;
288 const base::TimeDelta two_and_three_to_one_period =
289 base::TimeDelta::FromSeconds(1) / 24;
290 const int redundant_capture_goal = 1;
292 SmoothEventSampler sampler(one_to_one_period, redundant_capture_goal);
293 base::TimeTicks t = InitialTestTimeTicks();
295 TestRedundantCaptureStrategy(one_to_one_period, redundant_capture_goal,
296 &sampler, &t);
298 // With the capture rate at 60 Hz, we should capture every vsync.
299 for (int i = 0; i < 100; i++) {
300 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
301 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
304 // Now change to the capture rate to 30 Hz, and we should capture every other
305 // vsync.
306 sampler.SetMinCapturePeriod(two_to_one_period);
307 for (int i = 0; i < 100; i++) {
308 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
309 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
310 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
313 // Now change the capture rate back to 60 Hz, and we should capture every
314 // vsync again.
315 sampler.SetMinCapturePeriod(one_to_one_period);
316 for (int i = 0; i < 100; i++) {
317 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
318 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
321 // Now change the capture rate to 24 Hz, and we should capture with a 2-3-2-3
322 // cadence.
323 sampler.SetMinCapturePeriod(two_and_three_to_one_period);
324 for (int i = 0; i < 100; i++) {
325 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
326 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
327 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
328 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
329 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
330 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
334 TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) {
335 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
336 const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1);
338 SmoothEventSampler sampler(capture_period, 1);
339 base::TimeTicks t = InitialTestTimeTicks();
341 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
342 sampler.RecordSample();
343 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t))
344 << "Sampled last event; should not be dirty.";
345 t += overdue_period;
347 // Now simulate 2 events with the same clock value.
348 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
349 sampler.RecordSample();
350 ASSERT_FALSE(AddEventAndConsiderSampling(&sampler, t))
351 << "Two events at same time -- expected second not to be sampled.";
352 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period))
353 << "Second event should dirty the capture state.";
354 sampler.RecordSample();
355 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t + overdue_period));
358 namespace {
360 struct DataPoint {
361 bool should_capture;
362 double increment_ms;
365 void ReplayCheckingSamplerDecisions(const DataPoint* data_points,
366 size_t num_data_points,
367 SmoothEventSampler* sampler) {
368 base::TimeTicks t = InitialTestTimeTicks();
369 for (size_t i = 0; i < num_data_points; ++i) {
370 t += base::TimeDelta::FromMicroseconds(
371 static_cast<int64>(data_points[i].increment_ms * 1000));
372 ASSERT_EQ(data_points[i].should_capture,
373 AddEventAndConsiderSampling(sampler, t))
374 << "at data_points[" << i << ']';
375 if (data_points[i].should_capture)
376 sampler->RecordSample();
380 } // namespace
382 TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) {
383 // Actual capturing of timing data: Initial instability as a 24 FPS video was
384 // started from a still screen, then clearly followed by steady-state.
385 static const DataPoint data_points[] = {{true, 1437.93},
386 {true, 150.484},
387 {true, 217.362},
388 {true, 50.161},
389 {true, 33.44},
390 {false, 0},
391 {true, 16.721},
392 {true, 66.88},
393 {true, 50.161},
394 {false, 0},
395 {false, 0},
396 {true, 50.16},
397 {true, 33.441},
398 {true, 16.72},
399 {false, 16.72},
400 {true, 117.041},
401 {true, 16.72},
402 {false, 16.72},
403 {true, 50.161},
404 {true, 50.16},
405 {true, 33.441},
406 {true, 33.44},
407 {true, 33.44},
408 {true, 16.72},
409 {false, 0},
410 {true, 50.161},
411 {false, 0},
412 {true, 33.44},
413 {true, 16.72},
414 {false, 16.721},
415 {true, 66.881},
416 {false, 0},
417 {true, 33.441},
418 {true, 16.72},
419 {true, 50.16},
420 {true, 16.72},
421 {false, 16.721},
422 {true, 50.161},
423 {true, 50.16},
424 {false, 0},
425 {true, 33.441},
426 {true, 50.337},
427 {true, 50.183},
428 {true, 16.722},
429 {true, 50.161},
430 {true, 33.441},
431 {true, 50.16},
432 {true, 33.441},
433 {true, 50.16},
434 {true, 33.441},
435 {true, 50.16},
436 {true, 33.44},
437 {true, 50.161},
438 {true, 50.16},
439 {true, 33.44},
440 {true, 33.441},
441 {true, 50.16},
442 {true, 50.161},
443 {true, 33.44},
444 {true, 33.441},
445 {true, 50.16},
446 {true, 33.44},
447 {true, 50.161},
448 {true, 33.44},
449 {true, 50.161},
450 {true, 33.44},
451 {true, 50.161},
452 {true, 33.44},
453 {true, 83.601},
454 {true, 16.72},
455 {true, 33.44},
456 {false, 0}};
458 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
459 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
462 TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) {
463 // Actual capturing of timing data: Initial instability as a 30 FPS video was
464 // started from a still screen, then followed by steady-state. Drawing
465 // framerate from the video rendering was a bit volatile, but averaged 30 FPS.
466 static const DataPoint data_points[] = {{true, 2407.69},
467 {true, 16.733},
468 {true, 217.362},
469 {true, 33.441},
470 {true, 33.44},
471 {true, 33.44},
472 {true, 33.441},
473 {true, 33.44},
474 {true, 33.44},
475 {true, 33.441},
476 {true, 33.44},
477 {true, 33.44},
478 {true, 16.721},
479 {true, 33.44},
480 {false, 0},
481 {true, 50.161},
482 {true, 50.16},
483 {false, 0},
484 {true, 50.161},
485 {true, 33.44},
486 {true, 16.72},
487 {false, 0},
488 {false, 16.72},
489 {true, 66.881},
490 {false, 0},
491 {true, 33.44},
492 {true, 16.72},
493 {true, 50.161},
494 {false, 0},
495 {true, 33.538},
496 {true, 33.526},
497 {true, 33.447},
498 {true, 33.445},
499 {true, 33.441},
500 {true, 16.721},
501 {true, 33.44},
502 {true, 33.44},
503 {true, 50.161},
504 {true, 16.72},
505 {true, 33.44},
506 {true, 33.441},
507 {true, 33.44},
508 {false, 0},
509 {false, 16.72},
510 {true, 66.881},
511 {true, 16.72},
512 {false, 16.72},
513 {true, 50.16},
514 {true, 33.441},
515 {true, 33.44},
516 {true, 33.44},
517 {true, 33.44},
518 {true, 33.441},
519 {true, 33.44},
520 {true, 50.161},
521 {false, 0},
522 {true, 33.44},
523 {true, 33.44},
524 {true, 50.161},
525 {true, 16.72},
526 {true, 33.44},
527 {true, 33.441},
528 {false, 0},
529 {true, 66.88},
530 {true, 33.441},
531 {true, 33.44},
532 {true, 33.44},
533 {false, 0},
534 {true, 33.441},
535 {true, 33.44},
536 {true, 33.44},
537 {false, 0},
538 {true, 16.72},
539 {true, 50.161},
540 {false, 0},
541 {true, 50.16},
542 {false, 0.001},
543 {true, 16.721},
544 {true, 66.88},
545 {true, 33.44},
546 {true, 33.441},
547 {true, 33.44},
548 {true, 50.161},
549 {true, 16.72},
550 {false, 0},
551 {true, 33.44},
552 {false, 16.72},
553 {true, 66.881},
554 {true, 33.44},
555 {true, 16.72},
556 {true, 33.441},
557 {false, 16.72},
558 {true, 66.88},
559 {true, 16.721},
560 {true, 50.16},
561 {true, 33.44},
562 {true, 16.72},
563 {true, 33.441},
564 {true, 33.44},
565 {true, 33.44}};
567 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
568 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
571 TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) {
572 // Actual capturing of timing data: WebGL Acquarium demo
573 // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran
574 // between 55-60 FPS in the steady-state.
575 static const DataPoint data_points[] = {{true, 16.72},
576 {true, 16.72},
577 {true, 4163.29},
578 {true, 50.193},
579 {true, 117.041},
580 {true, 50.161},
581 {true, 50.16},
582 {true, 33.441},
583 {true, 50.16},
584 {true, 33.44},
585 {false, 0},
586 {false, 0},
587 {true, 50.161},
588 {true, 83.601},
589 {true, 50.16},
590 {true, 16.72},
591 {true, 33.441},
592 {false, 16.72},
593 {true, 50.16},
594 {true, 16.72},
595 {false, 0.001},
596 {true, 33.441},
597 {false, 16.72},
598 {true, 16.72},
599 {true, 50.16},
600 {false, 0},
601 {true, 16.72},
602 {true, 33.441},
603 {false, 0},
604 {true, 33.44},
605 {false, 16.72},
606 {true, 16.72},
607 {true, 50.161},
608 {false, 0},
609 {true, 16.72},
610 {true, 33.44},
611 {false, 0},
612 {true, 33.44},
613 {false, 16.721},
614 {true, 16.721},
615 {true, 50.161},
616 {false, 0},
617 {true, 16.72},
618 {true, 33.441},
619 {false, 0},
620 {true, 33.44},
621 {false, 16.72},
622 {true, 33.44},
623 {false, 0},
624 {true, 16.721},
625 {true, 50.161},
626 {false, 0},
627 {true, 33.44},
628 {false, 0},
629 {true, 16.72},
630 {true, 33.441},
631 {false, 0},
632 {true, 33.44},
633 {false, 16.72},
634 {true, 16.72},
635 {true, 50.16},
636 {false, 0},
637 {true, 16.721},
638 {true, 33.44},
639 {false, 0},
640 {true, 33.44},
641 {false, 16.721},
642 {true, 16.721},
643 {true, 50.161},
644 {false, 0},
645 {true, 16.72},
646 {true, 33.44},
647 {false, 0},
648 {true, 33.441},
649 {false, 16.72},
650 {true, 16.72},
651 {true, 50.16},
652 {false, 0},
653 {true, 16.72},
654 {true, 33.441},
655 {true, 33.44},
656 {false, 0},
657 {true, 33.44},
658 {true, 33.441},
659 {false, 0},
660 {true, 33.44},
661 {true, 33.441},
662 {false, 0},
663 {true, 33.44},
664 {false, 0},
665 {true, 33.44},
666 {false, 16.72},
667 {true, 16.721},
668 {true, 50.161},
669 {false, 0},
670 {true, 16.72},
671 {true, 33.44},
672 {true, 33.441},
673 {false, 0},
674 {true, 33.44},
675 {true, 33.44},
676 {false, 0},
677 {true, 33.441},
678 {false, 16.72},
679 {true, 16.72},
680 {true, 50.16},
681 {false, 0},
682 {true, 16.72},
683 {true, 33.441},
684 {false, 0},
685 {true, 33.44},
686 {false, 16.72},
687 {true, 33.44},
688 {false, 0},
689 {true, 16.721},
690 {true, 50.161},
691 {false, 0},
692 {true, 16.72},
693 {true, 33.44},
694 {false, 0},
695 {true, 33.441},
696 {false, 16.72},
697 {true, 16.72},
698 {true, 50.16}};
700 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
701 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
704 } // namespace media