Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: media/capture/content/smooth_event_sampler_unittest.cc

Issue 2143903003: [WIP] Move media/capture to device/capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/capture/content/smooth_event_sampler.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include "base/macros.h"
11 #include "base/strings/stringprintf.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace media {
15
16 namespace {
17
18 bool AddEventAndConsiderSampling(SmoothEventSampler* sampler,
19 base::TimeTicks event_time) {
20 sampler->ConsiderPresentationEvent(event_time);
21 return sampler->ShouldSample();
22 }
23
24 void SteadyStateSampleAndAdvance(base::TimeDelta vsync,
25 SmoothEventSampler* sampler,
26 base::TimeTicks* t) {
27 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t));
28 ASSERT_TRUE(sampler->HasUnrecordedEvent());
29 sampler->RecordSample();
30 ASSERT_FALSE(sampler->HasUnrecordedEvent());
31 *t += vsync;
32 }
33
34 void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync,
35 SmoothEventSampler* sampler,
36 base::TimeTicks* t) {
37 ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t));
38 ASSERT_TRUE(sampler->HasUnrecordedEvent());
39 *t += vsync;
40 }
41
42 base::TimeTicks InitialTestTimeTicks() {
43 return base::TimeTicks() + base::TimeDelta::FromSeconds(1);
44 }
45
46
47 } // namespace
48
49 // 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains
50 // much more comprehensive before/after/edge-case scenarios than the others.
51 TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
52 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
53 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
54
55 SmoothEventSampler sampler(capture_period);
56 base::TimeTicks t = InitialTestTimeTicks();
57
58 // Steady state, we should capture every other vsync, indefinitely.
59 for (int i = 0; i < 100; i++) {
60 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
61 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
62 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
63 }
64
65 // Now pretend we're limited by backpressure in the pipeline. In this scenario
66 // case we are adding events but not sampling them.
67 for (int i = 0; i < 20; i++) {
68 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
69 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
70 ASSERT_TRUE(sampler.HasUnrecordedEvent());
71 t += vsync;
72 }
73
74 // Now suppose we can sample again. We should be back in the steady state,
75 // but at a different phase.
76 for (int i = 0; i < 100; i++) {
77 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
78 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
79 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
80 }
81 }
82
83 // 50Hz sampled at 30Hz should produce a sequence where some frames are skipped.
84 TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
85 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
86 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50;
87
88 SmoothEventSampler sampler(capture_period);
89 base::TimeTicks t = InitialTestTimeTicks();
90
91 // Steady state, we should capture 1st, 2nd and 4th frames out of every five
92 // frames, indefinitely.
93 for (int i = 0; i < 100; i++) {
94 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
95 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
96 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
97 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
98 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
99 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
100 }
101
102 // Now pretend we're limited by backpressure in the pipeline. In this scenario
103 // case we are adding events but not sampling them.
104 for (int i = 0; i < 20; i++) {
105 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
106 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
107 t += vsync;
108 }
109
110 // Now suppose we can sample again. We should be back in the steady state
111 // again.
112 for (int i = 0; i < 100; i++) {
113 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
114 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
115 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
116 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
117 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
118 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
119 }
120 }
121
122 // 75Hz sampled at 30Hz should produce a sequence where some frames are skipped.
123 TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) {
124 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
125 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75;
126
127 SmoothEventSampler sampler(capture_period);
128 base::TimeTicks t = InitialTestTimeTicks();
129
130 // Steady state, we should capture 1st and 3rd frames out of every five
131 // frames, indefinitely.
132 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
133 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
134 for (int i = 0; i < 100; i++) {
135 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
136 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
137 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
138 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
139 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
140 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
141 }
142
143 // Now pretend we're limited by backpressure in the pipeline. In this scenario
144 // case we are adding events but not sampling them.
145 for (int i = 0; i < 20; i++) {
146 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
147 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
148 t += vsync;
149 }
150
151 // 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.
153 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
154 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
155 for (int i = 0; i < 100; i++) {
156 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
157 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
158 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
159 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
160 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
161 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
162 }
163 }
164
165 // 30Hz sampled at 30Hz should produce 30Hz.
166 TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
167 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
168 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30;
169
170 SmoothEventSampler sampler(capture_period);
171 base::TimeTicks t = InitialTestTimeTicks();
172
173 // Steady state, we should capture every vsync, indefinitely.
174 for (int i = 0; i < 200; i++) {
175 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
176 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
177 }
178
179 // Now pretend we're limited by backpressure in the pipeline. In this scenario
180 // case we are adding events but not sampling them.
181 for (int i = 0; i < 10; i++) {
182 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
183 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
184 t += vsync;
185 }
186
187 // Now suppose we can sample again. We should be back in the steady state.
188 for (int i = 0; i < 100; i++) {
189 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
190 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
191 }
192 }
193
194 // 24Hz sampled at 30Hz should produce 24Hz.
195 TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) {
196 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
197 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24;
198
199 SmoothEventSampler sampler(capture_period);
200 base::TimeTicks t = InitialTestTimeTicks();
201
202 // Steady state, we should capture every vsync, indefinitely.
203 for (int i = 0; i < 200; i++) {
204 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
205 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
206 }
207
208 // Now pretend we're limited by backpressure in the pipeline. In this scenario
209 // case we are adding events but not sampling them.
210 for (int i = 0; i < 10; i++) {
211 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
212 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
213 t += vsync;
214 }
215
216 // Now suppose we can sample again. We should be back in the steady state.
217 for (int i = 0; i < 100; i++) {
218 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
219 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
220 }
221 }
222
223 // Tests that changing the minimum capture period during usage results in the
224 // desired behavior.
225 TEST(SmoothEventSamplerTest, Sample60HertzWithVariedCapturePeriods) {
226 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
227 const base::TimeDelta one_to_one_period = vsync;
228 const base::TimeDelta two_to_one_period = vsync * 2;
229 const base::TimeDelta two_and_three_to_one_period =
230 base::TimeDelta::FromSeconds(1) / 24;
231
232 SmoothEventSampler sampler(one_to_one_period);
233 base::TimeTicks t = InitialTestTimeTicks();
234
235 // With the capture rate at 60 Hz, we should capture every vsync.
236 for (int i = 0; i < 100; i++) {
237 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
238 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
239 }
240
241 // Now change to the capture rate to 30 Hz, and we should capture every other
242 // vsync.
243 sampler.SetMinCapturePeriod(two_to_one_period);
244 for (int i = 0; i < 100; i++) {
245 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
246 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
247 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
248 }
249
250 // Now change the capture rate back to 60 Hz, and we should capture every
251 // vsync again.
252 sampler.SetMinCapturePeriod(one_to_one_period);
253 for (int i = 0; i < 100; i++) {
254 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
255 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
256 }
257
258 // Now change the capture rate to 24 Hz, and we should capture with a 2-3-2-3
259 // cadence.
260 sampler.SetMinCapturePeriod(two_and_three_to_one_period);
261 for (int i = 0; i < 100; i++) {
262 SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
263 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
264 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
265 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
266 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
267 SteadyStateSampleAndAdvance(vsync, &sampler, &t);
268 }
269 }
270
271 namespace {
272
273 struct DataPoint {
274 bool should_capture;
275 double increment_ms;
276 };
277
278 void ReplayCheckingSamplerDecisions(const DataPoint* data_points,
279 size_t num_data_points,
280 SmoothEventSampler* sampler) {
281 base::TimeTicks t = InitialTestTimeTicks();
282 for (size_t i = 0; i < num_data_points; ++i) {
283 t += base::TimeDelta::FromMicroseconds(
284 static_cast<int64_t>(data_points[i].increment_ms * 1000));
285 ASSERT_EQ(data_points[i].should_capture,
286 AddEventAndConsiderSampling(sampler, t))
287 << "at data_points[" << i << ']';
288 if (data_points[i].should_capture)
289 sampler->RecordSample();
290 }
291 }
292
293 } // namespace
294
295 TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) {
296 // Actual capturing of timing data: Initial instability as a 24 FPS video was
297 // started from a still screen, then clearly followed by steady-state.
298 static const DataPoint data_points[] = {{true, 1437.93},
299 {true, 150.484},
300 {true, 217.362},
301 {true, 50.161},
302 {true, 33.44},
303 {false, 0},
304 {true, 16.721},
305 {true, 66.88},
306 {true, 50.161},
307 {false, 0},
308 {false, 0},
309 {true, 50.16},
310 {true, 33.441},
311 {true, 16.72},
312 {false, 16.72},
313 {true, 117.041},
314 {true, 16.72},
315 {false, 16.72},
316 {true, 50.161},
317 {true, 50.16},
318 {true, 33.441},
319 {true, 33.44},
320 {true, 33.44},
321 {true, 16.72},
322 {false, 0},
323 {true, 50.161},
324 {false, 0},
325 {true, 33.44},
326 {true, 16.72},
327 {false, 16.721},
328 {true, 66.881},
329 {false, 0},
330 {true, 33.441},
331 {true, 16.72},
332 {true, 50.16},
333 {true, 16.72},
334 {false, 16.721},
335 {true, 50.161},
336 {true, 50.16},
337 {false, 0},
338 {true, 33.441},
339 {true, 50.337},
340 {true, 50.183},
341 {true, 16.722},
342 {true, 50.161},
343 {true, 33.441},
344 {true, 50.16},
345 {true, 33.441},
346 {true, 50.16},
347 {true, 33.441},
348 {true, 50.16},
349 {true, 33.44},
350 {true, 50.161},
351 {true, 50.16},
352 {true, 33.44},
353 {true, 33.441},
354 {true, 50.16},
355 {true, 50.161},
356 {true, 33.44},
357 {true, 33.441},
358 {true, 50.16},
359 {true, 33.44},
360 {true, 50.161},
361 {true, 33.44},
362 {true, 50.161},
363 {true, 33.44},
364 {true, 50.161},
365 {true, 33.44},
366 {true, 83.601},
367 {true, 16.72},
368 {true, 33.44},
369 {false, 0}};
370
371 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30);
372 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
373 }
374
375 TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) {
376 // 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
378 // framerate from the video rendering was a bit volatile, but averaged 30 FPS.
379 static const DataPoint data_points[] = {{true, 2407.69},
380 {true, 16.733},
381 {true, 217.362},
382 {true, 33.441},
383 {true, 33.44},
384 {true, 33.44},
385 {true, 33.441},
386 {true, 33.44},
387 {true, 33.44},
388 {true, 33.441},
389 {true, 33.44},
390 {true, 33.44},
391 {true, 16.721},
392 {true, 33.44},
393 {false, 0},
394 {true, 50.161},
395 {true, 50.16},
396 {false, 0},
397 {true, 50.161},
398 {true, 33.44},
399 {true, 16.72},
400 {false, 0},
401 {false, 16.72},
402 {true, 66.881},
403 {false, 0},
404 {true, 33.44},
405 {true, 16.72},
406 {true, 50.161},
407 {false, 0},
408 {true, 33.538},
409 {true, 33.526},
410 {true, 33.447},
411 {true, 33.445},
412 {true, 33.441},
413 {true, 16.721},
414 {true, 33.44},
415 {true, 33.44},
416 {true, 50.161},
417 {true, 16.72},
418 {true, 33.44},
419 {true, 33.441},
420 {true, 33.44},
421 {false, 0},
422 {false, 16.72},
423 {true, 66.881},
424 {true, 16.72},
425 {false, 16.72},
426 {true, 50.16},
427 {true, 33.441},
428 {true, 33.44},
429 {true, 33.44},
430 {true, 33.44},
431 {true, 33.441},
432 {true, 33.44},
433 {true, 50.161},
434 {false, 0},
435 {true, 33.44},
436 {true, 33.44},
437 {true, 50.161},
438 {true, 16.72},
439 {true, 33.44},
440 {true, 33.441},
441 {false, 0},
442 {true, 66.88},
443 {true, 33.441},
444 {true, 33.44},
445 {true, 33.44},
446 {false, 0},
447 {true, 33.441},
448 {true, 33.44},
449 {true, 33.44},
450 {false, 0},
451 {true, 16.72},
452 {true, 50.161},
453 {false, 0},
454 {true, 50.16},
455 {false, 0.001},
456 {true, 16.721},
457 {true, 66.88},
458 {true, 33.44},
459 {true, 33.441},
460 {true, 33.44},
461 {true, 50.161},
462 {true, 16.72},
463 {false, 0},
464 {true, 33.44},
465 {false, 16.72},
466 {true, 66.881},
467 {true, 33.44},
468 {true, 16.72},
469 {true, 33.441},
470 {false, 16.72},
471 {true, 66.88},
472 {true, 16.721},
473 {true, 50.16},
474 {true, 33.44},
475 {true, 16.72},
476 {true, 33.441},
477 {true, 33.44},
478 {true, 33.44}};
479
480 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30);
481 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
482 }
483
484 TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) {
485 // Actual capturing of timing data: WebGL Acquarium demo
486 // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran
487 // between 55-60 FPS in the steady-state.
488 static const DataPoint data_points[] = {{true, 16.72},
489 {true, 16.72},
490 {true, 4163.29},
491 {true, 50.193},
492 {true, 117.041},
493 {true, 50.161},
494 {true, 50.16},
495 {true, 33.441},
496 {true, 50.16},
497 {true, 33.44},
498 {false, 0},
499 {false, 0},
500 {true, 50.161},
501 {true, 83.601},
502 {true, 50.16},
503 {true, 16.72},
504 {true, 33.441},
505 {false, 16.72},
506 {true, 50.16},
507 {true, 16.72},
508 {false, 0.001},
509 {true, 33.441},
510 {false, 16.72},
511 {true, 16.72},
512 {true, 50.16},
513 {false, 0},
514 {true, 16.72},
515 {true, 33.441},
516 {false, 0},
517 {true, 33.44},
518 {false, 16.72},
519 {true, 16.72},
520 {true, 50.161},
521 {false, 0},
522 {true, 16.72},
523 {true, 33.44},
524 {false, 0},
525 {true, 33.44},
526 {false, 16.721},
527 {true, 16.721},
528 {true, 50.161},
529 {false, 0},
530 {true, 16.72},
531 {true, 33.441},
532 {false, 0},
533 {true, 33.44},
534 {false, 16.72},
535 {true, 33.44},
536 {false, 0},
537 {true, 16.721},
538 {true, 50.161},
539 {false, 0},
540 {true, 33.44},
541 {false, 0},
542 {true, 16.72},
543 {true, 33.441},
544 {false, 0},
545 {true, 33.44},
546 {false, 16.72},
547 {true, 16.72},
548 {true, 50.16},
549 {false, 0},
550 {true, 16.721},
551 {true, 33.44},
552 {false, 0},
553 {true, 33.44},
554 {false, 16.721},
555 {true, 16.721},
556 {true, 50.161},
557 {false, 0},
558 {true, 16.72},
559 {true, 33.44},
560 {false, 0},
561 {true, 33.441},
562 {false, 16.72},
563 {true, 16.72},
564 {true, 50.16},
565 {false, 0},
566 {true, 16.72},
567 {true, 33.441},
568 {true, 33.44},
569 {false, 0},
570 {true, 33.44},
571 {true, 33.441},
572 {false, 0},
573 {true, 33.44},
574 {true, 33.441},
575 {false, 0},
576 {true, 33.44},
577 {false, 0},
578 {true, 33.44},
579 {false, 16.72},
580 {true, 16.721},
581 {true, 50.161},
582 {false, 0},
583 {true, 16.72},
584 {true, 33.44},
585 {true, 33.441},
586 {false, 0},
587 {true, 33.44},
588 {true, 33.44},
589 {false, 0},
590 {true, 33.441},
591 {false, 16.72},
592 {true, 16.72},
593 {true, 50.16},
594 {false, 0},
595 {true, 16.72},
596 {true, 33.441},
597 {false, 0},
598 {true, 33.44},
599 {false, 16.72},
600 {true, 33.44},
601 {false, 0},
602 {true, 16.721},
603 {true, 50.161},
604 {false, 0},
605 {true, 16.72},
606 {true, 33.44},
607 {false, 0},
608 {true, 33.441},
609 {false, 16.72},
610 {true, 16.72},
611 {true, 50.16}};
612
613 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30);
614 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
615 }
616
617 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/content/smooth_event_sampler.cc ('k') | media/capture/content/thread_safe_capture_oracle.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698