1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
media / base / frame_rate_estimator_unittest.cc [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/frame_rate_estimator.h"
#include <tuple>
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
using FpsPair = std::tuple<int, int>;
class FrameRateEstimatorTest : public testing::TestWithParam<FpsPair> {
public:
void ProvideSamples(base::TimeDelta duration, int count) {
while (count--)
estimator_.AddSample(duration);
}
void ProvideSample(base::TimeDelta duration) {
estimator_.AddSample(duration);
}
int low_fps() const { return std::get<0>(GetParam()); }
int high_fps() const { return std::get<1>(GetParam()); }
base::TimeDelta duration(int fps) { return base::Seconds(1.0 / fps); }
FrameRateEstimator estimator_;
};
TEST_P(FrameRateEstimatorTest, NoEstimateInitially) {
// Asking for an estimate with no samples is okay, though it shouldn't return
// an estimate.
EXPECT_FALSE(estimator_.ComputeFPS());
}
TEST_P(FrameRateEstimatorTest, AverageConvergesThenReset) {
// Verify that the estimate is provided after the required samples are reached
// and that Reset() clears it.
// The initial sample requirement should allow quick convergence.
EXPECT_EQ(estimator_.GetRequiredSamplesForTesting(),
estimator_.GetMinSamplesForTesting());
// Make sure that it doesn't converge before the required sample count.
ProvideSamples(duration(low_fps()),
estimator_.GetRequiredSamplesForTesting() - 1);
EXPECT_FALSE(estimator_.ComputeFPS());
ProvideSample(duration(low_fps()));
EXPECT_EQ(*estimator_.ComputeFPS(), low_fps());
estimator_.Reset();
EXPECT_FALSE(estimator_.ComputeFPS());
ProvideSamples(duration(low_fps()),
estimator_.GetRequiredSamplesForTesting() - 1);
EXPECT_FALSE(estimator_.ComputeFPS());
}
TEST_P(FrameRateEstimatorTest, DurationJitterIsFine) {
// A little jitter doesn't change anything.
ProvideSamples(duration(low_fps()),
estimator_.GetRequiredSamplesForTesting());
// Compute a jitter that's not big enough to move it out of its bucket. We
// use +1 so it works either above or below (below has more room). 2.0 would
// be fine ideally, but we make it a bit smaller than that just to prevent
// floating point weirdness.
auto jitter = (duration(low_fps()) - duration(low_fps() + 1)) / 2.1;
for (int i = 0; i < estimator_.GetRequiredSamplesForTesting(); i++) {
ProvideSample(duration(low_fps()) + jitter);
EXPECT_EQ(*estimator_.ComputeFPS(), low_fps());
}
for (int i = 0; i < estimator_.GetRequiredSamplesForTesting(); i++) {
ProvideSample(duration(low_fps()) - jitter);
EXPECT_EQ(*estimator_.ComputeFPS(), low_fps());
}
}
TEST_P(FrameRateEstimatorTest, AverageDoesntSkew) {
// Changing frame rates shouldn't skew between them. It should stop providing
// estimates temporarily.
ProvideSamples(duration(low_fps()),
estimator_.GetRequiredSamplesForTesting());
EXPECT_EQ(*estimator_.ComputeFPS(), low_fps());
ProvideSample(duration(high_fps()));
EXPECT_FALSE(estimator_.ComputeFPS());
// We should now require more samples one we destabilized.
EXPECT_EQ(estimator_.GetRequiredSamplesForTesting(),
estimator_.GetMaxSamplesForTesting());
ProvideSamples(duration(high_fps()),
estimator_.GetRequiredSamplesForTesting() - 2);
EXPECT_FALSE(estimator_.ComputeFPS());
ProvideSample(duration(high_fps()));
EXPECT_EQ(*estimator_.ComputeFPS(), high_fps());
}
TEST_P(FrameRateEstimatorTest, ResetAllowsFastConvergence) {
// If we're in slow-convergence mode, Reset() should allow fast convergence.
// Get into slow convergence mode by providing a non-uniform window.
ProvideSamples(duration(low_fps()), estimator_.GetMinSamplesForTesting() - 1);
ProvideSamples(duration(high_fps()), 1);
EXPECT_EQ(estimator_.GetRequiredSamplesForTesting(),
estimator_.GetMaxSamplesForTesting());
// See if Reset() gets us back to fast convergence.
estimator_.Reset();
EXPECT_EQ(estimator_.GetRequiredSamplesForTesting(),
estimator_.GetMinSamplesForTesting());
}
// Instantiate tests for lots of common frame rates.
INSTANTIATE_TEST_SUITE_P(All,
FrameRateEstimatorTest,
testing::Values(FpsPair(24, 30),
FpsPair(24, 60),
FpsPair(24, 90),
FpsPair(24, 120),
FpsPair(24, 240),
FpsPair(30, 60),
FpsPair(30, 90),
FpsPair(30, 120),
FpsPair(30, 240),
FpsPair(60, 90),
FpsPair(60, 120),
FpsPair(60, 240),
FpsPair(90, 120),
FpsPair(90, 240),
FpsPair(120, 240)));
} // namespace media