Index: media/filters/video_cadence_estimator_unittest.cc |
diff --git a/media/filters/video_cadence_estimator_unittest.cc b/media/filters/video_cadence_estimator_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..04ca70ca6356bc7067601e7c5ff09e959c25deee |
--- /dev/null |
+++ b/media/filters/video_cadence_estimator_unittest.cc |
@@ -0,0 +1,171 @@ |
+// Copyright 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 "base/memory/scoped_ptr.h" |
+#include "base/strings/stringprintf.h" |
+#include "media/filters/video_cadence_estimator.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace media { |
+ |
+// See VideoCadenceEstimator header for more details. |
+const int kMinimumAcceptableTimeBetweenGlitchesSecs = 8; |
+ |
+// Slows down the given |fps| according to NTSC field reduction standards; see |
+// http://en.wikipedia.org/wiki/Frame_rate#Digital_video_and_television |
+static double NTSC(double fps) { |
+ return fps / 1.001; |
+} |
+ |
+static base::TimeDelta Interval(double hertz) { |
+ return base::TimeDelta::FromSecondsD(1.0 / hertz); |
+} |
+ |
+static void VerifyCadence(VideoCadenceEstimator* estimator, |
+ double frame_hertz, |
+ double render_hertz, |
+ int expected_cadence) { |
+ SCOPED_TRACE(base::StringPrintf("Checking %.03f fps into %0.03f", frame_hertz, |
+ render_hertz)); |
+ estimator->Reset(); |
+ const base::TimeDelta acceptable_drift = Interval(frame_hertz) / 2; |
+ const bool cadence_changed = estimator->UpdateCadenceEstimate( |
+ Interval(render_hertz), Interval(frame_hertz), acceptable_drift); |
+ EXPECT_EQ(cadence_changed, estimator->has_cadence()); |
+ EXPECT_EQ(!!expected_cadence, estimator->has_cadence()); |
+ |
+ // Nothing further to test. |
+ if (!expected_cadence) |
+ return; |
+ |
+ // Spot check a few frame indices. |
+ if (frame_hertz <= render_hertz) { |
+ EXPECT_EQ(expected_cadence, estimator->GetCadenceForFrame(0)); |
+ EXPECT_EQ(expected_cadence, estimator->GetCadenceForFrame(1)); |
+ EXPECT_EQ(expected_cadence, estimator->GetCadenceForFrame(2)); |
+ } else { |
+ EXPECT_EQ(1, estimator->GetCadenceForFrame(0)); |
+ EXPECT_EQ(0, estimator->GetCadenceForFrame(1)); |
+ EXPECT_EQ(1, estimator->GetCadenceForFrame(expected_cadence)); |
+ EXPECT_EQ(0, estimator->GetCadenceForFrame(expected_cadence + 1)); |
+ } |
+} |
+ |
+// Spot check common display and frame rate pairs for correctness. |
+TEST(VideoCadenceEstimatorTest, CadenceCalculations) { |
+ VideoCadenceEstimator estimator( |
+ base::TimeDelta::FromSeconds(kMinimumAcceptableTimeBetweenGlitchesSecs)); |
+ estimator.set_cadence_hysteresis_threshold_for_testing(base::TimeDelta()); |
+ |
+ VerifyCadence(&estimator, 24, 60, 0); |
+ VerifyCadence(&estimator, NTSC(24), 60, 0); |
+ VerifyCadence(&estimator, 25, 60, 0); |
+ VerifyCadence(&estimator, NTSC(30), 60, 2); |
+ VerifyCadence(&estimator, 30, 60, 2); |
+ VerifyCadence(&estimator, 50, 60, 0); |
+ VerifyCadence(&estimator, NTSC(60), 60, 1); |
+ VerifyCadence(&estimator, 120, 60, 2); |
+ |
+ // 50Hz is common in the EU. |
+ VerifyCadence(&estimator, NTSC(24), 50, 0); |
+ VerifyCadence(&estimator, 24, 50, 0); |
+ VerifyCadence(&estimator, NTSC(25), 50, 2); |
+ VerifyCadence(&estimator, 25, 50, 2); |
+ VerifyCadence(&estimator, NTSC(30), 50, 0); |
+ VerifyCadence(&estimator, 30, 50, 0); |
+ VerifyCadence(&estimator, NTSC(60), 50, 0); |
+ VerifyCadence(&estimator, 60, 50, 0); |
+ |
+ VerifyCadence(&estimator, 25, NTSC(60), 0); |
+ VerifyCadence(&estimator, 120, NTSC(60), 0); |
+ VerifyCadence(&estimator, 1, NTSC(60), 60); |
+} |
+ |
+TEST(VideoCadenceEstimatorTest, CadenceVariesWithAcceptableDrift) { |
+ VideoCadenceEstimator estimator( |
+ base::TimeDelta::FromSeconds(kMinimumAcceptableTimeBetweenGlitchesSecs)); |
+ estimator.set_cadence_hysteresis_threshold_for_testing(base::TimeDelta()); |
+ |
+ const base::TimeDelta render_interval = Interval(NTSC(60)); |
+ const base::TimeDelta frame_interval = Interval(120); |
+ |
+ base::TimeDelta acceptable_drift = frame_interval / 2; |
+ EXPECT_FALSE(estimator.UpdateCadenceEstimate(render_interval, frame_interval, |
+ acceptable_drift)); |
+ EXPECT_FALSE(estimator.has_cadence()); |
+ |
+ // Increasing the acceptable drift should be result in more permissive |
+ // detection of cadence. |
+ acceptable_drift = render_interval; |
+ EXPECT_TRUE(estimator.UpdateCadenceEstimate(render_interval, frame_interval, |
+ acceptable_drift)); |
+ EXPECT_TRUE(estimator.has_cadence()); |
+ EXPECT_EQ(2, estimator.get_cadence_for_testing()); |
+} |
+ |
+TEST(VideoCadenceEstimatorTest, CadenceVariesWithAcceptableGlitchTime) { |
+ scoped_ptr<VideoCadenceEstimator> estimator(new VideoCadenceEstimator( |
+ base::TimeDelta::FromSeconds(kMinimumAcceptableTimeBetweenGlitchesSecs))); |
+ estimator->set_cadence_hysteresis_threshold_for_testing(base::TimeDelta()); |
+ |
+ const base::TimeDelta render_interval = Interval(NTSC(60)); |
+ const base::TimeDelta frame_interval = Interval(120); |
+ const base::TimeDelta acceptable_drift = frame_interval / 2; |
+ |
+ EXPECT_FALSE(estimator->UpdateCadenceEstimate(render_interval, frame_interval, |
+ acceptable_drift)); |
+ EXPECT_FALSE(estimator->has_cadence()); |
+ |
+ // Decreasing the acceptable glitch time should be result in more permissive |
+ // detection of cadence. |
+ estimator.reset(new VideoCadenceEstimator(base::TimeDelta::FromSeconds( |
+ kMinimumAcceptableTimeBetweenGlitchesSecs / 2))); |
+ estimator->set_cadence_hysteresis_threshold_for_testing(base::TimeDelta()); |
+ EXPECT_TRUE(estimator->UpdateCadenceEstimate(render_interval, frame_interval, |
+ acceptable_drift)); |
+ EXPECT_TRUE(estimator->has_cadence()); |
+ EXPECT_EQ(2, estimator->get_cadence_for_testing()); |
+} |
+ |
+TEST(VideoCadenceEstimatorTest, CadenceHystersisPreventsOscillation) { |
+ scoped_ptr<VideoCadenceEstimator> estimator(new VideoCadenceEstimator( |
+ base::TimeDelta::FromSeconds(kMinimumAcceptableTimeBetweenGlitchesSecs))); |
+ |
+ const base::TimeDelta render_interval = Interval(30); |
+ const base::TimeDelta frame_interval = Interval(60); |
+ const base::TimeDelta acceptable_drift = frame_interval / 2; |
+ estimator->set_cadence_hysteresis_threshold_for_testing(render_interval * 2); |
+ |
+ // Cadence hysteresis should prevent the cadence from taking effect yet. |
+ EXPECT_FALSE(estimator->UpdateCadenceEstimate(render_interval, frame_interval, |
+ acceptable_drift)); |
+ EXPECT_FALSE(estimator->has_cadence()); |
+ |
+ // A second call should exceed cadence hysteresis and take into effect. |
+ EXPECT_TRUE(estimator->UpdateCadenceEstimate(render_interval, frame_interval, |
+ acceptable_drift)); |
+ EXPECT_TRUE(estimator->has_cadence()); |
+ |
+ // One bad interval shouldn't cause cadence to drop |
+ EXPECT_FALSE(estimator->UpdateCadenceEstimate( |
+ render_interval, frame_interval * 0.75, acceptable_drift)); |
+ EXPECT_TRUE(estimator->has_cadence()); |
+ |
+ // Resumption of cadence should clear bad interval count. |
+ EXPECT_FALSE(estimator->UpdateCadenceEstimate(render_interval, frame_interval, |
+ acceptable_drift)); |
+ EXPECT_TRUE(estimator->has_cadence()); |
+ |
+ // So one more bad interval shouldn't cause cadence to drop |
+ EXPECT_FALSE(estimator->UpdateCadenceEstimate( |
+ render_interval, frame_interval * 0.75, acceptable_drift)); |
+ EXPECT_TRUE(estimator->has_cadence()); |
+ |
+ // Two bad intervals should. |
+ EXPECT_TRUE(estimator->UpdateCadenceEstimate( |
+ render_interval, frame_interval * 0.75, acceptable_drift)); |
+ EXPECT_FALSE(estimator->has_cadence()); |
+} |
+ |
+} // namespace media |