// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/capture/content/smooth_event_sampler.h"

#include <stddef.h>
#include <stdint.h>

#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

namespace {

bool AddEventAndConsiderSampling(SmoothEventSampler* sampler,
                                 base::TimeTicks event_time) {
  sampler->ConsiderPresentationEvent(event_time);
  return sampler->ShouldSample();
}

void SteadyStateSampleAndAdvance(base::TimeDelta vsync,
                                 SmoothEventSampler* sampler,
                                 base::TimeTicks* t) {
  ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t));
  ASSERT_TRUE(sampler->HasUnrecordedEvent());
  sampler->RecordSample();
  ASSERT_FALSE(sampler->HasUnrecordedEvent());
  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
  *t += vsync;
  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
}

void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync,
                                   SmoothEventSampler* sampler,
                                   base::TimeTicks* t) {
  ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t));
  ASSERT_TRUE(sampler->HasUnrecordedEvent());
  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
  *t += vsync;
  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
}

base::TimeTicks InitialTestTimeTicks() {
  return base::TimeTicks() + base::TimeDelta::FromSeconds(1);
}

void TestRedundantCaptureStrategy(base::TimeDelta capture_period,
                                  int redundant_capture_goal,
                                  SmoothEventSampler* sampler,
                                  base::TimeTicks* t) {
  // Before any events have been considered, we're overdue for sampling.
  ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t));

  // Consider the first event.  We want to sample that.
  ASSERT_FALSE(sampler->HasUnrecordedEvent());
  ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t));
  ASSERT_TRUE(sampler->HasUnrecordedEvent());
  sampler->RecordSample();
  ASSERT_FALSE(sampler->HasUnrecordedEvent());

  // After more than 250 ms has passed without considering an event, we should
  // repeatedly be overdue for sampling.  However, once the redundant capture
  // goal is achieved, we should no longer be overdue for sampling.
  *t += base::TimeDelta::FromMilliseconds(250);
  for (int i = 0; i < redundant_capture_goal; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    ASSERT_FALSE(sampler->HasUnrecordedEvent());
    ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t))
        << "Should sample until redundant capture goal is hit";
    sampler->RecordSample();
    *t += capture_period;  // Timer fires once every capture period.
  }
  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t))
      << "Should not be overdue once redundant capture goal achieved.";
}

}  // namespace

// 60Hz sampled at 30Hz should produce 30Hz.  In addition, this test contains
// much more comprehensive before/after/edge-case scenarios than the others.
TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
  const int redundant_capture_goal = 200;
  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;

  SmoothEventSampler sampler(capture_period, redundant_capture_goal);
  base::TimeTicks t = InitialTestTimeTicks();

  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
                               &t);

  // Steady state, we should capture every other vsync, indefinitely.
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now pretend we're limited by backpressure in the pipeline. In this scenario
  // case we are adding events but not sampling them.
  for (int i = 0; i < 20; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    ASSERT_EQ(i >= 14, sampler.IsOverdueForSamplingAt(t));
    ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
    ASSERT_TRUE(sampler.HasUnrecordedEvent());
    t += vsync;
  }

  // Now suppose we can sample again. We should be back in the steady state,
  // but at a different phase.
  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  }
}

// 50Hz sampled at 30Hz should produce a sequence where some frames are skipped.
TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
  const int redundant_capture_goal = 2;
  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50;

  SmoothEventSampler sampler(capture_period, redundant_capture_goal);
  base::TimeTicks t = InitialTestTimeTicks();

  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
                               &t);

  // Steady state, we should capture 1st, 2nd and 4th frames out of every five
  // frames, indefinitely.
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now pretend we're limited by backpressure in the pipeline. In this scenario
  // case we are adding events but not sampling them.
  for (int i = 0; i < 20; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    ASSERT_EQ(i >= 11, sampler.IsOverdueForSamplingAt(t));
    ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
    t += vsync;
  }

  // Now suppose we can sample again. We should be back in the steady state
  // again.
  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  }
}

// 75Hz sampled at 30Hz should produce a sequence where some frames are skipped.
TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) {
  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
  const int redundant_capture_goal = 32;
  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75;

  SmoothEventSampler sampler(capture_period, redundant_capture_goal);
  base::TimeTicks t = InitialTestTimeTicks();

  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
                               &t);

  // Steady state, we should capture 1st and 3rd frames out of every five
  // frames, indefinitely.
  SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now pretend we're limited by backpressure in the pipeline. In this scenario
  // case we are adding events but not sampling them.
  for (int i = 0; i < 20; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    ASSERT_EQ(i >= 16, sampler.IsOverdueForSamplingAt(t));
    ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
    t += vsync;
  }

  // Now suppose we can sample again. We capture the next frame, and not the one
  // after that, and then we're back in the steady state again.
  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
  SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
  }
}

// 30Hz sampled at 30Hz should produce 30Hz.
TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
  const int redundant_capture_goal = 1;
  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30;

  SmoothEventSampler sampler(capture_period, redundant_capture_goal);
  base::TimeTicks t = InitialTestTimeTicks();

  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
                               &t);

  // Steady state, we should capture every vsync, indefinitely.
  for (int i = 0; i < 200; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now pretend we're limited by backpressure in the pipeline. In this scenario
  // case we are adding events but not sampling them.
  for (int i = 0; i < 10; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t));
    ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
    t += vsync;
  }

  // Now suppose we can sample again. We should be back in the steady state.
  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }
}

// 24Hz sampled at 30Hz should produce 24Hz.
TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) {
  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
  const int redundant_capture_goal = 333;
  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24;

  SmoothEventSampler sampler(capture_period, redundant_capture_goal);
  base::TimeTicks t = InitialTestTimeTicks();

  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler,
                               &t);

  // Steady state, we should capture every vsync, indefinitely.
  for (int i = 0; i < 200; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now pretend we're limited by backpressure in the pipeline. In this scenario
  // case we are adding events but not sampling them.
  for (int i = 0; i < 10; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    ASSERT_EQ(i >= 6, sampler.IsOverdueForSamplingAt(t));
    ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
    t += vsync;
  }

  // Now suppose we can sample again. We should be back in the steady state.
  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }
}

// Tests that changing the minimum capture period during usage results in the
// desired behavior.
TEST(SmoothEventSamplerTest, Sample60HertzWithVariedCapturePeriods) {
  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
  const base::TimeDelta one_to_one_period = vsync;
  const base::TimeDelta two_to_one_period = vsync * 2;
  const base::TimeDelta two_and_three_to_one_period =
      base::TimeDelta::FromSeconds(1) / 24;
  const int redundant_capture_goal = 1;

  SmoothEventSampler sampler(one_to_one_period, redundant_capture_goal);
  base::TimeTicks t = InitialTestTimeTicks();

  TestRedundantCaptureStrategy(one_to_one_period, redundant_capture_goal,
                               &sampler, &t);

  // With the capture rate at 60 Hz, we should capture every vsync.
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now change to the capture rate to 30 Hz, and we should capture every other
  // vsync.
  sampler.SetMinCapturePeriod(two_to_one_period);
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now change the capture rate back to 60 Hz, and we should capture every
  // vsync again.
  sampler.SetMinCapturePeriod(one_to_one_period);
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }

  // Now change the capture rate to 24 Hz, and we should capture with a 2-3-2-3
  // cadence.
  sampler.SetMinCapturePeriod(two_and_three_to_one_period);
  for (int i = 0; i < 100; i++) {
    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
  }
}

TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) {
  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
  const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1);

  SmoothEventSampler sampler(capture_period, 1);
  base::TimeTicks t = InitialTestTimeTicks();

  ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
  sampler.RecordSample();
  ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t))
      << "Sampled last event; should not be dirty.";
  t += overdue_period;

  // Now simulate 2 events with the same clock value.
  ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
  sampler.RecordSample();
  ASSERT_FALSE(AddEventAndConsiderSampling(&sampler, t))
      << "Two events at same time -- expected second not to be sampled.";
  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period))
      << "Second event should dirty the capture state.";
  sampler.RecordSample();
  ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t + overdue_period));
}

namespace {

struct DataPoint {
  bool should_capture;
  double increment_ms;
};

void ReplayCheckingSamplerDecisions(const DataPoint* data_points,
                                    size_t num_data_points,
                                    SmoothEventSampler* sampler) {
  base::TimeTicks t = InitialTestTimeTicks();
  for (size_t i = 0; i < num_data_points; ++i) {
    t += base::TimeDelta::FromMicroseconds(
        static_cast<int64_t>(data_points[i].increment_ms * 1000));
    ASSERT_EQ(data_points[i].should_capture,
              AddEventAndConsiderSampling(sampler, t))
        << "at data_points[" << i << ']';
    if (data_points[i].should_capture)
      sampler->RecordSample();
  }
}

}  // namespace

TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) {
  // Actual capturing of timing data: Initial instability as a 24 FPS video was
  // started from a still screen, then clearly followed by steady-state.
  static const DataPoint data_points[] = {{true, 1437.93},
                                          {true, 150.484},
                                          {true, 217.362},
                                          {true, 50.161},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 16.721},
                                          {true, 66.88},
                                          {true, 50.161},
                                          {false, 0},
                                          {false, 0},
                                          {true, 50.16},
                                          {true, 33.441},
                                          {true, 16.72},
                                          {false, 16.72},
                                          {true, 117.041},
                                          {true, 16.72},
                                          {false, 16.72},
                                          {true, 50.161},
                                          {true, 50.16},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 16.72},
                                          {false, 0},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 33.44},
                                          {true, 16.72},
                                          {false, 16.721},
                                          {true, 66.881},
                                          {false, 0},
                                          {true, 33.441},
                                          {true, 16.72},
                                          {true, 50.16},
                                          {true, 16.72},
                                          {false, 16.721},
                                          {true, 50.161},
                                          {true, 50.16},
                                          {false, 0},
                                          {true, 33.441},
                                          {true, 50.337},
                                          {true, 50.183},
                                          {true, 16.722},
                                          {true, 50.161},
                                          {true, 33.441},
                                          {true, 50.16},
                                          {true, 33.441},
                                          {true, 50.16},
                                          {true, 33.441},
                                          {true, 50.16},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {true, 50.16},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {true, 50.16},
                                          {true, 50.161},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {true, 50.16},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {true, 33.44},
                                          {true, 83.601},
                                          {true, 16.72},
                                          {true, 33.44},
                                          {false, 0}};

  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
  ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
}

TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) {
  // Actual capturing of timing data: Initial instability as a 30 FPS video was
  // started from a still screen, then followed by steady-state.  Drawing
  // framerate from the video rendering was a bit volatile, but averaged 30 FPS.
  static const DataPoint data_points[] = {{true, 2407.69},
                                          {true, 16.733},
                                          {true, 217.362},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 16.721},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 50.161},
                                          {true, 50.16},
                                          {false, 0},
                                          {true, 50.161},
                                          {true, 33.44},
                                          {true, 16.72},
                                          {false, 0},
                                          {false, 16.72},
                                          {true, 66.881},
                                          {false, 0},
                                          {true, 33.44},
                                          {true, 16.72},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 33.538},
                                          {true, 33.526},
                                          {true, 33.447},
                                          {true, 33.445},
                                          {true, 33.441},
                                          {true, 16.721},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {true, 16.72},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {false, 0},
                                          {false, 16.72},
                                          {true, 66.881},
                                          {true, 16.72},
                                          {false, 16.72},
                                          {true, 50.16},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {true, 16.72},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 66.88},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 50.16},
                                          {false, 0.001},
                                          {true, 16.721},
                                          {true, 66.88},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 50.161},
                                          {true, 16.72},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.72},
                                          {true, 66.881},
                                          {true, 33.44},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {false, 16.72},
                                          {true, 66.88},
                                          {true, 16.721},
                                          {true, 50.16},
                                          {true, 33.44},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {true, 33.44}};

  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
  ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
}

TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) {
  // Actual capturing of timing data: WebGL Acquarium demo
  // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran
  // between 55-60 FPS in the steady-state.
  static const DataPoint data_points[] = {{true, 16.72},
                                          {true, 16.72},
                                          {true, 4163.29},
                                          {true, 50.193},
                                          {true, 117.041},
                                          {true, 50.161},
                                          {true, 50.16},
                                          {true, 33.441},
                                          {true, 50.16},
                                          {true, 33.44},
                                          {false, 0},
                                          {false, 0},
                                          {true, 50.161},
                                          {true, 83.601},
                                          {true, 50.16},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {false, 16.72},
                                          {true, 50.16},
                                          {true, 16.72},
                                          {false, 0.001},
                                          {true, 33.441},
                                          {false, 16.72},
                                          {true, 16.72},
                                          {true, 50.16},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.72},
                                          {true, 16.72},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.721},
                                          {true, 16.721},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.72},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 16.721},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.72},
                                          {true, 16.72},
                                          {true, 50.16},
                                          {false, 0},
                                          {true, 16.721},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.721},
                                          {true, 16.721},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.441},
                                          {false, 16.72},
                                          {true, 16.72},
                                          {true, 50.16},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.72},
                                          {true, 16.721},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.44},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 33.44},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.441},
                                          {false, 16.72},
                                          {true, 16.72},
                                          {true, 50.16},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.441},
                                          {false, 0},
                                          {true, 33.44},
                                          {false, 16.72},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 16.721},
                                          {true, 50.161},
                                          {false, 0},
                                          {true, 16.72},
                                          {true, 33.44},
                                          {false, 0},
                                          {true, 33.441},
                                          {false, 16.72},
                                          {true, 16.72},
                                          {true, 50.16}};

  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3);
  ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
}

}  // namespace media