Remove PlatformFile from profile_browsertest
[chromium-blink-merge.git] / content / browser / media / capture / video_capture_oracle_unittest.cc
blobdff8e97de7fec39c7f3e0f56f2c33c7f50ab5e1b
1 // Copyright (c) 2013 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 "content/browser/media/capture/video_capture_oracle.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/time/time.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 namespace content {
12 namespace {
14 void SteadyStateSampleAndAdvance(base::TimeDelta vsync,
15 SmoothEventSampler* sampler,
16 base::TimeTicks* t) {
17 ASSERT_TRUE(sampler->AddEventAndConsiderSampling(*t));
18 ASSERT_TRUE(sampler->HasUnrecordedEvent());
19 sampler->RecordSample();
20 ASSERT_FALSE(sampler->HasUnrecordedEvent());
21 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
22 *t += vsync;
23 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
26 void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync,
27 SmoothEventSampler* sampler,
28 base::TimeTicks* t) {
29 ASSERT_FALSE(sampler->AddEventAndConsiderSampling(*t));
30 ASSERT_TRUE(sampler->HasUnrecordedEvent());
31 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
32 *t += vsync;
33 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
36 void TimeTicksFromString(const char* string, base::TimeTicks* t) {
37 base::Time time;
38 ASSERT_TRUE(base::Time::FromString(string, &time));
39 *t = base::TimeTicks::UnixEpoch() + (time - base::Time::UnixEpoch());
42 void TestRedundantCaptureStrategy(base::TimeDelta capture_period,
43 int redundant_capture_goal,
44 SmoothEventSampler* sampler,
45 base::TimeTicks* t) {
46 // Before any events have been considered, we're overdue for sampling.
47 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t));
49 // Consider the first event. We want to sample that.
50 ASSERT_FALSE(sampler->HasUnrecordedEvent());
51 ASSERT_TRUE(sampler->AddEventAndConsiderSampling(*t));
52 ASSERT_TRUE(sampler->HasUnrecordedEvent());
53 sampler->RecordSample();
54 ASSERT_FALSE(sampler->HasUnrecordedEvent());
56 // After more than one capture period has passed without considering an event,
57 // we should repeatedly be overdue for sampling. However, once the redundant
58 // capture goal is achieved, we should no longer be overdue for sampling.
59 *t += capture_period * 4;
60 for (int i = 0; i < redundant_capture_goal; i++) {
61 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
62 ASSERT_FALSE(sampler->HasUnrecordedEvent());
63 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t))
64 << "Should sample until redundant capture goal is hit";
65 sampler->RecordSample();
66 *t += capture_period; // Timer fires once every capture period.
68 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t))
69 << "Should not be overdue once redundant capture goal achieved.";
72 // 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains
73 // much more comprehensive before/after/edge-case scenarios than the others.
74 TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
75 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
76 const int redundant_capture_goal = 200;
77 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
79 SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
80 base::TimeTicks t;
81 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
83 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
84 &sampler, &t);
86 // Steady state, we should capture every other vsync, indefinitely.
87 for (int i = 0; i < 100; i++) {
88 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
89 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
90 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
93 // Now pretend we're limited by backpressure in the pipeline. In this scenario
94 // case we are adding events but not sampling them.
95 for (int i = 0; i < 20; i++) {
96 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
97 ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t));
98 ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
99 ASSERT_TRUE(sampler.HasUnrecordedEvent());
100 t += vsync;
103 // Now suppose we can sample again. We should be back in the steady state,
104 // but at a different phase.
105 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
106 for (int i = 0; i < 100; i++) {
107 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
108 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
109 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
113 // 50Hz sampled at 30Hz should produce a sequence where some frames are skipped.
114 TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
115 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
116 const int redundant_capture_goal = 2;
117 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50;
119 SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
120 base::TimeTicks t;
121 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
123 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
124 &sampler, &t);
126 // Steady state, we should capture 1st, 2nd and 4th frames out of every five
127 // frames, indefinitely.
128 for (int i = 0; i < 100; i++) {
129 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
130 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
131 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
132 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
133 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
134 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
137 // Now pretend we're limited by backpressure in the pipeline. In this scenario
138 // case we are adding events but not sampling them.
139 for (int i = 0; i < 12; i++) {
140 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
141 ASSERT_EQ(i >= 5, sampler.IsOverdueForSamplingAt(t));
142 ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
143 t += vsync;
146 // Now suppose we can sample again. We should be back in the steady state
147 // again.
148 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
149 for (int i = 0; i < 100; i++) {
150 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
151 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
152 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
153 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
154 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
155 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
159 // 75Hz sampled at 30Hz should produce a sequence where some frames are skipped.
160 TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) {
161 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
162 const int redundant_capture_goal = 32;
163 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75;
165 SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
166 base::TimeTicks t;
167 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
169 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
170 &sampler, &t);
172 // Steady state, we should capture 1st and 3rd frames out of every five
173 // frames, indefinitely.
174 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
175 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
176 for (int i = 0; i < 100; i++) {
177 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
178 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
179 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
180 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
181 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
182 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
185 // Now pretend we're limited by backpressure in the pipeline. In this scenario
186 // case we are adding events but not sampling them.
187 for (int i = 0; i < 20; i++) {
188 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
189 ASSERT_EQ(i >= 8, sampler.IsOverdueForSamplingAt(t));
190 ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
191 t += vsync;
194 // Now suppose we can sample again. We capture the next frame, and not the one
195 // after that, and then we're back in the steady state again.
196 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
197 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
198 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
199 for (int i = 0; i < 100; i++) {
200 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
201 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
202 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
203 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
204 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
205 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
209 // 30Hz sampled at 30Hz should produce 30Hz.
210 TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
211 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
212 const int redundant_capture_goal = 1;
213 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30;
215 SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
216 base::TimeTicks t;
217 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
219 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
220 &sampler, &t);
222 // Steady state, we should capture every vsync, indefinitely.
223 for (int i = 0; i < 200; i++) {
224 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
225 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
228 // Now pretend we're limited by backpressure in the pipeline. In this scenario
229 // case we are adding events but not sampling them.
230 for (int i = 0; i < 7; i++) {
231 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
232 ASSERT_EQ(i >= 3, sampler.IsOverdueForSamplingAt(t));
233 ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
234 t += vsync;
237 // Now suppose we can sample again. We should be back in the steady state.
238 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
239 for (int i = 0; i < 100; i++) {
240 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
241 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
245 // 24Hz sampled at 30Hz should produce 24Hz.
246 TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) {
247 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
248 const int redundant_capture_goal = 333;
249 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24;
251 SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
252 base::TimeTicks t;
253 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
255 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
256 &sampler, &t);
258 // Steady state, we should capture every vsync, indefinitely.
259 for (int i = 0; i < 200; i++) {
260 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
261 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
264 // Now pretend we're limited by backpressure in the pipeline. In this scenario
265 // case we are adding events but not sampling them.
266 for (int i = 0; i < 7; i++) {
267 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
268 ASSERT_EQ(i >= 3, sampler.IsOverdueForSamplingAt(t));
269 ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
270 t += vsync;
273 // Now suppose we can sample again. We should be back in the steady state.
274 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
275 for (int i = 0; i < 100; i++) {
276 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
277 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
281 TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) {
282 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
283 const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1);
285 SmoothEventSampler sampler(capture_period, true, 1);
286 base::TimeTicks t;
287 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
289 ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
290 sampler.RecordSample();
291 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t))
292 << "Sampled last event; should not be dirty.";
293 t += overdue_period;
295 // Now simulate 2 events with the same clock value.
296 ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
297 sampler.RecordSample();
298 ASSERT_FALSE(sampler.AddEventAndConsiderSampling(t))
299 << "Two events at same time -- expected second not to be sampled.";
300 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period))
301 << "Second event should dirty the capture state.";
302 sampler.RecordSample();
303 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t + overdue_period));
306 TEST(SmoothEventSamplerTest, FallbackToPollingIfUpdatesUnreliable) {
307 const base::TimeDelta timer_interval = base::TimeDelta::FromSeconds(1) / 30;
309 SmoothEventSampler should_not_poll(timer_interval, true, 1);
310 SmoothEventSampler should_poll(timer_interval, false, 1);
311 base::TimeTicks t;
312 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
314 // Do one round of the "happy case" where an event was received and
315 // RecordSample() was called by the client.
316 ASSERT_TRUE(should_not_poll.AddEventAndConsiderSampling(t));
317 ASSERT_TRUE(should_poll.AddEventAndConsiderSampling(t));
318 should_not_poll.RecordSample();
319 should_poll.RecordSample();
321 // One time period ahead, neither sampler says we're overdue.
322 for (int i = 0; i < 3; i++) {
323 t += timer_interval;
324 ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
325 << "Sampled last event; should not be dirty.";
326 ASSERT_FALSE(should_poll.IsOverdueForSamplingAt(t))
327 << "Dirty interval has not elapsed yet.";
330 // Next time period ahead, both samplers say we're overdue. The non-polling
331 // sampler is returning true here because it has been configured to allow one
332 // redundant capture.
333 t += timer_interval;
334 ASSERT_TRUE(should_not_poll.IsOverdueForSamplingAt(t))
335 << "Sampled last event; is dirty one time only to meet redundancy goal.";
336 ASSERT_TRUE(should_poll.IsOverdueForSamplingAt(t))
337 << "If updates are unreliable, must fall back to polling when idle.";
338 should_not_poll.RecordSample();
339 should_poll.RecordSample();
341 // Forever more, the non-polling sampler returns false while the polling one
342 // returns true.
343 for (int i = 0; i < 100; ++i) {
344 t += timer_interval;
345 ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
346 << "Sampled last event; should not be dirty.";
347 ASSERT_TRUE(should_poll.IsOverdueForSamplingAt(t))
348 << "If updates are unreliable, must fall back to polling when idle.";
349 should_poll.RecordSample();
351 t += timer_interval / 3;
352 ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
353 << "Sampled last event; should not be dirty.";
354 ASSERT_TRUE(should_poll.IsOverdueForSamplingAt(t))
355 << "If updates are unreliable, must fall back to polling when idle.";
356 should_poll.RecordSample();
359 struct DataPoint {
360 bool should_capture;
361 double increment_ms;
364 void ReplayCheckingSamplerDecisions(const DataPoint* data_points,
365 size_t num_data_points,
366 SmoothEventSampler* sampler) {
367 base::TimeTicks t;
368 TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
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 sampler->AddEventAndConsiderSampling(t))
374 << "at data_points[" << i << ']';
375 if (data_points[i].should_capture)
376 sampler->RecordSample();
380 TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) {
381 // Actual capturing of timing data: Initial instability as a 24 FPS video was
382 // started from a still screen, then clearly followed by steady-state.
383 static const DataPoint data_points[] = {
384 { true, 1437.93 }, { true, 150.484 }, { true, 217.362 }, { true, 50.161 },
385 { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 66.88 },
386 { true, 50.161 }, { false, 0 }, { false, 0 }, { true, 50.16 },
387 { true, 33.441 }, { true, 16.72 }, { false, 16.72 }, { true, 117.041 },
388 { true, 16.72 }, { false, 16.72 }, { true, 50.161 }, { true, 50.16 },
389 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 16.72 },
390 { false, 0 }, { true, 50.161 }, { false, 0 }, { true, 33.44 },
391 { true, 16.72 }, { false, 16.721 }, { true, 66.881 }, { false, 0 },
392 { true, 33.441 }, { true, 16.72 }, { true, 50.16 }, { true, 16.72 },
393 { false, 16.721 }, { true, 50.161 }, { true, 50.16 }, { false, 0 },
394 { true, 33.441 }, { true, 50.337 }, { true, 50.183 }, { true, 16.722 },
395 { true, 50.161 }, { true, 33.441 }, { true, 50.16 }, { true, 33.441 },
396 { true, 50.16 }, { true, 33.441 }, { true, 50.16 }, { true, 33.44 },
397 { true, 50.161 }, { true, 50.16 }, { true, 33.44 }, { true, 33.441 },
398 { true, 50.16 }, { true, 50.161 }, { true, 33.44 }, { true, 33.441 },
399 { true, 50.16 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 },
400 { true, 50.161 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 },
401 { true, 83.601 }, { true, 16.72 }, { true, 33.44 }, { false, 0 }
404 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true, 3);
405 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
408 TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) {
409 // Actual capturing of timing data: Initial instability as a 30 FPS video was
410 // started from a still screen, then followed by steady-state. Drawing
411 // framerate from the video rendering was a bit volatile, but averaged 30 FPS.
412 static const DataPoint data_points[] = {
413 { true, 2407.69 }, { true, 16.733 }, { true, 217.362 }, { true, 33.441 },
414 { true, 33.44 }, { true, 33.44 }, { true, 33.441 }, { true, 33.44 },
415 { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 },
416 { true, 16.721 }, { true, 33.44 }, { false, 0 }, { true, 50.161 },
417 { true, 50.16 }, { false, 0 }, { true, 50.161 }, { true, 33.44 },
418 { true, 16.72 }, { false, 0 }, { false, 16.72 }, { true, 66.881 },
419 { false, 0 }, { true, 33.44 }, { true, 16.72 }, { true, 50.161 },
420 { false, 0 }, { true, 33.538 }, { true, 33.526 }, { true, 33.447 },
421 { true, 33.445 }, { true, 33.441 }, { true, 16.721 }, { true, 33.44 },
422 { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, { true, 33.44 },
423 { true, 33.441 }, { true, 33.44 }, { false, 0 }, { false, 16.72 },
424 { true, 66.881 }, { true, 16.72 }, { false, 16.72 }, { true, 50.16 },
425 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 33.44 },
426 { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { false, 0 },
427 { true, 33.44 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 },
428 { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 66.88 },
429 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 },
430 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 },
431 { true, 16.72 }, { true, 50.161 }, { false, 0 }, { true, 50.16 },
432 { false, 0.001 }, { true, 16.721 }, { true, 66.88 }, { true, 33.44 },
433 { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 },
434 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 66.881 },
435 { true, 33.44 }, { true, 16.72 }, { true, 33.441 }, { false, 16.72 },
436 { true, 66.88 }, { true, 16.721 }, { true, 50.16 }, { true, 33.44 },
437 { true, 16.72 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 }
440 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true, 3);
441 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
444 TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) {
445 // Actual capturing of timing data: WebGL Acquarium demo
446 // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran
447 // between 55-60 FPS in the steady-state.
448 static const DataPoint data_points[] = {
449 { true, 16.72 }, { true, 16.72 }, { true, 4163.29 }, { true, 50.193 },
450 { true, 117.041 }, { true, 50.161 }, { true, 50.16 }, { true, 33.441 },
451 { true, 50.16 }, { true, 33.44 }, { false, 0 }, { false, 0 },
452 { true, 50.161 }, { true, 83.601 }, { true, 50.16 }, { true, 16.72 },
453 { true, 33.441 }, { false, 16.72 }, { true, 50.16 }, { true, 16.72 },
454 { false, 0.001 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 },
455 { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
456 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 },
457 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 },
458 { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 },
459 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
460 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 33.44 },
461 { false, 0 }, { true, 16.721 }, { true, 50.161 }, { false, 0 },
462 { true, 33.44 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
463 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 },
464 { true, 50.16 }, { false, 0 }, { true, 16.721 }, { true, 33.44 },
465 { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 },
466 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 },
467 { false, 0 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 },
468 { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
469 { true, 33.44 }, { false, 0 }, { true, 33.44 }, { true, 33.441 },
470 { false, 0 }, { true, 33.44 }, { true, 33.441 }, { false, 0 },
471 { true, 33.44 }, { false, 0 }, { true, 33.44 }, { false, 16.72 },
472 { true, 16.721 }, { true, 50.161 }, { false, 0 }, { true, 16.72 },
473 { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 33.44 },
474 { true, 33.44 }, { false, 0 }, { true, 33.441 }, { false, 16.72 },
475 { true, 16.72 }, { true, 50.16 }, { false, 0 }, { true, 16.72 },
476 { true, 33.441 }, { false, 0 }, { true, 33.44 }, { false, 16.72 },
477 { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 50.161 },
478 { false, 0 }, { true, 16.72 }, { true, 33.44 }, { false, 0 },
479 { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, { true, 50.16 }
482 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true, 3);
483 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
486 } // namespace
487 } // namespace content