OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/capture/content/smooth_event_sampler.h" | 5 #include "media/capture/content/smooth_event_sampler.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 return sampler->ShouldSample(); | 21 return sampler->ShouldSample(); |
22 } | 22 } |
23 | 23 |
24 void SteadyStateSampleAndAdvance(base::TimeDelta vsync, | 24 void SteadyStateSampleAndAdvance(base::TimeDelta vsync, |
25 SmoothEventSampler* sampler, | 25 SmoothEventSampler* sampler, |
26 base::TimeTicks* t) { | 26 base::TimeTicks* t) { |
27 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); | 27 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); |
28 ASSERT_TRUE(sampler->HasUnrecordedEvent()); | 28 ASSERT_TRUE(sampler->HasUnrecordedEvent()); |
29 sampler->RecordSample(); | 29 sampler->RecordSample(); |
30 ASSERT_FALSE(sampler->HasUnrecordedEvent()); | 30 ASSERT_FALSE(sampler->HasUnrecordedEvent()); |
| 31 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); |
31 *t += vsync; | 32 *t += vsync; |
| 33 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); |
32 } | 34 } |
33 | 35 |
34 void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync, | 36 void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync, |
35 SmoothEventSampler* sampler, | 37 SmoothEventSampler* sampler, |
36 base::TimeTicks* t) { | 38 base::TimeTicks* t) { |
37 ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t)); | 39 ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t)); |
38 ASSERT_TRUE(sampler->HasUnrecordedEvent()); | 40 ASSERT_TRUE(sampler->HasUnrecordedEvent()); |
| 41 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); |
39 *t += vsync; | 42 *t += vsync; |
| 43 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); |
40 } | 44 } |
41 | 45 |
42 base::TimeTicks InitialTestTimeTicks() { | 46 base::TimeTicks InitialTestTimeTicks() { |
43 return base::TimeTicks() + base::TimeDelta::FromSeconds(1); | 47 return base::TimeTicks() + base::TimeDelta::FromSeconds(1); |
44 } | 48 } |
45 | 49 |
| 50 void TestRedundantCaptureStrategy(base::TimeDelta capture_period, |
| 51 int redundant_capture_goal, |
| 52 SmoothEventSampler* sampler, |
| 53 base::TimeTicks* t) { |
| 54 // Before any events have been considered, we're overdue for sampling. |
| 55 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)); |
| 56 |
| 57 // Consider the first event. We want to sample that. |
| 58 ASSERT_FALSE(sampler->HasUnrecordedEvent()); |
| 59 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); |
| 60 ASSERT_TRUE(sampler->HasUnrecordedEvent()); |
| 61 sampler->RecordSample(); |
| 62 ASSERT_FALSE(sampler->HasUnrecordedEvent()); |
| 63 |
| 64 // After more than 250 ms has passed without considering an event, we should |
| 65 // repeatedly be overdue for sampling. However, once the redundant capture |
| 66 // goal is achieved, we should no longer be overdue for sampling. |
| 67 *t += base::TimeDelta::FromMilliseconds(250); |
| 68 for (int i = 0; i < redundant_capture_goal; i++) { |
| 69 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
| 70 ASSERT_FALSE(sampler->HasUnrecordedEvent()); |
| 71 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)) |
| 72 << "Should sample until redundant capture goal is hit"; |
| 73 sampler->RecordSample(); |
| 74 *t += capture_period; // Timer fires once every capture period. |
| 75 } |
| 76 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)) |
| 77 << "Should not be overdue once redundant capture goal achieved."; |
| 78 } |
46 | 79 |
47 } // namespace | 80 } // namespace |
48 | 81 |
49 // 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains | 82 // 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains |
50 // much more comprehensive before/after/edge-case scenarios than the others. | 83 // much more comprehensive before/after/edge-case scenarios than the others. |
51 TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) { | 84 TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) { |
52 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | 85 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; |
| 86 const int redundant_capture_goal = 200; |
53 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; | 87 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; |
54 | 88 |
55 SmoothEventSampler sampler(capture_period); | 89 SmoothEventSampler sampler(capture_period, redundant_capture_goal); |
56 base::TimeTicks t = InitialTestTimeTicks(); | 90 base::TimeTicks t = InitialTestTimeTicks(); |
57 | 91 |
| 92 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler, |
| 93 &t); |
| 94 |
58 // Steady state, we should capture every other vsync, indefinitely. | 95 // Steady state, we should capture every other vsync, indefinitely. |
59 for (int i = 0; i < 100; i++) { | 96 for (int i = 0; i < 100; i++) { |
60 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 97 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
61 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 98 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
62 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 99 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
63 } | 100 } |
64 | 101 |
65 // Now pretend we're limited by backpressure in the pipeline. In this scenario | 102 // Now pretend we're limited by backpressure in the pipeline. In this scenario |
66 // case we are adding events but not sampling them. | 103 // case we are adding events but not sampling them. |
67 for (int i = 0; i < 20; i++) { | 104 for (int i = 0; i < 20; i++) { |
68 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 105 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
| 106 ASSERT_EQ(i >= 14, sampler.IsOverdueForSamplingAt(t)); |
69 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | 107 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); |
70 ASSERT_TRUE(sampler.HasUnrecordedEvent()); | 108 ASSERT_TRUE(sampler.HasUnrecordedEvent()); |
71 t += vsync; | 109 t += vsync; |
72 } | 110 } |
73 | 111 |
74 // Now suppose we can sample again. We should be back in the steady state, | 112 // Now suppose we can sample again. We should be back in the steady state, |
75 // but at a different phase. | 113 // but at a different phase. |
| 114 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); |
76 for (int i = 0; i < 100; i++) { | 115 for (int i = 0; i < 100; i++) { |
77 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 116 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
78 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 117 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
79 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 118 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
80 } | 119 } |
81 } | 120 } |
82 | 121 |
83 // 50Hz sampled at 30Hz should produce a sequence where some frames are skipped. | 122 // 50Hz sampled at 30Hz should produce a sequence where some frames are skipped. |
84 TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) { | 123 TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) { |
85 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | 124 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; |
| 125 const int redundant_capture_goal = 2; |
86 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50; | 126 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50; |
87 | 127 |
88 SmoothEventSampler sampler(capture_period); | 128 SmoothEventSampler sampler(capture_period, redundant_capture_goal); |
89 base::TimeTicks t = InitialTestTimeTicks(); | 129 base::TimeTicks t = InitialTestTimeTicks(); |
90 | 130 |
| 131 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler, |
| 132 &t); |
| 133 |
91 // Steady state, we should capture 1st, 2nd and 4th frames out of every five | 134 // Steady state, we should capture 1st, 2nd and 4th frames out of every five |
92 // frames, indefinitely. | 135 // frames, indefinitely. |
93 for (int i = 0; i < 100; i++) { | 136 for (int i = 0; i < 100; i++) { |
94 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 137 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
95 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 138 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
96 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 139 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
97 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 140 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
98 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 141 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
99 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 142 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
100 } | 143 } |
101 | 144 |
102 // Now pretend we're limited by backpressure in the pipeline. In this scenario | 145 // Now pretend we're limited by backpressure in the pipeline. In this scenario |
103 // case we are adding events but not sampling them. | 146 // case we are adding events but not sampling them. |
104 for (int i = 0; i < 20; i++) { | 147 for (int i = 0; i < 20; i++) { |
105 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 148 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
| 149 ASSERT_EQ(i >= 11, sampler.IsOverdueForSamplingAt(t)); |
106 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | 150 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); |
107 t += vsync; | 151 t += vsync; |
108 } | 152 } |
109 | 153 |
110 // Now suppose we can sample again. We should be back in the steady state | 154 // Now suppose we can sample again. We should be back in the steady state |
111 // again. | 155 // again. |
| 156 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); |
112 for (int i = 0; i < 100; i++) { | 157 for (int i = 0; i < 100; i++) { |
113 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 158 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
114 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 159 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
115 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 160 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
116 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 161 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
117 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 162 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
118 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 163 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
119 } | 164 } |
120 } | 165 } |
121 | 166 |
122 // 75Hz sampled at 30Hz should produce a sequence where some frames are skipped. | 167 // 75Hz sampled at 30Hz should produce a sequence where some frames are skipped. |
123 TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) { | 168 TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) { |
124 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | 169 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; |
| 170 const int redundant_capture_goal = 32; |
125 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75; | 171 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75; |
126 | 172 |
127 SmoothEventSampler sampler(capture_period); | 173 SmoothEventSampler sampler(capture_period, redundant_capture_goal); |
128 base::TimeTicks t = InitialTestTimeTicks(); | 174 base::TimeTicks t = InitialTestTimeTicks(); |
129 | 175 |
| 176 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler, |
| 177 &t); |
| 178 |
130 // Steady state, we should capture 1st and 3rd frames out of every five | 179 // Steady state, we should capture 1st and 3rd frames out of every five |
131 // frames, indefinitely. | 180 // frames, indefinitely. |
132 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 181 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
133 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 182 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
134 for (int i = 0; i < 100; i++) { | 183 for (int i = 0; i < 100; i++) { |
135 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 184 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
136 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 185 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
137 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 186 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
138 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 187 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
139 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 188 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
140 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 189 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
141 } | 190 } |
142 | 191 |
143 // Now pretend we're limited by backpressure in the pipeline. In this scenario | 192 // Now pretend we're limited by backpressure in the pipeline. In this scenario |
144 // case we are adding events but not sampling them. | 193 // case we are adding events but not sampling them. |
145 for (int i = 0; i < 20; i++) { | 194 for (int i = 0; i < 20; i++) { |
146 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 195 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
| 196 ASSERT_EQ(i >= 16, sampler.IsOverdueForSamplingAt(t)); |
147 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | 197 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); |
148 t += vsync; | 198 t += vsync; |
149 } | 199 } |
150 | 200 |
151 // Now suppose we can sample again. We capture the next frame, and not the one | 201 // Now suppose we can sample again. We capture the next frame, and not the one |
152 // after that, and then we're back in the steady state again. | 202 // after that, and then we're back in the steady state again. |
| 203 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); |
153 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 204 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
154 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 205 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
155 for (int i = 0; i < 100; i++) { | 206 for (int i = 0; i < 100; i++) { |
156 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 207 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
157 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 208 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
158 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 209 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
159 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 210 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
160 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 211 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
161 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 212 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
162 } | 213 } |
163 } | 214 } |
164 | 215 |
165 // 30Hz sampled at 30Hz should produce 30Hz. | 216 // 30Hz sampled at 30Hz should produce 30Hz. |
166 TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) { | 217 TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) { |
167 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | 218 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; |
| 219 const int redundant_capture_goal = 1; |
168 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30; | 220 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30; |
169 | 221 |
170 SmoothEventSampler sampler(capture_period); | 222 SmoothEventSampler sampler(capture_period, redundant_capture_goal); |
171 base::TimeTicks t = InitialTestTimeTicks(); | 223 base::TimeTicks t = InitialTestTimeTicks(); |
172 | 224 |
| 225 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler, |
| 226 &t); |
| 227 |
173 // Steady state, we should capture every vsync, indefinitely. | 228 // Steady state, we should capture every vsync, indefinitely. |
174 for (int i = 0; i < 200; i++) { | 229 for (int i = 0; i < 200; i++) { |
175 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 230 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
176 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 231 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
177 } | 232 } |
178 | 233 |
179 // Now pretend we're limited by backpressure in the pipeline. In this scenario | 234 // Now pretend we're limited by backpressure in the pipeline. In this scenario |
180 // case we are adding events but not sampling them. | 235 // case we are adding events but not sampling them. |
181 for (int i = 0; i < 10; i++) { | 236 for (int i = 0; i < 10; i++) { |
182 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 237 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
| 238 ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t)); |
183 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | 239 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); |
184 t += vsync; | 240 t += vsync; |
185 } | 241 } |
186 | 242 |
187 // Now suppose we can sample again. We should be back in the steady state. | 243 // Now suppose we can sample again. We should be back in the steady state. |
| 244 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); |
188 for (int i = 0; i < 100; i++) { | 245 for (int i = 0; i < 100; i++) { |
189 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 246 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
190 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 247 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
191 } | 248 } |
192 } | 249 } |
193 | 250 |
194 // 24Hz sampled at 30Hz should produce 24Hz. | 251 // 24Hz sampled at 30Hz should produce 24Hz. |
195 TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) { | 252 TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) { |
196 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | 253 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; |
| 254 const int redundant_capture_goal = 333; |
197 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24; | 255 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24; |
198 | 256 |
199 SmoothEventSampler sampler(capture_period); | 257 SmoothEventSampler sampler(capture_period, redundant_capture_goal); |
200 base::TimeTicks t = InitialTestTimeTicks(); | 258 base::TimeTicks t = InitialTestTimeTicks(); |
201 | 259 |
| 260 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, &sampler, |
| 261 &t); |
| 262 |
202 // Steady state, we should capture every vsync, indefinitely. | 263 // Steady state, we should capture every vsync, indefinitely. |
203 for (int i = 0; i < 200; i++) { | 264 for (int i = 0; i < 200; i++) { |
204 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 265 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
205 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 266 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
206 } | 267 } |
207 | 268 |
208 // Now pretend we're limited by backpressure in the pipeline. In this scenario | 269 // Now pretend we're limited by backpressure in the pipeline. In this scenario |
209 // case we are adding events but not sampling them. | 270 // case we are adding events but not sampling them. |
210 for (int i = 0; i < 10; i++) { | 271 for (int i = 0; i < 10; i++) { |
211 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 272 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
| 273 ASSERT_EQ(i >= 6, sampler.IsOverdueForSamplingAt(t)); |
212 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | 274 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); |
213 t += vsync; | 275 t += vsync; |
214 } | 276 } |
215 | 277 |
216 // Now suppose we can sample again. We should be back in the steady state. | 278 // Now suppose we can sample again. We should be back in the steady state. |
| 279 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); |
217 for (int i = 0; i < 100; i++) { | 280 for (int i = 0; i < 100; i++) { |
218 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 281 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
219 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 282 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
220 } | 283 } |
221 } | 284 } |
222 | 285 |
223 // Tests that changing the minimum capture period during usage results in the | 286 // Tests that changing the minimum capture period during usage results in the |
224 // desired behavior. | 287 // desired behavior. |
225 TEST(SmoothEventSamplerTest, Sample60HertzWithVariedCapturePeriods) { | 288 TEST(SmoothEventSamplerTest, Sample60HertzWithVariedCapturePeriods) { |
226 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; | 289 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; |
227 const base::TimeDelta one_to_one_period = vsync; | 290 const base::TimeDelta one_to_one_period = vsync; |
228 const base::TimeDelta two_to_one_period = vsync * 2; | 291 const base::TimeDelta two_to_one_period = vsync * 2; |
229 const base::TimeDelta two_and_three_to_one_period = | 292 const base::TimeDelta two_and_three_to_one_period = |
230 base::TimeDelta::FromSeconds(1) / 24; | 293 base::TimeDelta::FromSeconds(1) / 24; |
| 294 const int redundant_capture_goal = 1; |
231 | 295 |
232 SmoothEventSampler sampler(one_to_one_period); | 296 SmoothEventSampler sampler(one_to_one_period, redundant_capture_goal); |
233 base::TimeTicks t = InitialTestTimeTicks(); | 297 base::TimeTicks t = InitialTestTimeTicks(); |
234 | 298 |
| 299 TestRedundantCaptureStrategy(one_to_one_period, redundant_capture_goal, |
| 300 &sampler, &t); |
| 301 |
235 // With the capture rate at 60 Hz, we should capture every vsync. | 302 // With the capture rate at 60 Hz, we should capture every vsync. |
236 for (int i = 0; i < 100; i++) { | 303 for (int i = 0; i < 100; i++) { |
237 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 304 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
238 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 305 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
239 } | 306 } |
240 | 307 |
241 // Now change to the capture rate to 30 Hz, and we should capture every other | 308 // Now change to the capture rate to 30 Hz, and we should capture every other |
242 // vsync. | 309 // vsync. |
243 sampler.SetMinCapturePeriod(two_to_one_period); | 310 sampler.SetMinCapturePeriod(two_to_one_period); |
244 for (int i = 0; i < 100; i++) { | 311 for (int i = 0; i < 100; i++) { |
(...skipping 16 matching lines...) Expand all Loading... |
261 for (int i = 0; i < 100; i++) { | 328 for (int i = 0; i < 100; i++) { |
262 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | 329 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); |
263 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 330 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
264 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 331 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
265 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 332 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
266 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | 333 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); |
267 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | 334 SteadyStateSampleAndAdvance(vsync, &sampler, &t); |
268 } | 335 } |
269 } | 336 } |
270 | 337 |
| 338 TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) { |
| 339 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; |
| 340 const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1); |
| 341 |
| 342 SmoothEventSampler sampler(capture_period, 1); |
| 343 base::TimeTicks t = InitialTestTimeTicks(); |
| 344 |
| 345 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); |
| 346 sampler.RecordSample(); |
| 347 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t)) |
| 348 << "Sampled last event; should not be dirty."; |
| 349 t += overdue_period; |
| 350 |
| 351 // Now simulate 2 events with the same clock value. |
| 352 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); |
| 353 sampler.RecordSample(); |
| 354 ASSERT_FALSE(AddEventAndConsiderSampling(&sampler, t)) |
| 355 << "Two events at same time -- expected second not to be sampled."; |
| 356 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period)) |
| 357 << "Second event should dirty the capture state."; |
| 358 sampler.RecordSample(); |
| 359 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t + overdue_period)); |
| 360 } |
| 361 |
271 namespace { | 362 namespace { |
272 | 363 |
273 struct DataPoint { | 364 struct DataPoint { |
274 bool should_capture; | 365 bool should_capture; |
275 double increment_ms; | 366 double increment_ms; |
276 }; | 367 }; |
277 | 368 |
278 void ReplayCheckingSamplerDecisions(const DataPoint* data_points, | 369 void ReplayCheckingSamplerDecisions(const DataPoint* data_points, |
279 size_t num_data_points, | 370 size_t num_data_points, |
280 SmoothEventSampler* sampler) { | 371 SmoothEventSampler* sampler) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 {true, 33.44}, | 452 {true, 33.44}, |
362 {true, 50.161}, | 453 {true, 50.161}, |
363 {true, 33.44}, | 454 {true, 33.44}, |
364 {true, 50.161}, | 455 {true, 50.161}, |
365 {true, 33.44}, | 456 {true, 33.44}, |
366 {true, 83.601}, | 457 {true, 83.601}, |
367 {true, 16.72}, | 458 {true, 16.72}, |
368 {true, 33.44}, | 459 {true, 33.44}, |
369 {false, 0}}; | 460 {false, 0}}; |
370 | 461 |
371 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30); | 462 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); |
372 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); | 463 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); |
373 } | 464 } |
374 | 465 |
375 TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) { | 466 TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) { |
376 // Actual capturing of timing data: Initial instability as a 30 FPS video was | 467 // Actual capturing of timing data: Initial instability as a 30 FPS video was |
377 // started from a still screen, then followed by steady-state. Drawing | 468 // started from a still screen, then followed by steady-state. Drawing |
378 // framerate from the video rendering was a bit volatile, but averaged 30 FPS. | 469 // framerate from the video rendering was a bit volatile, but averaged 30 FPS. |
379 static const DataPoint data_points[] = {{true, 2407.69}, | 470 static const DataPoint data_points[] = {{true, 2407.69}, |
380 {true, 16.733}, | 471 {true, 16.733}, |
381 {true, 217.362}, | 472 {true, 217.362}, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 {false, 16.72}, | 561 {false, 16.72}, |
471 {true, 66.88}, | 562 {true, 66.88}, |
472 {true, 16.721}, | 563 {true, 16.721}, |
473 {true, 50.16}, | 564 {true, 50.16}, |
474 {true, 33.44}, | 565 {true, 33.44}, |
475 {true, 16.72}, | 566 {true, 16.72}, |
476 {true, 33.441}, | 567 {true, 33.441}, |
477 {true, 33.44}, | 568 {true, 33.44}, |
478 {true, 33.44}}; | 569 {true, 33.44}}; |
479 | 570 |
480 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30); | 571 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); |
481 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); | 572 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); |
482 } | 573 } |
483 | 574 |
484 TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) { | 575 TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) { |
485 // Actual capturing of timing data: WebGL Acquarium demo | 576 // Actual capturing of timing data: WebGL Acquarium demo |
486 // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran | 577 // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran |
487 // between 55-60 FPS in the steady-state. | 578 // between 55-60 FPS in the steady-state. |
488 static const DataPoint data_points[] = {{true, 16.72}, | 579 static const DataPoint data_points[] = {{true, 16.72}, |
489 {true, 16.72}, | 580 {true, 16.72}, |
490 {true, 4163.29}, | 581 {true, 4163.29}, |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 {true, 50.161}, | 694 {true, 50.161}, |
604 {false, 0}, | 695 {false, 0}, |
605 {true, 16.72}, | 696 {true, 16.72}, |
606 {true, 33.44}, | 697 {true, 33.44}, |
607 {false, 0}, | 698 {false, 0}, |
608 {true, 33.441}, | 699 {true, 33.441}, |
609 {false, 16.72}, | 700 {false, 16.72}, |
610 {true, 16.72}, | 701 {true, 16.72}, |
611 {true, 50.16}}; | 702 {true, 50.16}}; |
612 | 703 |
613 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30); | 704 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); |
614 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); | 705 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); |
615 } | 706 } |
616 | 707 |
617 } // namespace media | 708 } // namespace media |
OLD | NEW |