Move UpdateManifest test from unit_tests into extensions_unittests.
[chromium-blink-merge.git] / media / capture / smooth_event_sampler_unittest.cc
blob14a6823f556d8b44d2dd8a8604fa3fcf372c8eab
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/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,
89 &sampler, &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,
128 &sampler, &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,
173 &sampler, &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,
222 &sampler, &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,
257 &sampler, &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[] = {
386 { true, 1437.93 }, { true, 150.484 }, { true, 217.362 }, { true, 50.161 },
387 { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 66.88 },
388 { true, 50.161 }, { false, 0 }, { false, 0 }, { true, 50.16 },
389 { true, 33.441 }, { true, 16.72 }, { false, 16.72 }, { true, 117.041 },
390 { true, 16.72 }, { false, 16.72 }, { true, 50.161 }, { true, 50.16 },
391 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 16.72 },
392 { false, 0 }, { true, 50.161 }, { false, 0 }, { true, 33.44 },
393 { true, 16.72 }, { false, 16.721 }, { true, 66.881 }, { false, 0 },
394 { true, 33.441 }, { true, 16.72 }, { true, 50.16 }, { true, 16.72 },
395 { false, 16.721 }, { true, 50.161 }, { true, 50.16 }, { false, 0 },
396 { true, 33.441 }, { true, 50.337 }, { true, 50.183 }, { true, 16.722 },
397 { true, 50.161 }, { true, 33.441 }, { true, 50.16 }, { true, 33.441 },
398 { true, 50.16 }, { true, 33.441 }, { true, 50.16 }, { true, 33.44 },
399 { true, 50.161 }, { true, 50.16 }, { true, 33.44 }, { true, 33.441 },
400 { true, 50.16 }, { true, 50.161 }, { true, 33.44 }, { true, 33.441 },
401 { true, 50.16 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 },
402 { true, 50.161 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 },
403 { true, 83.601 }, { true, 16.72 }, { true, 33.44 }, { false, 0 }
406 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
407 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
410 TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) {
411 // Actual capturing of timing data: Initial instability as a 30 FPS video was
412 // started from a still screen, then followed by steady-state. Drawing
413 // framerate from the video rendering was a bit volatile, but averaged 30 FPS.
414 static const DataPoint data_points[] = {
415 { true, 2407.69 }, { true, 16.733 }, { true, 217.362 }, { true, 33.441 },
416 { true, 33.44 }, { true, 33.44 }, { true, 33.441 }, { true, 33.44 },
417 { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 },
418 { true, 16.721 }, { true, 33.44 }, { false, 0 }, { true, 50.161 },
419 { true, 50.16 }, { false, 0 }, { true, 50.161 }, { true, 33.44 },
420 { true, 16.72 }, { false, 0 }, { false, 16.72 }, { true, 66.881 },
421 { false, 0 }, { true, 33.44 }, { true, 16.72 }, { true, 50.161 },
422 { false, 0 }, { true, 33.538 }, { true, 33.526 }, { true, 33.447 },
423 { true, 33.445 }, { true, 33.441 }, { true, 16.721 }, { true, 33.44 },
424 { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, { true, 33.44 },
425 { true, 33.441 }, { true, 33.44 }, { false, 0 }, { false, 16.72 },
426 { true, 66.881 }, { true, 16.72 }, { false, 16.72 }, { true, 50.16 },
427 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 33.44 },
428 { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { false, 0 },
429 { true, 33.44 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 },
430 { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 66.88 },
431 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 },
432 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 },
433 { true, 16.72 }, { true, 50.161 }, { false, 0 }, { true, 50.16 },
434 { false, 0.001 }, { true, 16.721 }, { true, 66.88 }, { true, 33.44 },
435 { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 },
436 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 66.881 },
437 { true, 33.44 }, { true, 16.72 }, { true, 33.441 }, { false, 16.72 },
438 { true, 66.88 }, { true, 16.721 }, { true, 50.16 }, { true, 33.44 },
439 { true, 16.72 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 }
442 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
443 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
446 TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) {
447 // Actual capturing of timing data: WebGL Acquarium demo
448 // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran
449 // between 55-60 FPS in the steady-state.
450 static const DataPoint data_points[] = {
451 { true, 16.72 }, { true, 16.72 }, { true, 4163.29 }, { true, 50.193 },
452 { true, 117.041 }, { true, 50.161 }, { true, 50.16 }, { true, 33.441 },
453 { true, 50.16 }, { true, 33.44 }, { false, 0 }, { false, 0 },
454 { true, 50.161 }, { true, 83.601 }, { true, 50.16 }, { true, 16.72 },
455 { true, 33.441 }, { false, 16.72 }, { true, 50.16 }, { true, 16.72 },
456 { false, 0.001 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 },
457 { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
458 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 },
459 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 },
460 { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 },
461 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
462 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 33.44 },
463 { false, 0 }, { true, 16.721 }, { true, 50.161 }, { false, 0 },
464 { true, 33.44 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
465 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 },
466 { true, 50.16 }, { false, 0 }, { true, 16.721 }, { true, 33.44 },
467 { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 },
468 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 },
469 { false, 0 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 },
470 { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
471 { true, 33.44 }, { false, 0 }, { true, 33.44 }, { true, 33.441 },
472 { false, 0 }, { true, 33.44 }, { true, 33.441 }, { false, 0 },
473 { true, 33.44 }, { false, 0 }, { true, 33.44 }, { false, 16.72 },
474 { true, 16.721 }, { true, 50.161 }, { false, 0 }, { true, 16.72 },
475 { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 33.44 },
476 { true, 33.44 }, { false, 0 }, { true, 33.441 }, { false, 16.72 },
477 { true, 16.72 }, { true, 50.16 }, { false, 0 }, { true, 16.72 },
478 { true, 33.441 }, { false, 0 }, { true, 33.44 }, { false, 16.72 },
479 { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 50.161 },
480 { false, 0 }, { true, 16.72 }, { true, 33.44 }, { false, 0 },
481 { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, { true, 50.16 }
484 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
485 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
488 } // namespace media